Report room and decline & block screens tweaks (#4044)

* report rom and decline and block screens tweaks

- Use the copies: "Leave room" and "Report room" everywhere, also in DMs
- Report reason in report room is now mandatory.
- Report reason in decline and block is now mandatory if the report action is set to on.
- Generic alert for failure of main API in both report room and decline and block has been added

* report room and decline and block screen previews
This commit is contained in:
Mauro
2025-04-22 11:44:20 +02:00
committed by GitHub
parent 49c8897b02
commit 7fcc550a59
19 changed files with 64 additions and 36 deletions

View File

@@ -240,6 +240,7 @@
"common_shared_location" = "Shared location";
"common_signing_out" = "Signing out";
"common_something_went_wrong" = "Something went wrong";
"common_something_went_wrong_message" = "We encountered an issue. Please try again.";
"common_starting_chat" = "Starting chat…";
"common_sticker" = "Sticker";
"common_success" = "Success";
@@ -486,7 +487,7 @@
"screen_report_room_leave_failed_alert_message" = "Your report was submitted successfully, but we encountered an issue while trying to leave the room. Please try again.";
"screen_report_room_leave_failed_alert_title" = "Unable to Leave Room";
"screen_report_room_reason_footer" = "Report this room to your admin. If the messages are encrypted, your admin will not be able to read them.";
"screen_report_room_reason_placeholder" = "Describe the reason…";
"screen_report_room_reason_placeholder" = "Describe the reason to report…";
"screen_report_room_title" = "Report room";
"screen_reset_encryption_password_error" = "An unknown error happened. Please check your account password is correct and try again.";
"screen_resolve_send_failure_changed_identity_primary_button_title" = "Withdraw verification and send";

View File

@@ -544,6 +544,8 @@ internal enum L10n {
internal static var commonSigningOut: String { return L10n.tr("Localizable", "common_signing_out") }
/// Something went wrong
internal static var commonSomethingWentWrong: String { return L10n.tr("Localizable", "common_something_went_wrong") }
/// We encountered an issue. Please try again.
internal static var commonSomethingWentWrongMessage: String { return L10n.tr("Localizable", "common_something_went_wrong_message") }
/// Starting chat
internal static var commonStartingChat: String { return L10n.tr("Localizable", "common_starting_chat") }
/// Sticker
@@ -1884,7 +1886,7 @@ internal enum L10n {
internal static var screenReportRoomLeaveFailedAlertTitle: String { return L10n.tr("Localizable", "screen_report_room_leave_failed_alert_title") }
/// Report this room to your admin. If the messages are encrypted, your admin will not be able to read them.
internal static var screenReportRoomReasonFooter: String { return L10n.tr("Localizable", "screen_report_room_reason_footer") }
/// Describe the reason
/// Describe the reason to report
internal static var screenReportRoomReasonPlaceholder: String { return L10n.tr("Localizable", "screen_report_room_reason_placeholder") }
/// Report room
internal static var screenReportRoomTitle: String { return L10n.tr("Localizable", "screen_report_room_title") }

View File

@@ -15,7 +15,10 @@ struct DeclineAndBlockScreenViewState: BindableState {
var bindings = DeclineAndBlockScreenViewStateBindings()
var isDeclineDisabled: Bool {
!bindings.shouldBlockUser && !bindings.shouldReport
if bindings.shouldReport {
return bindings.reportReason.isEmpty
}
return !bindings.shouldBlockUser && !bindings.shouldReport
}
}
@@ -23,9 +26,15 @@ struct DeclineAndBlockScreenViewStateBindings {
var shouldBlockUser = true
var shouldReport = false
var reportReason = ""
var alert: AlertInfo<DeclineAndBlockAlertType>?
}
enum DeclineAndBlockScreenViewAction {
case decline
case dismiss
}
enum DeclineAndBlockAlertType {
case declineFailed
}

View File

@@ -50,7 +50,7 @@ class DeclineAndBlockScreenViewModel: DeclineAndBlockScreenViewModelType, Declin
guard case let .invited(roomProxy) = await clientProxy.roomForIdentifier(roomID) else {
MXLog.error("DeclineAndBlockScreenViewModel: Unable to find an invited room for identifier \(roomID)")
hideLoadingIndicator()
showError()
showTryAgainAlert { [weak self] in Task { await self?.decline() } }
return
}
@@ -58,7 +58,7 @@ class DeclineAndBlockScreenViewModel: DeclineAndBlockScreenViewModelType, Declin
case .success:
var shouldShowFailure = false
if state.bindings.shouldReport {
shouldShowFailure = await clientProxy.reportRoomForIdentifier(roomID, reason: state.bindings.reportReason.isBlank ? nil : state.bindings.reportReason).isFailure
shouldShowFailure = await clientProxy.reportRoomForIdentifier(roomID, reason: state.bindings.reportReason.isEmpty ? nil : state.bindings.reportReason).isFailure
}
if state.bindings.shouldBlockUser {
@@ -74,7 +74,7 @@ class DeclineAndBlockScreenViewModel: DeclineAndBlockScreenViewModelType, Declin
actionsSubject.send(.dismiss(hasDeclined: true))
case .failure:
hideLoadingIndicator()
showError()
showTryAgainAlert { [weak self] in Task { await self?.decline() } }
}
}
@@ -97,6 +97,14 @@ class DeclineAndBlockScreenViewModel: DeclineAndBlockScreenViewModelType, Declin
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
}
private func showTryAgainAlert(retryAction: @escaping () -> Void) {
state.bindings.alert = .init(id: .declineFailed,
title: L10n.commonSomethingWentWrong,
message: L10n.commonSomethingWentWrongMessage,
primaryButton: .init(title: L10n.actionDismiss, role: .cancel, action: nil),
secondaryButton: .init(title: L10n.actionTryAgain, action: retryAction))
}
private func showSuccess() {
userIndicatorController.submitIndicator(.init(title: L10n.commonSuccess, iconName: "checkmark"))
}

View File

@@ -24,6 +24,7 @@ struct DeclineAndBlockScreen: View {
.navigationBarTitleDisplayMode(.inline)
.toolbar { toolbar }
.animation(.elementDefault, value: context.shouldReport)
.alert(item: $context.alert)
}
private var blockUserSection: some View {

View File

@@ -73,7 +73,7 @@ struct HomeScreenRoomList: View {
Button(role: .destructive) {
context.send(viewAction: .reportRoom(roomIdentifier: room.id))
} label: {
Label(room.isDirect ? L10n.actionReportDm : L10n.actionReportRoom, icon: \.chatProblem)
Label(L10n.actionReportRoom, icon: \.chatProblem)
}
}

View File

@@ -13,6 +13,10 @@ enum ReportRoomScreenViewModelAction: Equatable {
struct ReportRoomScreenViewState: BindableState {
var bindings = ReportRoomScreenViewStateBindings()
var canReport: Bool {
!bindings.reason.isEmpty
}
}
struct ReportRoomScreenViewStateBindings {
@@ -27,5 +31,6 @@ enum ReportRoomScreenViewAction {
}
enum ReportRoomScreenAlertType {
case reportRoomFailed
case leaveRoomFailed
}

View File

@@ -38,7 +38,7 @@ class ReportRoomScreenViewModel: ReportRoomScreenViewModelType, ReportRoomScreen
private func report() async {
showLoadingIndicator()
let result = await roomProxy.reportRoom(reason: state.bindings.reason.isBlank ? nil : state.bindings.reason)
let result = await roomProxy.reportRoom(reason: state.bindings.reason.isEmpty ? nil : state.bindings.reason)
switch result {
case .success:
@@ -51,7 +51,11 @@ class ReportRoomScreenViewModel: ReportRoomScreenViewModelType, ReportRoomScreen
}
case .failure:
hideLoadingIndicator()
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
state.bindings.alert = .init(id: .reportRoomFailed,
title: L10n.commonSomethingWentWrong,
message: L10n.commonSomethingWentWrongMessage,
primaryButton: .init(title: L10n.actionDismiss, role: .cancel, action: nil),
secondaryButton: .init(title: L10n.actionTryAgain) { [weak self] in Task { await self?.report() } })
}
}
@@ -72,7 +76,7 @@ class ReportRoomScreenViewModel: ReportRoomScreenViewModelType, ReportRoomScreen
title: L10n.screenReportRoomLeaveFailedAlertTitle,
message: L10n.screenReportRoomLeaveFailedAlertMessage,
primaryButton: .init(title: L10n.actionDismiss, role: .cancel) { [weak self] in self?.actionsSubject.send(.dismiss(shouldLeaveRoom: false)) },
secondaryButton: .init(title: L10n.actionRetry) { [weak self] in Task { await self?.leaveRoom(showLoading: true) } })
secondaryButton: .init(title: L10n.actionTryAgain) { [weak self] in Task { await self?.leaveRoom(showLoading: true) } })
}
}

