Files
element-x-ios/ElementX/Sources/Screens/ManageRoomMemberSheet/View/ManageRoomMemberSheetView.swift
T
Michael ff5dcb040d Replace the ServiceLocator with direct dependency injection (#5548)
Removes the ServiceLocator singleton and instead directly injects the dependencies it was holding for more control over instantiation of the various component subtrees and better visibility over how they're being used.
2026-05-14 09:45:49 +03:00

127 lines
6.0 KiB
Swift

//
// Copyright 2025 Element Creations Ltd.
// Copyright 2024-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 Compound
import SwiftUI
struct ManageRoomMemberSheetView: View {
@Bindable var context: ManageRoomMemberSheetViewModelType.Context
var body: some View {
Form {
switch context.viewState.memberDetails {
case .memberDetails(let member):
AvatarHeaderView(member: member,
avatarSize: .user(on: .memberDetails),
mediaProvider: context.mediaProvider) {
EmptyView()
}
case .loadingMemberDetails(let sender):
AvatarHeaderView(sender: sender,
avatarSize: .user(on: .memberDetails),
mediaProvider: context.mediaProvider) {
EmptyView()
}
}
Section {
ListRow(label: .default(title: L10n.screenBottomSheetManageRoomMemberMemberUserInfo,
icon: \.userProfileSolid),
kind: .navigationLink {
context.send(viewAction: .displayDetails)
})
.accessibilityIdentifier(A11yIdentifiers.manageRoomMemberSheet.viewProfile)
}
Section {
if context.viewState.permissions.canKick, !context.viewState.isMemberBanned {
ListRow(label: .default(title: L10n.screenBottomSheetManageRoomMemberRemove,
icon: \.close,
role: .destructive),
kind: .button {
context.send(viewAction: .kick)
})
.disabled(context.viewState.isKickDisabled)
}
if context.viewState.permissions.canBan {
if !context.viewState.isMemberBanned {
ListRow(label: .default(title: L10n.screenBottomSheetManageRoomMemberBan,
icon: \.block,
role: .destructive),
kind: .button {
context.send(viewAction: .ban)
})
.disabled(context.viewState.isBanUnbanDisabled)
// Kick permission is also needed to unban
} else if context.viewState.permissions.canKick {
ListRow(label: .default(title: L10n.screenBottomSheetManageRoomMemberUnban,
icon: \.restart,
role: .destructive),
kind: .button {
context.send(viewAction: .unban)
})
.disabled(context.viewState.isBanUnbanDisabled)
}
}
}
}
.compoundList()
.scrollBounceBehavior(.basedOnSize)
.presentationDragIndicator(.visible)
.presentationDetents([.large, .fraction(0.67)]) // Maybe find a way to use the ideal height somehow?
.alert(item: $context.alertInfo)
}
}
struct ManageRoomMemberSheetView_Previews: PreviewProvider, TestablePreview {
static let allActionsViewModel = ManageRoomMemberSheetViewModel.mock()
static let allActionsDisabledViewModel = ManageRoomMemberSheetViewModel.mock(powerLevel: .init(value: 0))
static let kickOnlyViewModel = ManageRoomMemberSheetViewModel.mock(canBan: false)
static let banOnlyViewModel = ManageRoomMemberSheetViewModel.mock(canKick: false)
static let unbanOnlyViewModel = ManageRoomMemberSheetViewModel.mock(canKick: true, memberIsBanned: true)
static var previews: some View {
ManageRoomMemberSheetView(context: allActionsViewModel.context)
.previewDisplayName("All Actions")
ManageRoomMemberSheetView(context: allActionsDisabledViewModel.context)
.previewDisplayName("All Actions Disabled")
ManageRoomMemberSheetView(context: kickOnlyViewModel.context)
.previewDisplayName("Kick Only")
ManageRoomMemberSheetView(context: banOnlyViewModel.context)
.previewDisplayName("Ban Only")
ManageRoomMemberSheetView(context: unbanOnlyViewModel.context)
.previewDisplayName("Unban Only")
}
}
private extension ManageRoomMemberSheetViewModel {
static func mock(canKick: Bool = true,
canBan: Bool = true,
memberIsBanned: Bool = false,
powerLevel: RoomPowerLevel = .init(value: 100)) -> ManageRoomMemberSheetViewModel {
let member = if memberIsBanned {
RoomMemberDetails(withProxy: RoomMemberProxyMock.mockBanned[0])
} else {
RoomMemberDetails(withProxy: RoomMemberProxyMock.mockDan)
}
return ManageRoomMemberSheetViewModel(memberDetails: .memberDetails(roomMember: member),
permissions: .init(canKick: canKick,
canBan: canBan,
ownPowerLevel: powerLevel),
roomProxy: JoinedRoomProxyMock(.init()),
userIndicatorController: UserIndicatorControllerMock(),
analyticsService: .mock(),
mediaProvider: MediaProviderMock(configuration: .init()))
}
}