Moderation tweaks (#2548)

* Only allow admins to see the roles and permissions screen.

* Hide the selection checkbox on Admins when changing roles.

* Show an empty state for banned users.

* Add separate actions for ban and remove.

* Implement reset permissions and demote self alerts.

* Add tests for resetting permissions and demoting self.

* Add a warning when promoting someone to administrator.
This commit is contained in:
Doug
2024-03-11 14:19:53 +00:00
committed by GitHub
parent 9ce12e6e16
commit 71721f01b1
37 changed files with 411 additions and 104 deletions
@@ -83,12 +83,14 @@ struct RoomChangeRolesScreenViewState: BindableState {
struct RoomChangeRolesScreenViewStateBindings {
var searchQuery = ""
/// Information about the currently displayed alert.
var alertInfo: AlertInfo<RoomChangePermissionsScreenAlertType>?
var alertInfo: AlertInfo<RoomChangeRolesScreenAlertType>?
}
enum RoomChangeRolesScreenAlertType {
/// A warning that a particular promotion can't be undone.
case promotionWarning
/// The generic error message.
case generic
case error
}
enum RoomChangeRolesScreenViewAction {
@@ -64,7 +64,11 @@ class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomCh
case .demoteMember(let member):
demoteMember(member)
case .save:
Task { await save() }
if state.mode == .administrator, !state.membersToPromote.isEmpty {
showPromotionWarning()
} else {
Task { await save() }
}
}
}
@@ -99,6 +103,16 @@ class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomCh
}
}
private func showPromotionWarning() {
context.alertInfo = AlertInfo(id: .promotionWarning,
title: L10n.screenRoomChangeRoleConfirmAddAdminTitle,
message: L10n.screenRoomChangeRoleConfirmAddAdminDescription,
primaryButton: .init(title: L10n.actionContinue) {
Task { await self.save() }
},
secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil))
}
private func save() async {
showSavingIndicator()
@@ -112,7 +126,7 @@ class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomCh
case .success:
MXLog.info("Success")
case .failure:
context.alertInfo = AlertInfo(id: .generic)
context.alertInfo = AlertInfo(id: .error)
}
}
@@ -77,10 +77,10 @@ struct RoomChangeRolesScreen: View {
ForEach(context.viewState.visibleMembers, id: \.id) { member in
RoomChangeRolesScreenRow(member: member,
imageProvider: context.imageProvider,
kind: .multiSelection(isSelected: context.viewState.isMemberSelected(member)) {
context.send(viewAction: .toggleMember(member))
})
.disabled(member.role == .administrator)
isSelected: context.viewState.isMemberSelected(member)) {
context.send(viewAction: .toggleMember(member))
}
.disabled(member.role == .administrator)
}
} header: {
Text(L10n.screenRoomMemberListRoomMembersHeaderTitle)
@@ -19,16 +19,19 @@ import MatrixRustSDK
import SwiftUI
struct RoomChangeRolesScreenRow: View {
@Environment(\.isEnabled) private var isEnabled
let member: RoomMemberDetails
let imageProvider: ImageProviderProtocol?
let kind: ListRow<LoadableAvatarImage, EmptyView, EmptyView, Bool>.Kind<EmptyView, Bool>
let isSelected: Bool
let action: () -> Void
var body: some View {
ListRow(label: .avatar(title: member.name ?? member.id,
description: member.name == nil ? nil : member.id,
icon: avatar),
kind: kind)
kind: isEnabled ? .multiSelection(isSelected: isSelected, action: action) : .label)
}
var avatar: LoadableAvatarImage {
@@ -47,25 +50,30 @@ struct RoomChangeRolesScreenRow_Previews: PreviewProvider, TestablePreview {
Form {
RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock.mockAlice),
imageProvider: MockMediaProvider(),
kind: .multiSelection(isSelected: true, action: action))
isSelected: true,
action: action)
RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock.mockBob),
imageProvider: MockMediaProvider(),
kind: .multiSelection(isSelected: false, action: action))
isSelected: false,
action: action)
RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock.mockCharlie),
imageProvider: MockMediaProvider(),
kind: .multiSelection(isSelected: true, action: action))
isSelected: true,
action: action)
.disabled(true)
RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock(with: .init(userID: "@someone:matrix.org", membership: .join))),
imageProvider: MockMediaProvider(),
kind: .multiSelection(isSelected: false, action: action))
isSelected: false,
action: action)
.disabled(true)
RoomChangeRolesScreenRow(member: .init(withProxy: RoomMemberProxyMock(with: .init(userID: "@someone:matrix.org", membership: .join))),
imageProvider: MockMediaProvider(),
kind: .multiSelection(isSelected: false, action: action))
isSelected: false,
action: action)
}
.compoundList()
}