Skip to content

Commit

Permalink
Require acknowledgement to send to verified users who have unsigned d…
Browse files Browse the repository at this point in the history
…evices or have changed their identity. (#3215)

* Refactor HeroImage style.

* Add a screen to resolve (crypto-related) timeline item send failures.

* Refactor send failures.

* Update the SDK.
  • Loading branch information
pixlwave committed Sep 10, 2024
1 parent f6c8aae commit cc4942f
Show file tree
Hide file tree
Showing 86 changed files with 1,422 additions and 158 deletions.
42 changes: 41 additions & 1 deletion ElementX.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/element-hq/matrix-rust-components-swift",
"state" : {
"revision" : "343d7045a0ad6fe508728f624a02698e679327fb",
"version" : "1.0.44"
"revision" : "103b7000e5191485873a81386d0134d71bd9fc36",
"version" : "1.0.45"
}
},
{
Expand Down
18 changes: 13 additions & 5 deletions ElementX/Resources/Localizations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"action_back" = "Back";
"action_call" = "Call";
"action_cancel" = "Cancel";
"action_cancel_for_now" = "Cancel for now";
"action_choose_photo" = "Choose photo";
"action_clear" = "Clear";
"action_close" = "Close";
Expand Down Expand Up @@ -106,6 +107,10 @@
"action_view_source" = "View source";
"action_yes" = "Yes";
"action.load_more" = "Load more";
"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.";
"banner_migrate_to_native_sliding_sync_title" = "Upgrade available";
"banner.set_up_recovery.content" = "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices.";
"banner.set_up_recovery.title" = "Set up recovery";
"common_about" = "About";
Expand Down Expand Up @@ -325,12 +330,20 @@
"screen_pinned_timeline_empty_state_headline" = "Pin important messages so that they can be easily discovered";
"screen_pinned_timeline_screen_title_empty" = "Pinned messages";
"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";
"screen_resolve_send_failure_changed_identity_subtitle" = "You can withdraw your verification and send this message anyway, or you can cancel for now and try again later after reverifying %1$@.";
"screen_resolve_send_failure_changed_identity_title" = "Your message was not sent because %1$@’s verified identity has changed";
"screen_resolve_send_failure_unsigned_device_primary_button_title" = "Send message anyway";
"screen_resolve_send_failure_unsigned_device_subtitle" = "%1$@ is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$@ has verified all their devices.";
"screen_resolve_send_failure_unsigned_device_title" = "Your message was not sent because %1$@ has not verified one or more devices";
"screen_room_mentions_at_room_subtitle" = "Notify the whole room";
"screen_room_pinned_banner_indicator" = "%1$@ of %2$@";
"screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages";
"screen_room_pinned_banner_loading_description" = "Loading message…";
"screen_room_pinned_banner_view_all_button_title" = "View All";
"screen_room_details_pinned_events_row_title" = "Pinned messages";
"screen_timeline_item_menu_send_failure_changed_identity" = "Message not sent because %1$@’s verified identity has changed.";
"screen_timeline_item_menu_send_failure_unsigned_device" = "Message not sent because %1$@ has not verified one or more devices.";
"screen_account_provider_change" = "Change account provider";
"screen_account_provider_form_hint" = "Homeserver address";
"screen_account_provider_form_notice" = "Enter a search term or a domain address.";
Expand Down Expand Up @@ -579,7 +592,6 @@
"screen_recovery_key_confirm_error_content" = "Please try again to confirm access to your chat backup.";
"screen_recovery_key_confirm_error_title" = "Incorrect recovery key";
"screen_recovery_key_confirm_key_description" = "If you have a security key or security phrase, this will work too.";
"screen_recovery_key_confirm_key_label" = "Recovery key or passcode";
"screen_recovery_key_confirm_key_placeholder" = "Enter…";
"screen_recovery_key_confirm_lost_recovery_key" = "Lost your recovery key?";
"screen_recovery_key_confirm_success" = "Recovery key confirmed";
Expand Down Expand Up @@ -806,9 +818,6 @@
"screen_signout_save_recovery_key_title" = "Have you saved your recovery key?";
"screen_start_chat_error_starting_chat" = "An error occurred when trying to start a chat";
"screen_view_location_title" = "Location";
"screen_waitlist_message" = "There's a high demand for %1$@ on %2$@ at the moment. Come back to the app in a few days and try again.\n\nThanks for your patience!";
"screen_waitlist_title" = "You’re almost there.";
"screen_waitlist_title_success" = "You're in.";
"screen_welcome_bullet_1" = "Calls, polls, search and more will be added later this year.";
"screen_welcome_bullet_2" = "Message history for encrypted rooms isn’t available yet.";
"screen_welcome_bullet_3" = "We’d love to hear from you, let us know what you think via the settings page.";
Expand Down Expand Up @@ -983,4 +992,3 @@
"screen_signout_confirmation_dialog_submit" = "Sign out";
"screen_signout_confirmation_dialog_title" = "Sign out";
"screen_signout_preference_item" = "Sign out";
"screen_waitlist_message_success" = "Welcome to %1$@!";
35 changes: 35 additions & 0 deletions ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
case (.roomDetails, .presentRoomMemberDetails(let userID)):
return .roomMemberDetails(userID: userID, previousState: fromState)

case (.room, .presentResolveSendFailure):
return .resolveSendFailure
case (.resolveSendFailure, .dismissResolveSendFailure):
return .room

// Child flow

case (_, .startChildFlow(let roomID, _, _)):
Expand Down Expand Up @@ -499,6 +504,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
case (.roomMemberDetails, .dismissUserProfile, .roomDetails):
break

case (.room, .presentResolveSendFailure(let failure, let itemID), .resolveSendFailure):
presentResolveSendFailure(failure: failure, itemID: itemID)
case (.resolveSendFailure, .dismissResolveSendFailure, .room):
break

// Child flow
case (_, .startChildFlow(let roomID, let via, let entryPoint), .presentingChild):
Task { await self.startChildFlow(for: roomID, via: via, entryPoint: entryPoint) }
Expand Down Expand Up @@ -623,6 +633,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
actionsSubject.send(.presentCallScreen(roomProxy: roomProxy))
case .presentPinnedEventsTimeline:
stateMachine.tryEvent(.presentPinnedEventsTimeline)
case .presentResolveSendFailure(failure: let failure, itemID: let itemID):
stateMachine.tryEvent(.presentResolveSendFailure(failure: failure, itemID: itemID))
}
}
.store(in: &cancellables)
Expand Down Expand Up @@ -1351,6 +1363,25 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
coordinator.start()
}

