mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Always open manage member sheet (#4110)
* always open manage member sheet * Update ElementX/Sources/Screens/ManageRoomMemberSheet/ManageRoomMemberSheetModels.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * Update ElementX/Sources/Screens/ManageRoomMemberSheet/ManageRoomMemberSheetModels.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * pr suggestions and handled the buttons actions correctly * Update ElementX/Sources/Screens/ManageRoomMemberSheet/View/ManageRoomMemberSheetView.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * fixed some compilation errors * added some documentation * using a struct instead of a protocol * using arguments instead of a struct --------- Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com>
This commit is contained in:
@@ -10,9 +10,35 @@ enum ManageRoomMemberSheetViewModelAction: Equatable {
|
||||
}
|
||||
|
||||
struct ManageRoomMemberSheetViewState: BindableState {
|
||||
let member: RoomMemberDetails
|
||||
let canKick: Bool
|
||||
let canBan: Bool
|
||||
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()
|
||||
}
|
||||
@@ -24,10 +50,41 @@ struct ManageRoomMemberSheetViewStateBindings {
|
||||
enum ManageRoomMemberSheetViewAlertType {
|
||||
case kick
|
||||
case ban
|
||||
case unban
|
||||
}
|
||||
|
||||
enum ManageRoomMemberSheetViewAction {
|
||||
case kick
|
||||
case ban
|
||||
case unban
|
||||
case displayDetails
|
||||
}
|
||||
|
||||
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: Int
|
||||
}
|
||||
|
||||
+39
-14
@@ -22,9 +22,8 @@ class ManageRoomMemberSheetViewModel: ManageRoomMemberSheetViewModelType, Manage
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(member: RoomMemberDetails,
|
||||
canKick: Bool,
|
||||
canBan: Bool,
|
||||
init(memberDetails: ManageRoomMemberDetails,
|
||||
permissions: ManageRoomMemberPermissions,
|
||||
roomProxy: JoinedRoomProxyProtocol,
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
analyticsService: AnalyticsService,
|
||||
@@ -32,7 +31,7 @@ class ManageRoomMemberSheetViewModel: ManageRoomMemberSheetViewModelType, Manage
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.roomProxy = roomProxy
|
||||
self.analyticsService = analyticsService
|
||||
super.init(initialViewState: .init(member: member, canKick: canKick, canBan: canBan), mediaProvider: mediaProvider)
|
||||
super.init(initialViewState: .init(memberDetails: memberDetails, permissions: permissions), mediaProvider: mediaProvider)
|
||||
}
|
||||
|
||||
override func process(viewAction: ManageRoomMemberSheetViewAction) {
|
||||
@@ -43,11 +42,15 @@ class ManageRoomMemberSheetViewModel: ManageRoomMemberSheetViewModelType, Manage
|
||||
displayAlert(.ban)
|
||||
case .displayDetails:
|
||||
actionsSubject.send(.dismiss(shouldShowDetails: true))
|
||||
case .unban:
|
||||
displayAlert(.unban)
|
||||
}
|
||||
}
|
||||
|
||||
private func displayAlert(_ alertType: ManageRoomMemberSheetViewAlertType) {
|
||||
let member = state.member
|
||||
let memberID = state.memberDetails.id
|
||||
let memberName = state.memberDetails.name
|
||||
|
||||
var reason: String?
|
||||
let binding: Binding<String> = .init(get: { reason ?? "" },
|
||||
set: { reason = $0.isBlank ? nil : $0 })
|
||||
@@ -57,7 +60,7 @@ class ManageRoomMemberSheetViewModel: ManageRoomMemberSheetViewModelType, Manage
|
||||
title: L10n.screenBottomSheetManageRoomMemberKickMemberConfirmationTitle,
|
||||
message: L10n.screenBottomSheetManageRoomMemberKickMemberConfirmationDescription,
|
||||
primaryButton: .init(title: L10n.actionCancel, role: .cancel) { },
|
||||
secondaryButton: .init(title: L10n.screenBottomSheetManageRoomMemberKickMemberConfirmationAction) { [weak self] in Task { await self?.kickMember(member, reason: reason) } },
|
||||
secondaryButton: .init(title: L10n.screenBottomSheetManageRoomMemberKickMemberConfirmationAction) { [weak self] in Task { await self?.kickMember(id: memberID, name: memberName, reason: reason) } },
|
||||
textFields: [.init(placeholder: L10n.commonReason,
|
||||
text: binding,
|
||||
autoCapitalization: .sentences,
|
||||
@@ -67,19 +70,25 @@ class ManageRoomMemberSheetViewModel: ManageRoomMemberSheetViewModelType, Manage
|
||||
title: L10n.screenBottomSheetManageRoomMemberBanMemberConfirmationTitle,
|
||||
message: L10n.screenBottomSheetManageRoomMemberBanMemberConfirmationDescription,
|
||||
primaryButton: .init(title: L10n.actionCancel, role: .cancel) { },
|
||||
secondaryButton: .init(title: L10n.screenBottomSheetManageRoomMemberBanMemberConfirmationAction) { [weak self] in Task { await self?.banMember(member, reason: reason) } },
|
||||
secondaryButton: .init(title: L10n.screenBottomSheetManageRoomMemberBanMemberConfirmationAction) { [weak self] in Task { await self?.banMember(id: memberID, name: memberName, reason: reason) } },
|
||||
textFields: [.init(placeholder: L10n.commonReason,
|
||||
text: binding,
|
||||
autoCapitalization: .sentences,
|
||||
autoCorrectionDisabled: false)])
|
||||
case .unban:
|
||||
state.bindings.alertInfo = .init(id: alertType,
|
||||
title: L10n.screenBottomSheetManageRoomMemberUnbanMemberConfirmationTitle,
|
||||
message: L10n.screenBottomSheetManageRoomMemberUnbanMemberConfirmationDescription,
|
||||
primaryButton: .init(title: L10n.actionCancel, role: .cancel) { },
|
||||
secondaryButton: .init(title: L10n.screenBottomSheetManageRoomMemberUnbanMemberConfirmationAction) { [weak self] in Task { await self?.unbanMember(id: memberID, name: memberName) } })
|
||||
}
|
||||
}
|
||||
|
||||
private func kickMember(_ member: RoomMemberDetails, reason: String?) async {
|
||||
let indicatorTitle = L10n.screenBottomSheetManageRoomMemberRemovingUser(member.name ?? member.id)
|
||||
private func kickMember(id: String, name: String?, reason: String?) async {
|
||||
let indicatorTitle = L10n.screenBottomSheetManageRoomMemberRemovingUser(name ?? id)
|
||||
showManageMemberIndicator(title: indicatorTitle)
|
||||
|
||||
switch await roomProxy.kickUser(member.id, reason: reason) {
|
||||
switch await roomProxy.kickUser(id, reason: reason) {
|
||||
case .success:
|
||||
hideManageMemberIndicator(title: indicatorTitle)
|
||||
analyticsService.trackRoomModeration(action: .KickMember, role: nil)
|
||||
@@ -89,11 +98,11 @@ class ManageRoomMemberSheetViewModel: ManageRoomMemberSheetViewModelType, Manage
|
||||
}
|
||||
}
|
||||
|
||||
private func banMember(_ member: RoomMemberDetails, reason: String?) async {
|
||||
let indicatorTitle = L10n.screenBottomSheetManageRoomMemberBanningUser(member.name ?? member.id)
|
||||
private func banMember(id: String, name: String?, reason: String?) async {
|
||||
let indicatorTitle = L10n.screenBottomSheetManageRoomMemberBanningUser(name ?? id)
|
||||
showManageMemberIndicator(title: indicatorTitle)
|
||||
|
||||
switch await roomProxy.banUser(member.id, reason: reason) {
|
||||
switch await roomProxy.banUser(id, reason: reason) {
|
||||
case .success:
|
||||
hideManageMemberIndicator(title: indicatorTitle)
|
||||
analyticsService.trackRoomModeration(action: .BanMember, role: nil)
|
||||
@@ -103,6 +112,20 @@ class ManageRoomMemberSheetViewModel: ManageRoomMemberSheetViewModelType, Manage
|
||||
}
|
||||
}
|
||||
|
||||
private func unbanMember(id: String, name: String?) async {
|
||||
let indicatorTitle = L10n.screenBottomSheetManageRoomMemberUnbanningUser(name ?? id)
|
||||
showManageMemberIndicator(title: indicatorTitle)
|
||||
|
||||
switch await roomProxy.unbanUser(id) {
|
||||
case .success:
|
||||
hideManageMemberIndicator(title: indicatorTitle)
|
||||
analyticsService.trackRoomModeration(action: .UnbanMember, role: nil)
|
||||
actionsSubject.send(.dismiss(shouldShowDetails: false))
|
||||
case .failure:
|
||||
showManageMemberFailure(title: indicatorTitle)
|
||||
}
|
||||
}
|
||||
|
||||
private func showManageMemberIndicator(title: String) {
|
||||
userIndicatorController.submitIndicator(UserIndicator(id: title,
|
||||
type: .toast(progress: .indeterminate),
|
||||
@@ -121,5 +144,7 @@ class ManageRoomMemberSheetViewModel: ManageRoomMemberSheetViewModelType, Manage
|
||||
}
|
||||
|
||||
extension ManageRoomMemberSheetViewModel: Identifiable {
|
||||
var id: String { state.member.id }
|
||||
var id: String {
|
||||
state.memberDetails.id
|
||||
}
|
||||
}
|
||||
|
||||
+44
-14
@@ -13,10 +13,19 @@ struct ManageRoomMemberSheetView: View {
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
AvatarHeaderView(member: context.viewState.member,
|
||||
avatarSize: .user(on: .memberDetails),
|
||||
mediaProvider: context.mediaProvider) {
|
||||
EmptyView()
|
||||
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 {
|
||||
@@ -28,22 +37,28 @@ struct ManageRoomMemberSheetView: View {
|
||||
}
|
||||
|
||||
Section {
|
||||
if context.viewState.canKick {
|
||||
if context.viewState.permissions.canKick {
|
||||
ListRow(label: .default(title: L10n.screenBottomSheetManageRoomMemberRemove,
|
||||
icon: \.close,
|
||||
role: .destructive),
|
||||
kind: .button {
|
||||
context.send(viewAction: .kick)
|
||||
})
|
||||
.disabled(context.viewState.isKickDisabled)
|
||||
}
|
||||
|
||||
if context.viewState.canBan {
|
||||
ListRow(label: .default(title: L10n.screenBottomSheetManageRoomMemberBan,
|
||||
icon: \.block,
|
||||
if context.viewState.permissions.canBan {
|
||||
let title = context.viewState.isMemberBanned ? L10n.screenBottomSheetManageRoomMemberUnban : L10n.screenBottomSheetManageRoomMemberBan
|
||||
let icon: KeyPath<CompoundIcons, Image> = context.viewState.isMemberBanned ? \.restart : \.block
|
||||
let action: ManageRoomMemberSheetViewAction = context.viewState.isMemberBanned ? .unban : .ban
|
||||
|
||||
ListRow(label: .default(title: title,
|
||||
icon: icon,
|
||||
role: .destructive),
|
||||
kind: .button {
|
||||
context.send(viewAction: .ban)
|
||||
context.send(viewAction: action)
|
||||
})
|
||||
.disabled(context.viewState.isBanUnbanDisabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,27 +73,42 @@ struct ManageRoomMemberSheetView: View {
|
||||
struct ManageRoomMemberSheetView_Previews: PreviewProvider, TestablePreview {
|
||||
static let allActionsViewModel = ManageRoomMemberSheetViewModel.mock()
|
||||
|
||||
static let allActionsDisabledViewModel = ManageRoomMemberSheetViewModel.mock(powerLevel: 0)
|
||||
|
||||
static let kickOnlyViewModel = ManageRoomMemberSheetViewModel.mock(canBan: false)
|
||||
|
||||
static let banOnlyViewModel = ManageRoomMemberSheetViewModel.mock(canKick: false)
|
||||
|
||||
static let unbanOnlyViewModel = ManageRoomMemberSheetViewModel.mock(canKick: false, 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) -> ManageRoomMemberSheetViewModel {
|
||||
let member = RoomMemberDetails(withProxy: RoomMemberProxyMock.mockDan)
|
||||
return ManageRoomMemberSheetViewModel(member: member,
|
||||
canKick: canKick,
|
||||
canBan: canBan,
|
||||
canBan: Bool = true,
|
||||
memberIsBanned: Bool = false,
|
||||
powerLevel: Int = 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: ServiceLocator.shared.analytics,
|
||||
|
||||
@@ -89,7 +89,6 @@ struct RoomMembersListScreenViewStateBindings {
|
||||
|
||||
enum RoomMembersListScreenViewAction {
|
||||
case selectMember(RoomMemberDetails)
|
||||
case unbanMember(RoomMemberDetails)
|
||||
case invite
|
||||
}
|
||||
|
||||
|
||||
+18
-35
@@ -51,8 +51,6 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
||||
switch viewAction {
|
||||
case .selectMember(let member):
|
||||
selectMember(member)
|
||||
case .unbanMember(let member):
|
||||
Task { await unbanMember(member) }
|
||||
case .invite:
|
||||
actionsSubject.send(.invite)
|
||||
}
|
||||
@@ -144,46 +142,31 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
||||
}
|
||||
|
||||
private func selectMember(_ member: RoomMemberDetails) {
|
||||
guard let currentUserProxy,
|
||||
currentUserProxy.powerLevel > member.powerLevel else {
|
||||
guard currentUserProxy?.userID != member.id else {
|
||||
showMemberDetails(member)
|
||||
return
|
||||
}
|
||||
|
||||
if member.isBanned { // No need to check canBan here, banned users are only shown when it is true.
|
||||
state.bindings.alertInfo = AlertInfo(id: .unbanConfirmation(member),
|
||||
title: L10n.screenRoomMemberListManageMemberUnbanTitle,
|
||||
message: L10n.screenRoomMemberListManageMemberUnbanMessage,
|
||||
primaryButton: .init(title: L10n.screenRoomMemberListManageMemberUnbanAction) { [weak self] in
|
||||
self?.context.send(viewAction: .unbanMember(member))
|
||||
},
|
||||
secondaryButton: .init(title: L10n.actionCancel, role: .cancel) { })
|
||||
return
|
||||
}
|
||||
|
||||
if state.canKickUsers || state.canBanUsers {
|
||||
let manageMemeberViewModel = ManageRoomMemberSheetViewModel(member: member,
|
||||
canKick: state.canKickUsers,
|
||||
canBan: state.canBanUsers,
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: userIndicatorController,
|
||||
analyticsService: analytics,
|
||||
mediaProvider: mediaProvider)
|
||||
manageMemeberViewModel.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .dismiss(let shouldShowDetails):
|
||||
state.bindings.manageMemeberViewModel = nil
|
||||
if shouldShowDetails {
|
||||
showMemberDetails(member)
|
||||
}
|
||||
let manageMemeberViewModel = ManageRoomMemberSheetViewModel(memberDetails: .memberDetails(roomMember: member),
|
||||
permissions: .init(canKick: state.canKickUsers,
|
||||
canBan: state.canBanUsers,
|
||||
ownPowerLevel: currentUserProxy?.powerLevel ?? 0),
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: userIndicatorController,
|
||||
analyticsService: analytics,
|
||||
mediaProvider: mediaProvider)
|
||||
manageMemeberViewModel.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .dismiss(let shouldShowDetails):
|
||||
state.bindings.manageMemeberViewModel = nil
|
||||
if shouldShowDetails {
|
||||
showMemberDetails(member)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
state.bindings.manageMemeberViewModel = manageMemeberViewModel
|
||||
} else {
|
||||
showMemberDetails(member)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
state.bindings.manageMemeberViewModel = manageMemeberViewModel
|
||||
}
|
||||
|
||||
private func showMemberDetails(_ member: RoomMemberDetails) {
|
||||
|
||||
@@ -55,7 +55,7 @@ enum TimelineViewAction {
|
||||
case displayTimelineItemMenu(itemID: TimelineItemIdentifier)
|
||||
case handleTimelineItemMenuAction(itemID: TimelineItemIdentifier, action: TimelineItemMenuAction)
|
||||
|
||||
case tappedOnSenderDetails(userID: String)
|
||||
case tappedOnSenderDetails(sender: TimelineItemSender)
|
||||
case displayReactionSummary(itemID: TimelineItemIdentifier, key: String)
|
||||
case displayEmojiPicker(itemID: TimelineItemIdentifier)
|
||||
case displayReadReceipts(itemID: TimelineItemIdentifier)
|
||||
|
||||
@@ -183,8 +183,8 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
||||
timelineInteractionHandler.displayTimelineItemActionMenu(for: itemID)
|
||||
case .handleTimelineItemMenuAction(let itemID, let action):
|
||||
timelineInteractionHandler.handleTimelineItemMenuAction(action, itemID: itemID)
|
||||
case .tappedOnSenderDetails(let userID):
|
||||
handleTappedOnSenderDetails(userID: userID)
|
||||
case .tappedOnSenderDetails(let sender):
|
||||
handleTappedOnSenderDetails(sender: sender)
|
||||
case .displayEmojiPicker(let itemID):
|
||||
timelineInteractionHandler.displayEmojiPicker(for: itemID)
|
||||
case .displayReactionSummary(let itemID, let key):
|
||||
@@ -271,39 +271,34 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func handleTappedOnSenderDetails(userID: String) {
|
||||
// We also need to make sure the user is in the joined state, otherwise we just show the details.
|
||||
guard let memberProxy = roomProxy.membersPublisher.value.first(where: { $0.userID == userID && $0.membership == .join }),
|
||||
let currentUserProxy,
|
||||
currentUserProxy.powerLevel > memberProxy.powerLevel else {
|
||||
actionsSubject.send(.displaySenderDetails(userID: userID))
|
||||
return
|
||||
private func handleTappedOnSenderDetails(sender: TimelineItemSender) {
|
||||
let memberDetails: ManageRoomMemberDetails = if let memberProxy = roomProxy.membersPublisher.value.first(where: { $0.userID == sender.id }) {
|
||||
.memberDetails(roomMember: .init(withProxy: memberProxy))
|
||||
} else {
|
||||
.loadingMemberDetails(sender: sender)
|
||||
}
|
||||
|
||||
if state.canCurrentUserBan || state.canCurrentUserKick {
|
||||
let member = RoomMemberDetails(withProxy: memberProxy)
|
||||
let manageMemeberViewModel = ManageRoomMemberSheetViewModel(member: member,
|
||||
canKick: state.canCurrentUserKick,
|
||||
canBan: state.canCurrentUserBan,
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: userIndicatorController,
|
||||
analyticsService: analyticsService,
|
||||
mediaProvider: mediaProvider)
|
||||
manageMemeberViewModel.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .dismiss(let shouldShowDetails):
|
||||
state.bindings.manageMemberViewModel = nil
|
||||
if shouldShowDetails {
|
||||
actionsSubject.send(.displaySenderDetails(userID: userID))
|
||||
}
|
||||
let viewModel = ManageRoomMemberSheetViewModel(memberDetails: memberDetails,
|
||||
permissions: .init(canKick: state.canCurrentUserKick,
|
||||
canBan: state.canCurrentUserBan,
|
||||
ownPowerLevel: currentUserProxy?.powerLevel ?? 0),
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: userIndicatorController,
|
||||
analyticsService: analyticsService,
|
||||
mediaProvider: mediaProvider)
|
||||
|
||||
viewModel.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .dismiss(let shouldShowDetails):
|
||||
state.bindings.manageMemberViewModel = nil
|
||||
if shouldShowDetails {
|
||||
actionsSubject.send(.displaySenderDetails(userID: sender.id))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
state.bindings.manageMemberViewModel = manageMemeberViewModel
|
||||
} else {
|
||||
actionsSubject.send(.displaySenderDetails(userID: userID))
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
state.bindings.manageMemberViewModel = viewModel
|
||||
}
|
||||
|
||||
private func focusLive() {
|
||||
|
||||
@@ -95,7 +95,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
||||
// sender info are read inside the `TimelineAccessibilityModifier`
|
||||
.accessibilityHidden(true)
|
||||
.onTapGesture {
|
||||
context.send(viewAction: .tappedOnSenderDetails(userID: timelineItem.sender.id))
|
||||
context.send(viewAction: .tappedOnSenderDetails(sender: timelineItem.sender))
|
||||
}
|
||||
.padding(.top, 8)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user