Files
element-x-ios/ElementX/Sources/Screens/ManageRoomMemberSheet/ManageRoomMemberSheetModels.swift
T
Danny 1a72a4e17b Allow tapping the avatar in the room member bottom sheet to view it fullscreen (#5989)
* Extract a shared helper for loading a media preview

The four screens that show a fullscreen avatar each had their own copy of the same
load-and-wrap logic. Move it to MediaPreviewItem.load, with the mime type as a
parameter defaulting to JPEG, and leave each screen's loading indicator where it is.

Signed-off-by: Daniel Anderson <daniel.anderson@toptal.com>

* Only dismiss a QuickLook preview that is still presented

UIKit forwards dismiss() up the presentation chain when the receiver has nothing
presented, so dismissing the avatar view was dismissing the profile details sheet
also.

Signed-off-by: Daniel Anderson <daniel.anderson@toptal.com>

* Allow tapping the avatar in the room member bottom sheet to view it fullscreen

Signed-off-by: Daniel Anderson <daniel.anderson@toptal.com>

---------

Signed-off-by: Daniel Anderson <daniel.anderson@toptal.com>
2026-08-07 13:11:40 +01:00

96 lines
2.6 KiB
Swift

//
// Copyright 2025 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import Foundation
enum ManageRoomMemberSheetViewModelAction: Equatable {
case dismiss(shouldShowDetails: Bool)
}
struct ManageRoomMemberSheetViewState: BindableState {
let memberDetails: ManageRoomMemberDetails
let permissions: ManageRoomMemberPermissions
var isBanUnbanDisabled: Bool {
// This is a best effort check, if we haven't fetched the member yet we assume we can peform the action
guard case let .memberDetails(member) = memberDetails else {
return false
}
return permissions.ownPowerLevel <= member.powerLevel
}
var isKickDisabled: Bool {
// This is a best effort check, if we haven't fetched the member yet we assume we can peform the action
guard case let .memberDetails(member) = memberDetails else {
return false
}
return !member.isActive || permissions.ownPowerLevel <= member.powerLevel
}
var isMemberBanned: Bool {
// This is a best effort check, if we haven't fetched the member yet we assume the member is not banned
guard case let .memberDetails(member) = memberDetails else {
return false
}
return member.isBanned
}
var bindings = ManageRoomMemberSheetViewStateBindings()
}
struct ManageRoomMemberSheetViewStateBindings {
var alertInfo: AlertInfo<ManageRoomMemberSheetViewAlertType>?
var mediaPreviewItem: MediaPreviewItem?
}
enum ManageRoomMemberSheetViewAlertType {
case kick
case ban
case unban
}
enum ManageRoomMemberSheetViewAction {
case kick
case ban
case unban
case displayDetails
case displayAvatar(URL)
}
enum ManageRoomMemberDetails {
case memberDetails(roomMember: RoomMemberDetails)
case loadingMemberDetails(sender: TimelineItemSender)
var id: String {
switch self {
case let .memberDetails(roomMember):
roomMember.id
case let .loadingMemberDetails(sender):
sender.id
}
}
var name: String? {
switch self {
case let .memberDetails(roomMember):
roomMember.name
case let .loadingMemberDetails(sender):
sender.displayName
}
}
}
struct ManageRoomMemberPermissions {
let canKick: Bool
let canBan: Bool
let ownPowerLevel: RoomPowerLevel
}