Skip to content

Commit

Permalink
added error state alerts with retry
Browse files Browse the repository at this point in the history
  • Loading branch information
Velin92 committed Dec 13, 2024
1 parent 8eb5f82 commit 560b62c
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 20 deletions.
7 changes: 7 additions & 0 deletions ElementX/Resources/Localizations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -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.";
Expand Down Expand Up @@ -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.";
Expand All @@ -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";
Expand Down
14 changes: 14 additions & 0 deletions ElementX/Sources/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ enum KnockRequestsListAlertType {
case acceptAllRequests
case declineRequest
case declineAndBan
case acceptAllFailed
case acceptFailed
case declineFailed
}

enum KnockRequestsListScreenViewAction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -81,70 +84,77 @@ 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)

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)

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 {
Expand All @@ -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))
}
}
}

Expand Down Expand Up @@ -230,7 +248,7 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn
allowsInteraction: false),
title: title,
persistent: true),
delay: .milliseconds(250))
delay: .milliseconds(200))
}

private func hideLoadingIndicator() {
Expand Down

0 comments on commit 560b62c

Please sign in to comment.