diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 2048776fe4..0d0b0e47f2 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -117,6 +117,7 @@ "action_view_in_timeline" = "View in timeline"; "action_view_source" = "View source"; "action_yes" = "Yes"; +"action_yes_try_again" = "Yes, try again"; "banner_migrate_to_native_sliding_sync_action" = "Log Out & Upgrade"; "banner_migrate_to_native_sliding_sync_description" = "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later."; "banner_migrate_to_native_sliding_sync_force_logout_title" = "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app."; @@ -380,7 +381,11 @@ "screen_knock_requests_list_accept_all_alert_description" = "Are you sure you want to accept all requests to join?"; "screen_knock_requests_list_accept_all_alert_title" = "Accept all requests"; "screen_knock_requests_list_accept_all_button_title" = "Accept all"; +"screen_knock_requests_list_accept_all_failed_alert_description" = "We couldn’t accept all requests. Would you like to try again?"; +"screen_knock_requests_list_accept_all_failed_alert_title" = "Failed to accept all requests"; "screen_knock_requests_list_accept_all_loading_title" = "Accepting all requests to join"; +"screen_knock_requests_list_accept_failed_alert_description" = "We couldn’t accept this request. Would you like to try again?"; +"screen_knock_requests_list_accept_failed_alert_title" = "Failed to accept request"; "screen_knock_requests_list_accept_loading_title" = "Accepting request to join"; "screen_knock_requests_list_ban_alert_confirm_button_title" = "Yes, decline and ban"; "screen_knock_requests_list_ban_alert_description" = "Are you sure you want to decline and ban %1$@? This user won’t be able to request access to join this room again."; @@ -390,6 +395,8 @@ "screen_knock_requests_list_decline_alert_description" = "Are you sure you want to decline %1$@ request to join this room?"; "screen_knock_requests_list_decline_alert_title" = "Decline access"; "screen_knock_requests_list_decline_and_ban_action_title" = "Decline and ban"; +"screen_knock_requests_list_decline_failed_alert_description" = "We couldn’t decline this request. Would you like to try again?"; +"screen_knock_requests_list_decline_failed_alert_title" = "Failed to decline request"; "screen_knock_requests_list_decline_loading_title" = "Declining request to join"; "screen_knock_requests_list_empty_state_description" = "When somebody will ask to join the room, you’ll be able to see their request here."; "screen_knock_requests_list_empty_state_title" = "No pending request to join"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index deb54ede38..47fb104f35 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -270,6 +270,8 @@ internal enum L10n { internal static var actionViewSource: String { return L10n.tr("Localizable", "action_view_source") } /// Yes internal static var actionYes: String { return L10n.tr("Localizable", "action_yes") } + /// Yes, try again + internal static var actionYesTryAgain: String { return L10n.tr("Localizable", "action_yes_try_again") } /// Log Out & Upgrade internal static var bannerMigrateToNativeSlidingSyncAction: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_action") } /// Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later. @@ -1320,8 +1322,16 @@ internal enum L10n { internal static var screenKnockRequestsListAcceptAllAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_alert_title") } /// Accept all internal static var screenKnockRequestsListAcceptAllButtonTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_button_title") } + /// We couldn’t accept all requests. Would you like to try again? + internal static var screenKnockRequestsListAcceptAllFailedAlertDescription: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_failed_alert_description") } + /// Failed to accept all requests + internal static var screenKnockRequestsListAcceptAllFailedAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_failed_alert_title") } /// Accepting all requests to join internal static var screenKnockRequestsListAcceptAllLoadingTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_all_loading_title") } + /// We couldn’t accept this request. Would you like to try again? + internal static var screenKnockRequestsListAcceptFailedAlertDescription: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_failed_alert_description") } + /// Failed to accept request + internal static var screenKnockRequestsListAcceptFailedAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_failed_alert_title") } /// Accepting request to join internal static var screenKnockRequestsListAcceptLoadingTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_accept_loading_title") } /// Yes, decline and ban @@ -1344,6 +1354,10 @@ internal enum L10n { internal static var screenKnockRequestsListDeclineAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_alert_title") } /// Decline and ban internal static var screenKnockRequestsListDeclineAndBanActionTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_and_ban_action_title") } + /// We couldn’t decline this request. Would you like to try again? + internal static var screenKnockRequestsListDeclineFailedAlertDescription: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_failed_alert_description") } + /// Failed to decline request + internal static var screenKnockRequestsListDeclineFailedAlertTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_failed_alert_title") } /// Declining request to join internal static var screenKnockRequestsListDeclineLoadingTitle: String { return L10n.tr("Localizable", "screen_knock_requests_list_decline_loading_title") } /// When somebody will ask to join the room, you’ll be able to see their request here. diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift index e1ed9f5201..7c464a200a 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenModels.swift @@ -60,6 +60,9 @@ enum KnockRequestsListAlertType { case acceptAllRequests case declineRequest case declineAndBan + case acceptAllFailed + case acceptFailed + case declineFailed } enum KnockRequestsListScreenViewAction { diff --git a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift index dd6a31496c..567566480f 100644 --- a/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift +++ b/ElementX/Sources/Screens/KnockRequestsListScreen/KnockRequestsListScreenViewModel.swift @@ -46,7 +46,10 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn action: acceptAll), secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) case .acceptRequest(let eventID): - acceptRequest(eventID: eventID) + guard let request = getRequest(eventID: eventID) else { + return + } + accept(request: request) case .declineRequest(let eventID): guard let request = getRequest(eventID: eventID) else { return @@ -81,30 +84,30 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn return request } - private func acceptRequest(eventID: String) { - guard let request = getRequest(eventID: eventID) else { - return - } - + private func accept(request: JoinRequestProxyProtocol) { showLoadingIndicator(title: L10n.screenKnockRequestsListAcceptLoadingTitle) - defer { hideLoadingIndicator() } + let eventID = request.eventID state.handledEventIDs.insert(eventID) Task { switch await request.accept() { case .success: - break + hideLoadingIndicator() case .failure: + hideLoadingIndicator() state.handledEventIDs.remove(eventID) - userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown)) + state.bindings.alertInfo = .init(id: .acceptFailed, + title: L10n.screenKnockRequestsListAcceptFailedAlertTitle, + message: L10n.screenKnockRequestsListAcceptFailedAlertDescription, + primaryButton: .init(title: L10n.actionYesTryAgain) { [weak self] in self?.accept(request: request) }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) } } } private func decline(request: JoinRequestProxyProtocol) { showLoadingIndicator(title: L10n.screenKnockRequestsListDeclineLoadingTitle) - defer { hideLoadingIndicator() } let eventID = request.eventID state.handledEventIDs.insert(eventID) @@ -112,17 +115,21 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn Task { switch await request.decline() { case .success: - break + hideLoadingIndicator() case .failure: + hideLoadingIndicator() state.handledEventIDs.remove(eventID) - userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown)) + state.bindings.alertInfo = .init(id: .declineFailed, + title: L10n.screenKnockRequestsListDeclineFailedAlertTitle, + message: L10n.screenKnockRequestsListDeclineFailedAlertDescription, + primaryButton: .init(title: L10n.actionYesTryAgain) { [weak self] in self?.decline(request: request) }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) } } } private func declineAndBan(request: JoinRequestProxyProtocol) { showLoadingIndicator(title: L10n.screenKnockRequestsListBanLoadingTitle) - defer { hideLoadingIndicator() } let eventID = request.eventID state.handledEventIDs.insert(eventID) @@ -130,21 +137,24 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn Task { switch await request.ban() { case .success: - break + hideLoadingIndicator() case .failure: + hideLoadingIndicator() state.handledEventIDs.remove(eventID) - userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown)) + state.bindings.alertInfo = .init(id: .declineFailed, + title: L10n.screenKnockRequestsListDeclineFailedAlertTitle, + message: L10n.screenKnockRequestsListDeclineFailedAlertDescription, + primaryButton: .init(title: L10n.actionYesTryAgain) { [weak self] in self?.declineAndBan(request: request) }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) } } } private func acceptAll() { - showLoadingIndicator(title: L10n.screenKnockRequestsListAcceptAllLoadingTitle) - defer { hideLoadingIndicator() } - guard case let .loaded(requests) = roomProxy.joinRequestsStatePublisher.value else { return } + showLoadingIndicator(title: L10n.screenKnockRequestsListAcceptAllLoadingTitle) state.handledEventIDs.formUnion(Set(requests.map(\.eventID))) Task { @@ -161,8 +171,16 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn } return failedIDs } + hideLoadingIndicator() - state.handledEventIDs.subtract(failedIDs) + if !failedIDs.isEmpty { + state.handledEventIDs.subtract(failedIDs) + state.bindings.alertInfo = .init(id: .acceptAllFailed, + title: L10n.screenKnockRequestsListAcceptAllFailedAlertTitle, + message: L10n.screenKnockRequestsListAcceptAllFailedAlertDescription, + primaryButton: .init(title: L10n.actionYesTryAgain) { [weak self] in self?.acceptAll() }, + secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) + } } } @@ -230,7 +248,7 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn allowsInteraction: false), title: title, persistent: true), - delay: .milliseconds(250)) + delay: .milliseconds(200)) } private func hideLoadingIndicator() {