View File

@@ -53,6 +53,7 @@ struct ReportRoomScreen: View {
Button(L10n.actionReport) {
context.send(viewAction: .report)
}
.disabled(!context.viewState.canReport)
}
}
}

View File

@@ -272,23 +272,15 @@ struct RoomDetailsScreen: View {
}
}
private var leaveRoomTitle: String {
context.viewState.dmRecipientInfo == nil ? L10n.screenRoomDetailsLeaveRoomTitle : L10n.screenRoomDetailsLeaveConversationTitle
}
private var reportRoomTitle: String {
context.viewState.dmRecipientInfo == nil ? L10n.actionReportRoom : L10n.actionReportDm
}
private var leaveRoomSection: some View {
Section {
if context.viewState.reportRoomEnabled {
ListRow(label: .action(title: reportRoomTitle,
ListRow(label: .action(title: L10n.actionReportRoom,
icon: \.chatProblem,
role: .destructive),
kind: .button { context.send(viewAction: .processTapReport) })
}
ListRow(label: .action(title: leaveRoomTitle,
ListRow(label: .action(title: L10n.screenRoomDetailsLeaveRoomTitle,
icon: \.leave,
role: .destructive),
kind: .button { context.send(viewAction: .processTapLeave) })

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:75f8f6719667c51e24b0e81fc0087e3dc89c78455eb4c5034ff390c1a6dedcc3
size 123998
oid sha256:ae55a771e173a36bb0c430f07ef9eb1163949251261c1ab34b6767d270000d75
size 123938

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97a51bbcea7e4196cc8be8c7a1a7e09ec9ad8fa0c45c544e2ce401aedd339d74
size 136178
oid sha256:c86228750f172b2c8beba3c353d0be92c07f29d42a43ff96445585fa38235d8e
size 136142

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4fa1b401510bd73e8ac4e9fda8ccc4504b0dada4c8f9b55b7df9fc8c5b205697
size 74827
oid sha256:9f8f68c34e6e3f5328a5e09194c5b95e8a598beac9950ff78429414b27f142fb
size 74746

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c25422fabd1dc5710b7f9e2736bb5d06a944dfe4ee94af7dd0b5bfa7ece5507c
size 93432
oid sha256:992e28b1f10659c3169b5b1835bfeb2390d3c1137da02dffe13b196bbd899d74
size 93388

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ac131e760c33abc71ff2561532486148184b2145ab8908fc93c8f59fd52a63bd
size 111036
oid sha256:8e5baed17a92e79e8e318646e04eaf1afb2d7eb3ae536eb113c603e660dbc8d7
size 111296

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ce3deae0c993d297780b9983f7864252b38ec5eb139b82c34eac5f66c344f30c
size 124615
oid sha256:bfddb027602a811e1dc71fd38606a16443eee31776cf88068a665ccbf75e9e52
size 124490

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:176befcab1eb8966e6aa976b7d08e0742229ed97d2d5d1df068d6fc04ecfb22a
size 63720
oid sha256:909fcf1c5e767941cf0f6173fa0c839e6e8a3f1cf38959ea70622e0f7042be0a
size 64555

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:65656c94698bb9e761ab88770432c3626e35eaea1eb09b0b439038f1d14f6465
size 82085
oid sha256:5596ae33489facd4c10d6dedbdc9fec041c8e68e9cff1e8105b36dc3acc0bd30
size 82025

View File

@@ -37,6 +37,11 @@ class DeclineAndBlockScreenViewModelTests: XCTestCase {
XCTAssertTrue(context.viewState.isDeclineDisabled)
XCTAssertFalse(context.shouldReport)
XCTAssertFalse(context.shouldBlockUser)
context.shouldReport = true
// Should report set to `true` always requires a non empty reason
XCTAssertTrue(context.viewState.isDeclineDisabled)
context.reportReason = "Test reason"
XCTAssertFalse(context.viewState.isDeclineDisabled)
}
func testDeclineBlockAndReport() async throws {