private func presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier) {
let coordinator = ResolveVerifiedUserSendFailureScreenCoordinator(parameters: .init(failure: failure,
itemID: itemID,
roomProxy: roomProxy))
coordinator.actionsPublisher.sink { [weak self] action in
guard let self else { return }

switch action {
case .dismiss:
navigationStackCoordinator.setSheetCoordinator(nil)
}
}
.store(in: &cancellables)

navigationStackCoordinator.setSheetCoordinator(coordinator) { [weak self] in
self?.stateMachine.tryEvent(.dismissResolveSendFailure)
}
}

// MARK: - Child Flow

private func startChildFlow(for roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) async {
Expand Down Expand Up @@ -1425,6 +1456,7 @@ private extension RoomFlowCoordinator {
case pollsHistoryForm
case rolesAndPermissions
case pinnedEventsTimeline(previousState: PinnedEventsTimelineSource)
case resolveSendFailure

/// A child flow is in progress.
case presentingChild(childRoomID: String, previousState: State)
Expand Down Expand Up @@ -1497,6 +1529,9 @@ private extension RoomFlowCoordinator {
case presentPinnedEventsTimeline
case dismissPinnedEventsTimeline

case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, itemID: TimelineItemIdentifier)
case dismissResolveSendFailure

// Child room flow events
case startChildFlow(roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint)
case dismissChildFlow
Expand Down
54 changes: 38 additions & 16 deletions ElementX/Sources/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ internal enum L10n {
internal static var actionCall: String { return L10n.tr("Localizable", "action_call") }
/// Cancel
internal static var actionCancel: String { return L10n.tr("Localizable", "action_cancel") }
/// Cancel for now
internal static var actionCancelForNow: String { return L10n.tr("Localizable", "action_cancel_for_now") }
/// Choose photo
internal static var actionChoosePhoto: String { return L10n.tr("Localizable", "action_choose_photo") }
/// Clear
Expand Down Expand Up @@ -244,6 +246,14 @@ 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") }
/// 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.
internal static var bannerMigrateToNativeSlidingSyncDescription: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_description") }
/// Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app.
internal static var bannerMigrateToNativeSlidingSyncForceLogoutTitle: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_force_logout_title") }
/// Upgrade available
internal static var bannerMigrateToNativeSlidingSyncTitle: String { return L10n.tr("Localizable", "banner_migrate_to_native_sliding_sync_title") }
/// About
internal static var commonAbout: String { return L10n.tr("Localizable", "common_about") }
/// Acceptable use policy
Expand Down Expand Up @@ -1383,8 +1393,6 @@ internal enum L10n {
internal static var screenRecoveryKeyConfirmErrorTitle: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_error_title") }
/// If you have a security key or security phrase, this will work too.
internal static var screenRecoveryKeyConfirmKeyDescription: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_key_description") }
/// Recovery key or passcode
internal static var screenRecoveryKeyConfirmKeyLabel: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_key_label") }
/// Enter…
internal static var screenRecoveryKeyConfirmKeyPlaceholder: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_key_placeholder") }
/// Lost your recovery key?
Expand Down Expand Up @@ -1447,6 +1455,26 @@ internal enum L10n {
}
/// Can't confirm? Go to your account to reset your identity.
internal static var screenResetIdentityConfirmationTitle: String { return L10n.tr("Localizable", "screen_reset_identity_confirmation_title") }
/// Withdraw verification and send
internal static var screenResolveSendFailureChangedIdentityPrimaryButtonTitle: String { return L10n.tr("Localizable", "screen_resolve_send_failure_changed_identity_primary_button_title") }
/// You can withdraw your verification and send this message anyway, or you can cancel for now and try again later after reverifying %1$@.
internal static func screenResolveSendFailureChangedIdentitySubtitle(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_resolve_send_failure_changed_identity_subtitle", String(describing: p1))
}
/// Your message was not sent because %1$@’s verified identity has changed
internal static func screenResolveSendFailureChangedIdentityTitle(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_resolve_send_failure_changed_identity_title", String(describing: p1))
}
/// Send message anyway
internal static var screenResolveSendFailureUnsignedDevicePrimaryButtonTitle: String { return L10n.tr("Localizable", "screen_resolve_send_failure_unsigned_device_primary_button_title") }
/// %1$@ is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$@ has verified all their devices.
internal static func screenResolveSendFailureUnsignedDeviceSubtitle(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "screen_resolve_send_failure_unsigned_device_subtitle", String(describing: p1), String(describing: p2))
}
/// Your message was not sent because %1$@ has not verified one or more devices
internal static func screenResolveSendFailureUnsignedDeviceTitle(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_resolve_send_failure_unsigned_device_title", String(describing: p1))
}
/// Failed to resolve room alias.
internal static var screenRoomAliasResolverResolveAliasFailure: String { return L10n.tr("Localizable", "screen_room_alias_resolver_resolve_alias_failure") }
/// Camera
Expand Down Expand Up @@ -1945,22 +1973,16 @@ internal enum L10n {
internal static var screenSignoutSaveRecoveryKeyTitle: String { return L10n.tr("Localizable", "screen_signout_save_recovery_key_title") }
/// An error occurred when trying to start a chat
internal static var screenStartChatErrorStartingChat: String { return L10n.tr("Localizable", "screen_start_chat_error_starting_chat") }
/// Location
internal static var screenViewLocationTitle: String { return L10n.tr("Localizable", "screen_view_location_title") }
/// There's a high demand for %1$@ on %2$@ at the moment. Come back to the app in a few days and try again.
///
/// Thanks for your patience!
internal static func screenWaitlistMessage(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "screen_waitlist_message", String(describing: p1), String(describing: p2))
/// Message not sent because %1$@’s verified identity has changed.
internal static func screenTimelineItemMenuSendFailureChangedIdentity(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_timeline_item_menu_send_failure_changed_identity", String(describing: p1))
}
/// Welcome to %1$@!
internal static func screenWaitlistMessageSuccess(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_waitlist_message_success", String(describing: p1))
/// Message not sent because %1$@ has not verified one or more devices.
internal static func screenTimelineItemMenuSendFailureUnsignedDevice(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_timeline_item_menu_send_failure_unsigned_device", String(describing: p1))
}
/// You’re almost there.
internal static var screenWaitlistTitle: String { return L10n.tr("Localizable", "screen_waitlist_title") }
/// You're in.
internal static var screenWaitlistTitleSuccess: String { return L10n.tr("Localizable", "screen_waitlist_title_success") }
/// Location
internal static var screenViewLocationTitle: String { return L10n.tr("Localizable", "screen_view_location_title") }
/// Calls, polls, search and more will be added later this year.
internal static var screenWelcomeBullet1: String { return L10n.tr("Localizable", "screen_welcome_bullet_1") }
/// Message history for encrypted rooms isn’t available yet.
Expand Down
Loading

0 comments on commit cc4942f

Please sign in to comment.