diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-move-labelled.yml index 1cce27e94..632e8b538 100644 --- a/.github/workflows/triage-move-labelled.yml +++ b/.github/workflows/triage-move-labelled.yml @@ -268,7 +268,7 @@ jobs: name: Add labelled issues to PS features team 3 runs-on: ubuntu-latest if: > - contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor'') + contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor') steps: - uses: octokit/graphql-action@v2.x id: add_to_project @@ -287,3 +287,27 @@ jobs: env: PROJECT_ID: "PVT_kwDOAM0swc4AHJKW" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + + voip: + name: Add labelled issues to VoIP project board + runs-on: ubuntu-latest + if: > + contains(github.event.issue.labels.*.name, 'Team: VoIP') + steps: + - uses: octokit/graphql-action@v2.x + id: add_to_project + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:ID!,$contentid:ID!) { + addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) { + item { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.issue.node_id }} + env: + PROJECT_ID: "PVT_kwDOAM0swc4ABMIk" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/CHANGES.md b/CHANGES.md index 5aa8502c9..8f8e82c1e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,40 @@ +## Changes in 1.9.10 (2022-11-01) + +✨ Features + +- Changed the info in the background audio message player. ([#6870](https://github.com/vector-im/element-ios/pull/6870)) +- Added voice message support to the Rich Text Composer ([#6941](https://github.com/vector-im/element-ios/issues/6941)) + +🙌 Improvements + +- Improves external links interaction UX. ([#6936](https://github.com/vector-im/element-ios/pull/6936)) +- Verification: Deprecate legacy device-to-device verification ([#6937](https://github.com/vector-im/element-ios/pull/6937)) +- Crypto: Define MXCrypto and MXCrossSigning as protocols ([#6943](https://github.com/vector-im/element-ios/pull/6943)) +- Hide the old session list when the new device manager is enabled. ([#6999](https://github.com/vector-im/element-ios/pull/6999)) +- Upgrade MatrixSDK version ([v0.24.2](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.24.2)). +- Added a responsive placeholder text to the Rich Text Composer ([#6935](https://github.com/vector-im/element-ios/issues/6935)) +- Added the maximise/minimise toggle button to the Rich Text Composer ([#6954](https://github.com/vector-im/element-ios/issues/6954)) + +🐛 Bugfixes + +- Timeline: Fix layout for SwiftUI content views. ([#5326](https://github.com/vector-im/element-ios/issues/5326)) +- Updates the avatar image loading logics. ([#6847](https://github.com/vector-im/element-ios/issues/6847)) +- Fixes input text view height when containing multiple lines of text. ([#6849](https://github.com/vector-im/element-ios/issues/6849)) +- Fixed the placeholder flickering in the input toolbar when there is an height change. ([#6949](https://github.com/vector-im/element-ios/issues/6949)) + +🧱 Build + +- Add Z-Labs tag for rich text editor and update to the new label naming. ([#6996](https://github.com/vector-im/element-ios/pull/6996)) + +🚧 In development 🚧 + +- Device Manager: Multi-session selection. ([#6928](https://github.com/vector-im/element-ios/issues/6928)) + +Others + +- Updated templates readme file. ([#6925](https://github.com/vector-im/element-ios/issues/6925)) + + ## Changes in 1.9.9 (2022-10-18) ✨ Features diff --git a/Config/AppVersion.xcconfig b/Config/AppVersion.xcconfig index f891de397..f0fe26011 100644 --- a/Config/AppVersion.xcconfig +++ b/Config/AppVersion.xcconfig @@ -15,5 +15,5 @@ // // Version -MARKETING_VERSION = 1.9.10 -CURRENT_PROJECT_VERSION = 1.9.10 +MARKETING_VERSION = 1.9.11 +CURRENT_PROJECT_VERSION = 1.9.11 diff --git a/Config/CommonConfiguration.swift b/Config/CommonConfiguration.swift index a89427c3a..fee3796ff 100644 --- a/Config/CommonConfiguration.swift +++ b/Config/CommonConfiguration.swift @@ -172,7 +172,7 @@ class CommonConfiguration: NSObject, Configurable { func setupSettingsWhenLoaded(for matrixSession: MXSession) { // Do not warn for unknown devices. We have cross-signing now - matrixSession.crypto?.warnOnUnknowDevices = false + (matrixSession.crypto as? MXLegacyCrypto)?.warnOnUnknowDevices = false } } diff --git a/Podfile b/Podfile index c734fd817..d89c32f61 100644 --- a/Podfile +++ b/Podfile @@ -16,7 +16,7 @@ use_frameworks! # - `{ :specHash => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for MatrixSDK repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixSDKVersion = '= 0.24.1' +$matrixSDKVersion = '= 0.24.2' # $matrixSDKVersion = :local # $matrixSDKVersion = { :branch => 'develop'} # $matrixSDKVersion = { :specHash => { git: 'https://git.io/fork123', branch: 'fix' } } diff --git a/Podfile.lock b/Podfile.lock index b3673f8ce..3d8bb303e 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -55,9 +55,9 @@ PODS: - LoggerAPI (1.9.200): - Logging (~> 1.1) - Logging (1.4.0) - - MatrixSDK (0.24.1): - - MatrixSDK/Core (= 0.24.1) - - MatrixSDK/Core (0.24.1): + - MatrixSDK (0.24.2): + - MatrixSDK/Core (= 0.24.2) + - MatrixSDK/Core (0.24.2): - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) @@ -65,12 +65,12 @@ PODS: - OLMKit (~> 3.2.5) - Realm (= 10.27.0) - SwiftyBeaver (= 1.9.5) - - MatrixSDK/CryptoSDK (0.24.1): - - MatrixSDKCrypto (= 0.1.2) - - MatrixSDK/JingleCallStack (0.24.1): + - MatrixSDK/CryptoSDK (0.24.2): + - MatrixSDKCrypto (= 0.1.5) + - MatrixSDK/JingleCallStack (0.24.2): - JitsiMeetSDK (= 5.0.2) - MatrixSDK/Core - - MatrixSDKCrypto (0.1.2) + - MatrixSDKCrypto (0.1.5) - OLMKit (3.2.12): - OLMKit/olmc (= 3.2.12) - OLMKit/olmcpp (= 3.2.12) @@ -122,8 +122,8 @@ DEPENDENCIES: - KeychainAccess (~> 4.2.2) - KTCenterFlowLayout (~> 1.3.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.24.1) - - MatrixSDK/JingleCallStack (= 0.24.1) + - MatrixSDK (= 0.24.2) + - MatrixSDK/JingleCallStack (= 0.24.2) - OLMKit - PostHog (~> 1.4.4) - ReadMoreTextView (~> 3.0.1) @@ -220,8 +220,8 @@ SPEC CHECKSUMS: libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75 LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d Logging: beeb016c9c80cf77042d62e83495816847ef108b - MatrixSDK: 0cb0727dd82f88d0115da93ce94ed9556a195c9b - MatrixSDKCrypto: e6e69cb16f9e459761567d078af0c17929f6a3c2 + MatrixSDK: 1b64384084050652fcffafdf8641200f1ab25060 + MatrixSDKCrypto: dcab554bc7157cad31c01fc1137cf5acb01959a4 OLMKit: da115f16582e47626616874e20f7bb92222c7a51 PostHog: 4b6321b521569092d4ef3a02238d9435dbaeb99f ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d @@ -241,6 +241,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 82fb79d0a6b074f77950ec73304a749eb0329d12 +PODFILE CHECKSUM: 96a971e076c61e54ae5bb7bf30ecba80563eeacf COCOAPODS: 1.11.3 diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 1751c12fb..5e7c7dee1 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -153,15 +153,15 @@ "room_two_users_are_typing" = "%@ und %@ tippen…"; "room_many_users_are_typing" = "%@, %@ und andere tippen…"; "room_message_placeholder" = "Nachricht senden (unverschlüsselt)…"; -"encrypted_room_message_placeholder" = "Verschlüsselte Nachricht…"; -"room_message_short_placeholder" = "Sende eine Nachricht…"; +"encrypted_room_message_placeholder" = "Verschlüsselte Nachricht senden …"; +"room_message_short_placeholder" = "Nachricht senden …"; "room_offline_notification" = "Verbindung zum Server wurde unterbrochen."; -"room_unsent_messages_notification" = "Nachrichten wurden nicht gesendet."; -"room_unsent_messages_unknown_devices_notification" = "Nachrichten wurden nicht gesendet, da unbekannte Sitzungen vorhanden waren."; +"room_unsent_messages_notification" = "Senden der Nachrichten fehlgeschlagen."; +"room_unsent_messages_unknown_devices_notification" = "Senden der Nachrichten aufgrund unbekannter Sitzungen fehlgeschlagen."; "room_prompt_resend" = "Alle erneut senden"; -"room_prompt_cancel" = "Alles abbrechen"; +"room_prompt_cancel" = "Alle abbrechen"; "room_resend_unsent_messages" = "Ungesendete Nachrichten erneut senden"; -"room_delete_unsent_messages" = "Lösche ungesendete Nachrichten"; +"room_delete_unsent_messages" = "Nicht gesendete Nachrichten löschen"; "room_event_action_copy" = "Kopieren"; "room_event_action_quote" = "Zitieren"; "room_event_action_more" = "Mehr"; @@ -301,7 +301,7 @@ "room_participants_action_unban" = "Entsperren"; "room_participants_action_set_default_power_level" = "Besondere Berechtigungen entziehen"; "room_participants_action_start_voice_call" = "Starte Sprach-Anruf"; -"room_ongoing_conference_call" = "Laufender Konferenz-Anruf. Trete bei als %@ oder %@."; +"room_ongoing_conference_call" = "Laufender Konferenzanruf. Tritt als %@ oder %@ bei."; "room_event_action_redact" = "Entfernen"; "room_warning_about_encryption" = "Ende-zu-Ende-Verschlüsselung ist in Beta und ist evtl. nicht zuverlässig.\n\nMan sollte noch nicht darauf vertrauen, dass die Daten sicher sind.\n\nGeräte werden Nachrichten von vor dem Beitritt des Raumes nicht entschlüsseln können.\n\nVerschlüsselte Nachrichten sind nicht lesbar in Anwendungen, die die Verschlüsselung noch nicht implementiert haben."; "unknown_devices_alert" = "Dieser Raum enthält unbekannte Sitzungen, die nicht verifiziert wurden.\nDas bedeutet, es gibt keine Garantie, dass sie den angegebenen Benutzern gehört.\nWir empfehlen eine Überprüfung für jedes Gerät, bevor du weitermachst. Du kannst die Nachricht auch ohne Verifizierung erneut senden."; @@ -411,14 +411,14 @@ "auth_home_server_placeholder" = "URL (z.B. https://matrix.org)"; "auth_identity_server_placeholder" = "URL (z. B. https://vector.im)"; "room_ongoing_conference_call_close" = "Schließen"; -"room_conference_call_no_power" = "Du brauchst die Berechtigung Konferenzgespräche in diesem Raum zu verwalten"; +"room_conference_call_no_power" = "Du bist nicht berechtigt, Konferenzgespräche in diesem Raum zu verwalten"; "settings_labs_create_conference_with_jitsi" = "Erstelle Konferenzgespräche mit Jitsi"; "call_already_displayed" = "Es existiert bereits ein Gespräch."; "call_jitsi_error" = "Konferenzgespräch konnte nicht betreten werden."; // Widget "widget_no_power_to_manage" = "Du brauchst die Berechtigung um Widgets in diesem Raum zu verwalten"; "widget_creation_failure" = "Widget-Erstellung fehlgeschlagen"; -"room_ongoing_conference_call_with_close" = "Laufendes Konferenzgespräch. Trete mit %@ oder %@ bei. %@ es."; +"room_ongoing_conference_call_with_close" = "Laufendes Konferenzgespräch. Tritt als %@ oder %@ bei. %@ es."; "settings_ui_theme" = "Thema"; "settings_ui_theme_auto" = "Auto"; "settings_ui_theme_light" = "Hell"; @@ -436,13 +436,13 @@ "call_incoming_voice" = "Eingehender Anruf…"; "call_incoming_video" = "Eingehender Videoanruf…"; // Widget Integration Manager -"widget_integration_need_to_be_able_to_invite" = "Du musst Benutzer einladen können um das zu tun."; +"widget_integration_need_to_be_able_to_invite" = "Du musst Benutzer einladen dürfen, um dies zu tun."; "widget_integration_unable_to_create" = "Erstellen des Widgets nicht möglich."; "widget_integration_failed_to_send_request" = "Senden der Anfrage fehlgeschlagen."; "widget_integration_room_not_recognised" = "Dieser Raum wurde nicht erkannt."; "widget_integration_positive_power_level" = "Berechtigungslevel muss eine positive Zahl sein."; "widget_integration_must_be_in_room" = "Du bist nicht in diesem Raum."; -"widget_integration_no_permission_in_room" = "Du hast keine Berechtigung dies in diesem Raum zu tun."; +"widget_integration_no_permission_in_room" = "Du bist nicht berechtigt, dies in diesem Raum zu tun."; "widget_integration_missing_room_id" = "room_id fehlt in der Anfrage."; "widget_integration_missing_user_id" = "user_id fehlt in der Anfrage."; "widget_integration_room_not_visible" = "Raum %@ ist nicht sichtbar."; @@ -502,7 +502,7 @@ // Group rooms "group_rooms_filter_rooms" = "Filtere Community-Räume"; "e2e_room_key_request_message_new_device" = "Du hast die neue Sitzung '%@' hinzugefügt, welche Verschlüsselungs-Schlüssel anfordert."; -"room_do_not_have_permission_to_post" = "Du hast keine Berechtigung Nachrichten in diesem Raum zu senden"; +"room_do_not_have_permission_to_post" = "Du bist nicht berechtigt, Nachrichten in diesem Raum zu senden"; "room_event_action_kick_prompt_reason" = "Grund für das Entfernen des Benutzers"; "room_event_action_ban_prompt_reason" = "Grund für die Verbannung der Person"; "room_action_send_photo_or_video" = "Foto oder Video senden"; @@ -532,8 +532,8 @@ "rerequest_keys_alert_title" = "Anfrage gesendet"; "rerequest_keys_alert_message" = "Bitte %@ auf einem anderen Gerät öffnen, das die Nachricht entschlüsseln kann, damit es die Schlüssel an diese Sitzung senden kann."; "room_message_reply_to_placeholder" = "Antwort senden (unverschlüsselt)…"; -"encrypted_room_message_reply_to_placeholder" = "Sende eine verschlüsselte Antwort…"; -"room_message_reply_to_short_placeholder" = "Sende eine Antwort…"; +"encrypted_room_message_reply_to_placeholder" = "Verschlüsselte Antwort senden …"; +"room_message_reply_to_short_placeholder" = "Antwort senden …"; "room_replacement_information" = "Dieser Raum wurde ersetzt und ist nicht länger aktiv."; "room_replacement_link" = "Die Konversation wird hier fortgesetzt."; "room_predecessor_information" = "Dieser Raum ist die Fortsetzung einer anderen Konversation."; @@ -743,8 +743,8 @@ "room_action_send_file" = "Datei senden"; "room_message_edits_history_title" = "Bearbeitungsverlauf"; // Widget -"widget_no_integrations_server_configured" = "Kein Integrationsserver konfiguriert"; -"widget_integrations_server_failed_to_connect" = "Verbindung zum Integrationsserver fehlgeschlagen"; +"widget_no_integrations_server_configured" = "Kein Integrations-Server konfiguriert"; +"widget_integrations_server_failed_to_connect" = "Verbindung zum Integrations-Server fehlgeschlagen"; "device_verification_security_advice" = "Für maximale Sicherheit empfehlen wir, dies persönlich zu tun oder ein anderes vertrauenswürdiges Kommunikationsmittel zu verwenden"; "device_verification_incoming_description_1" = "Überprüfe diese Sitzung, um sie als vertrauenswürdig zu markieren. Sitzungen von Partnern zu vertrauen gibt dir zusätzliche Sicherheit bei der Verwendung von Ende-zu-Ende verschlüsselten Nachrichten."; "device_verification_incoming_description_2" = "Wenn du diese Sitzung verifizierst, wird sie für dich und für dein Gegenüber als vertrauenswürdig gekennzeichnet."; @@ -821,7 +821,7 @@ "media_type_accessibility_video" = "Video"; "media_type_accessibility_location" = "Standort"; "media_type_accessibility_file" = "Datei"; -"media_type_accessibility_sticker" = "Aufkleber"; +"media_type_accessibility_sticker" = "Sticker"; "settings_identity_server_settings" = "IDENTITÄTSERVER"; "settings_three_pids_management_information_part1" = "Verwalte hier, mit welchen E-Mail-Adressen oder Telefonnummern du dich anmeldest, oder dein Konto wiederherstellen kannst. Kontrolliere, wer dich finden kann "; "settings_three_pids_management_information_part3" = "."; @@ -902,7 +902,7 @@ "room_participants_security_loading" = "Lade…"; "room_participants_security_information_room_not_encrypted" = "Nachrichten in diesem Raum sind nicht Ende-zu-Ende verschlüsselt."; "settings_security" = "SICHERHEIT"; -"settings_integrations_allow_description" = "Benutze einen Integrationsmanager (%@), um Bots, Bridges, Widgets und Aufkleberpakete zu verwalten.\n\nIntegrationsmanager erhalten Konfigurationsdaten und können Widgets verändern, Raum-Einladungen versenden sowie Berechtigungen in deinem Namen einstellen."; +"settings_integrations_allow_description" = "Nutze einen Integrationsassistenten (%@), um Bots, Brücken, Widgets und Sticker-Pakete zu verwalten.\n\nIntegrationsassistenten erhalten Konfigurationsdaten und können Widgets verändern, Raumeinladungen versenden sowie Berechtigungen in deinem Namen einstellen."; "settings_labs_enable_cross_signing" = "Aktiviere Cross-Signing, um deinen Gesprächspartner anstatt dessen Gerät zu verifizieren (in Entwicklung)"; // Security settings "security_settings_title" = "Sicherheit"; @@ -1301,8 +1301,8 @@ "settings_show_NSFW_public_rooms" = "Öffentliche Räume mit anstößigen Inhalte anzeigen"; "room_open_dialpad" = "Wähltastatur"; "room_place_voice_call" = "Sprachanruf"; -"room_unsent_messages_cancel_message" = "Bist du dir sicher alle nicht gesendete Nachrichten in diesem Raum zu löschen?"; -"room_unsent_messages_cancel_title" = "Lösche nicht gesendete Nachrichten"; +"room_unsent_messages_cancel_message" = "Bist du dir sicher, dass du alle nicht gesendeten Nachrichten in diesem Raum löschen möchtest?"; +"room_unsent_messages_cancel_title" = "Nicht gesendete Nachrichten löschen"; "callbar_return" = "Zurück"; "callbar_only_multiple_paused" = "%@ pausierte Anrufe"; "callbar_only_single_paused" = "Pausierter Anruf"; @@ -1483,7 +1483,7 @@ // Alert explaining what an identity server / integration manager is. "service_terms_modal_information_title_identity_server" = "Indentitätsserver"; -"service_terms_modal_description_integration_manager" = "Das erlaubt dir Bots, Bridges und Stickerpacks zu verwenden."; +"service_terms_modal_description_integration_manager" = "Dies wird dir die Verwendung von Bots, Brücken und Sticker-Paketen ermöglichen."; "service_terms_modal_description_identity_server" = "Dies erlaubt Personen, die deine Telefonnummer oder E-Mail in ihren Kontakten hat, dich zu finden."; "service_terms_modal_table_header_identity_server" = "NUTZUNGSBEDINGUNGEN IDENTITÄTSSERVER"; "service_terms_modal_table_header_integration_manager" = "NUTZUNGSBEDINGUNGEN INTEGRATIONSMANAGER"; @@ -1506,12 +1506,12 @@ "poll_edit_form_add_option" = "Option hinzufügen"; "poll_edit_form_option_number" = "Option %lu"; "poll_edit_form_question_or_topic" = "Frage oder Thematik"; -"room_event_action_end_poll" = "Umfrage beenden"; -"room_event_action_remove_poll" = "Umfrage entfernen"; +"room_event_action_end_poll" = "Abstimmung beenden"; +"room_event_action_remove_poll" = "Abstimmung entfernen"; // Mark: - Polls -"poll_edit_form_create_poll" = "Umfrage erstellen"; +"poll_edit_form_create_poll" = "Abstimmung erstellen"; "settings_labs_enabled_polls" = "Umfragen"; "share_extension_send_now" = "Jetzt senden"; "accessibility_button_label" = "Knopf"; @@ -1538,7 +1538,7 @@ "poll_edit_form_poll_question_or_topic" = "Frage oder Thema der Umfrage"; "poll_edit_form_input_placeholder" = "Schreib etwas"; "analytics_prompt_terms_link_upgrade" = "hier"; -"poll_timeline_not_closed_title" = "Fehler beim Beenden der Abstimmung"; +"poll_timeline_not_closed_title" = "Beenden der Abstimmung fehlgeschlagen"; "poll_timeline_vote_not_registered_subtitle" = "Wir konnten deine Stimme leider nicht erfassen. Versuche es bitte erneut"; "poll_timeline_total_final_results" = "Es wurden %lu Stimmen abgegeben"; "poll_timeline_total_final_results_one_vote" = "Es wurde 1 Stimme abgegeben"; @@ -1547,7 +1547,7 @@ "poll_timeline_not_closed_subtitle" = "Versuche es bitte erneut"; "poll_timeline_vote_not_registered_title" = "Stimme nicht erfasst"; "poll_edit_form_post_failure_subtitle" = "Versuche es bitte erneut"; -"poll_edit_form_post_failure_title" = "Fehler beim Senden der Abstimmung"; +"poll_edit_form_post_failure_title" = "Absenden der Abstimmung fehlgeschlagen"; "share_extension_low_quality_video_message" = "Für eine bessere Qualität sende es in %@ oder sende es in niedriger Qualität."; "share_extension_low_quality_video_title" = "Das Video wird in niedriger Qualität gesendet werden"; "analytics_prompt_stop" = "Teilen beenden"; @@ -1588,11 +1588,11 @@ "onboarding_splash_register_button_title" = "Konto erstellen"; "settings_enable_room_message_bubbles" = "Nachrichtenblasen"; "poll_edit_form_update_failure_subtitle" = "Bitte erneut versuchen"; -"poll_edit_form_poll_type" = "Umfragetyp"; -"poll_edit_form_poll_type_closed_description" = "Ergebnisse werden erst angezeigt, wenn du die Umfrage beendest"; -"poll_edit_form_poll_type_closed" = "Geschlossene Umfrage"; -"poll_edit_form_poll_type_open_description" = "Ergebnisse werden direkt nach Stimmabgabe angezeigt"; -"poll_edit_form_poll_type_open" = "Offene Umfrage"; +"poll_edit_form_poll_type" = "Abstimmungsart"; +"poll_edit_form_poll_type_closed_description" = "Die Ergebnisse werden erst sichtbar, sobald du die Umfrage beendest"; +"poll_edit_form_poll_type_closed" = "Abgeschlossene Abstimmung"; +"poll_edit_form_poll_type_open_description" = "Abstimmende können die Ergebnisse nach Stimmabgabe sehen"; +"poll_edit_form_poll_type_open" = "Laufende Abstimmung"; "poll_edit_form_update_failure_title" = "Aktualisierung der Umfrage fehlgeschlagen"; "threads_empty_tip" = "Hinweis: Tippe auf eine Nachricht und wähle „Thread“ um einen neuen zu starten."; "threads_empty_info_my" = "Antworte auf einen laufenden Thread oder tippe auf eine Nachricht und wähle „Thread“ um einen neuen zu starten."; @@ -1766,7 +1766,7 @@ "notice_room_history_visible_to_members_from_joined_point_for_dm" = "%@ hat den zukünftigen Verlauf für alle Raumteilnehmer ab deren Einladung sichtbar gemacht."; "notice_crypto_unable_to_decrypt" = "** Entschlüsselung nicht möglich: %@ **"; "notice_crypto_error_unknown_inbound_session_id" = "Die absendende Sitzung hat uns keine Schlüssel für diese Nachricht gesendet."; -"notice_sticker" = "Aufkleber"; +"notice_sticker" = "Sticker"; "notice_in_reply_to" = "Als Antwort auf"; // room display name "room_displayname_empty_room" = "Leerer Raum"; @@ -2365,7 +2365,7 @@ "spaces_explore_rooms_room_number" = "%@ Räume"; "spaces_create_space_title" = "Einen Space erstellen"; "spaces_add_space_title" = "Space erstellen"; -"space_invite_not_enough_permission" = "Du hast keine Berechtigung, Personen zu diesem Space einzuladen"; +"space_invite_not_enough_permission" = "Du hast keine Berechtigung, Personen in diesen Space einzuladen"; "room_invite_not_enough_permission" = "Du hast keine Berechtigung, Personen zu diesem Raum einzuladen"; "room_invite_to_room_option_detail" = "Sie werden kein Teil von %@ sein."; "room_invite_to_room_option_title" = "Nur zu diesem Raum"; diff --git a/Riot/Assets/et.lproj/Vector.strings b/Riot/Assets/et.lproj/Vector.strings index ea0fef48e..1dd7c1b42 100644 --- a/Riot/Assets/et.lproj/Vector.strings +++ b/Riot/Assets/et.lproj/Vector.strings @@ -2586,3 +2586,6 @@ "authentication_qr_login_loading_connecting_device" = "Loon ühendust seadmega"; "authentication_qr_login_confirm_alert" = "Palun vaata, et sa kindlasti tead, kust see QR-kood kuvatakse. Sellisel viisil seadmete sidumisel sa annad oma kasutajakontole täiemahulise ligipääsu."; "authentication_qr_login_confirm_subtitle" = "Kontrolli, et järgnev kood klapib teises seadmes kuvatava koodiga:"; +"deselect_all" = "Eemalda kõik valikud"; +"user_other_session_menu_select_sessions" = "Vali sessioonid"; +"user_other_session_selected_count" = "%@ valitud"; diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index 254398f9d..297ff79b0 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -2463,7 +2463,7 @@ "room_access_settings_screen_upgrade_alert_note" = "Houd er rekening mee dat bij het upgraden een nieuwe versie van de kamer wordt gemaakt. Alle huidige berichten blijven in deze gearchiveerde ruimte."; "room_access_settings_screen_upgrade_alert_message_no_param" = "Iedereen in een bovenliggende space kan deze ruimte vinden en er lid van worden. Het is niet nodig om iedereen handmatig uit te nodigen. U kunt dit op elk moment wijzigen in de kamerinstellingen."; "room_access_settings_screen_upgrade_alert_message" = "Iedereen in %@ kan deze ruimte vinden en er lid van worden - het is niet nodig om iedereen handmatig uit te nodigen. U kunt dit op elk moment wijzigen in de kamerinstellingen."; -"settings_presence_offline_mode_description" = "Indien ingeschakeld, verschijnt u altijd offline voor andere personen, zelfs wanneer u de applicatie gebruikt."; +"settings_presence_offline_mode_description" = "Indien ingeschakeld, verschijnt u altijd offline voor andere personen, zelfs wanneer u de toepassing gebruikt."; "settings_presence_offline_mode" = "Offline modus"; "settings_presence" = "Aanwezigheid"; "threads_discourage_information_2" = "\n\nWilt u toch threads inschakelen?"; @@ -2652,3 +2652,156 @@ // User sessions management "user_sessions_settings" = "Beheer sessies"; "invite_to" = "Uitnodigen %@"; +"room_event_encryption_info_key_authenticity_not_guaranteed" = "De authenticiteit van dit versleutelde bericht kan niet worden gegarandeerd op dit apparaat."; +"deselect_all" = "Deselecteer alles"; +"wysiwyg_composer_format_action_strikethrough" = "Onderstrepen formaat toepassen"; +"wysiwyg_composer_format_action_underline" = "Doorstrepen formaat toepassen"; +"wysiwyg_composer_format_action_italic" = "Cursief formaat toepassen"; + +// Formatting Actions +"wysiwyg_composer_format_action_bold" = "Vet formaat toepassen"; +"wysiwyg_composer_start_action_voice_broadcast" = "Spraakuitzending"; +"wysiwyg_composer_start_action_text_formatting" = "Tekst opmaak"; +"wysiwyg_composer_start_action_camera" = "Camera"; +"wysiwyg_composer_start_action_location" = "Locatie"; +"wysiwyg_composer_start_action_polls" = "Peilingen"; +"wysiwyg_composer_start_action_attachments" = "Bijlagen"; +"wysiwyg_composer_start_action_stickers" = "Stikkers"; + + +// Mark: - WYSIWYG Composer + +// Send Media Actions +"wysiwyg_composer_start_action_media_picker" = "Fotobibliotheek"; +"user_session_overview_session_details_button_title" = "Sessie details"; +"user_session_overview_session_title" = "Sessie"; +"user_session_overview_current_session_title" = "Huidige sessie"; +"user_session_details_application_url" = "URL"; +"user_session_details_application_version" = "Versie"; +"user_session_details_application_name" = "Naam"; +"user_session_details_device_os" = "Besturingssysteem"; +"user_session_details_device_browser" = "Browser"; +"user_session_details_device_model" = "Model"; +"user_session_details_device_ip_location" = "IP locatie"; +"user_session_details_device_ip_address" = "IP adres"; +"user_session_details_last_activity" = "Laatste activiteit"; +"user_session_details_session_section_footer" = "Kopieer alle gegevens door erop te tikken en ingedrukt te houden."; +"user_session_details_session_id" = "Sessie ID"; +"user_session_details_session_name" = "Sessie naam"; +"user_session_details_device_section_header" = "Apparaat"; +"device_name_unknown" = "Onbekende toepassing"; +"settings_labs_enable_new_app_layout" = "Nieuwe toepassing-indeling"; +"settings_labs_enable_new_client_info_feature" = "Noteer de naam, versie en url van de toepassing om sessies gemakkelijker te herkennen in sessiebeheer"; +"user_session_details_application_section_header" = "Toepassing"; +"user_session_details_session_section_header" = "Sessie"; +"user_session_details_title" = "Toon details"; +"device_type_name_unknown" = "Onbekend"; +"device_type_name_mobile" = "Mobiel"; +"device_type_name_web" = "Web"; +"device_type_name_desktop" = "Desktop"; +"device_name_mobile" = "%@ Mobiel"; +"device_name_web" = "%@ Web"; +"device_name_desktop" = "%@ Desktop"; +"user_inactive_session_item_with_date" = "Meer dan 90 dagen inactief (%@)"; +"user_inactive_session_item" = "90+ dagen inactief"; +"user_session_item_details_last_activity" = "Laatste activiteit %@"; + +/* %1$@ will be the verification state and %2$@ will be user_session_item_details_verification_unknown or user_other_session_current_session_details */ +"user_session_item_details" = "%1$@ · %2$@"; +// First item is client name and second item is session display name +"user_session_name" = "%@: %@"; +"user_other_session_menu_select_sessions" = "Selecteer sessies"; +"user_other_session_selected_count" = "%@ geselecteerd"; +"user_other_session_clear_filter" = "Leeg filter"; +"user_other_session_no_unverified_sessions" = "Geen niet geverifieerde sessies gevonden."; +"user_other_session_no_verified_sessions" = "Geen geverifieerde sessies gevonden."; +"user_other_session_no_inactive_sessions" = "Geen inactieve sessies gevonden."; +"user_other_session_filter_menu_inactive" = "Inactief"; +"user_other_session_filter_menu_unverified" = "Niet geverifieerd"; +"user_other_session_filter_menu_verified" = "Geverifieerd"; +"user_other_session_filter_menu_all" = "Alle sessies"; +"user_other_session_filter" = "Filter"; +"user_other_session_verified_sessions_header_subtitle" = "Voor de beste beveiliging logt u uit bij elke sessie die u niet meer herkent of gebruikt."; +"user_other_session_current_session_details" = "Uw huidige sessie"; +"user_other_session_unverified_sessions_header_subtitle" = "Verifieer uw sessies voor verbeterde beveiligde berichtenuitwisseling of meld u af bij sessies die u niet meer herkent of gebruikt."; +"user_other_session_security_recommendation_title" = "Beveiligingsaanbeveling"; +"user_session_push_notifications_message" = "Indien ingeschakeld, ontvangt deze sessie pushmeldingen."; +"user_session_push_notifications" = "Pushmeldingen"; +"user_other_session_verified_additional_info" = "Deze sessie is klaar voor beveiligde berichtenuitwisseling."; +"user_other_session_unverified_additional_info" = "Verifieer of meld u af bij deze sessie voor de beste beveiliging en betrouwbaarheid."; +"user_session_verification_unknown_additional_info" = "Verifieer uw huidige sessie om de verificatiestatus van deze sessie weer te geven."; +"user_session_unverified_additional_info" = "Verifieer uw huidige sessie voor verbeterde beveiligde berichtenuitwisseling."; +"user_session_verified_additional_info" = "Uw huidige sessie is klaar voor beveiligde berichtenuitwisseling."; +"user_session_learn_more" = "Meer lezen"; +"user_session_view_details" = "Bekijk details"; +"user_session_verify_action" = "Sessie verifiëren"; +"user_session_verification_unknown_short" = "Onbekend"; +"user_session_unverified_short" = "Niet geverifieerd"; +"user_session_verified_short" = "Geverifieerd"; +"user_session_verification_unknown" = "Onbekende verificatiestatus"; +"user_session_unverified" = "Niet geverifieerde sessie"; +"user_session_verified" = "Geverifieerde sessie"; +"user_sessions_view_all_action" = "Alles bekijken (%d)"; +"user_sessions_overview_link_device" = "Een apparaat koppelen"; +"user_sessions_overview_current_session_section_title" = "Huidige sessie"; +"user_sessions_overview_other_sessions_section_info" = "Voor de beste beveiliging verifieert u uw sessies en meldt u zich af bij elke sessie die u niet meer herkent of gebruikt."; +"user_sessions_overview_other_sessions_section_title" = "Andere sessies"; +"user_sessions_overview_security_recommendations_inactive_info" = "Overweeg om u af te melden bij oude sessies (90 dagen of ouder) die u niet meer gebruikt."; +"user_sessions_overview_security_recommendations_inactive_title" = "Inactieve sessies"; +"user_sessions_overview_security_recommendations_unverified_info" = "Verifieer of meld u af bij niet geverifieerde sessies."; +"user_sessions_overview_security_recommendations_unverified_title" = "Niet geverifieerde sessies"; +"user_sessions_overview_security_recommendations_section_info" = "Verbeter uw accountbeveiliging door deze aanbevelingen op te volgen."; +"user_sessions_overview_security_recommendations_section_title" = "Beveiligingsaanbevelingen"; + +// MARK: User sessions management + +// Parameter is the application display name (e.g. "Element") +"user_sessions_default_session_display_name" = "%@ iOS"; +"all_chats_user_menu_accessibility_label" = "Gebruikersmenu"; +"voice_broadcast_playback_loading_error" = "Kan deze spraakuitzending niet afspelen."; +"voice_broadcast_already_in_progress_message" = "U neemt al een spraakuitzending op. Beëindig uw huidige spraakuitzending om een nieuwe te starten."; +"voice_broadcast_blocked_by_someone_else_message" = "Iemand anders neemt al een spraakuitzending op. Wacht tot hun spraakuitzending is afgelopen om een nieuwe te starten."; +"voice_broadcast_permission_denied_message" = "U heeft niet de vereiste rechten om een spraakuitzending in deze kamer te starten. Neem contact op met een kamer beheerder om uw machtigingen te upgraden."; + +// Mark: - Voice broadcast +"voice_broadcast_unauthorized_title" = "Kan geen nieuwe spraakuitzending starten"; +"sign_out_confirmation_message" = "Weet u zeker dat u zich wilt afmelden?"; + +// MARK: Sign out warning + +"sign_out" = "Afmelden"; +"manage_session_rename" = "Sessie hernoemen"; +"manage_session_name_info_link" = "Lees meer"; +/* The placeholder will be replaces with manage_session_name_info_link */ +"manage_session_name_info" = "Houd er rekening mee dat sessienamen ook zichtbaar zijn voor mensen met wie u communiceert. %@"; +"manage_session_name_hint" = "Met aangepaste sessienamen kunt u uw apparaten gemakkelijker herkennen."; +"settings_labs_enable_voice_broadcast" = "Voice-uitzending (in actieve ontwikkeling)"; +"settings_labs_enable_wysiwyg_composer" = "Probeer de rich-text-editor (platte tekst-modus komt binnenkort)"; +"settings_labs_enable_new_session_manager" = "Nieuwe sessiemanager"; +"room_first_message_placeholder" = "Stuur uw eerste bericht…"; +"authentication_qr_login_failure_retry" = "Probeer het nog eens"; +"authentication_qr_login_failure_request_timed_out" = "De koppeling is niet binnen de vereiste tijd voltooid."; +"authentication_qr_login_failure_request_denied" = "Het verzoek is geweigerd op het andere apparaat."; +"authentication_qr_login_failure_invalid_qr" = "QR-code is ongeldig."; +"authentication_qr_login_failure_title" = "Koppelen mislukt"; +"authentication_qr_login_loading_signed_in" = "U bent nu aangemeld op uw andere apparaat."; +"authentication_qr_login_loading_waiting_signin" = "Wachten tot het apparaat zich aanmeldt."; +"authentication_qr_login_loading_connecting_device" = "Verbinden met apparaat"; +"authentication_qr_login_confirm_alert" = "Zorg ervoor dat u de herkomst van deze code kent. Door apparaten te koppelen, geeft u iemand volledige toegang tot uw account."; +"authentication_qr_login_confirm_subtitle" = "Controleer of de onderstaande code overeenkomt met uw andere apparaat:"; +"authentication_qr_login_confirm_title" = "Beveiligde verbinding tot stand gebracht"; +"authentication_qr_login_scan_subtitle" = "Positioneer de QR-code in het vierkant hieronder"; +"authentication_qr_login_scan_title" = "Scan QR-code"; +"authentication_qr_login_display_step2" = "Selecteer 'Aanmelden met QR-code'"; +"authentication_qr_login_display_step1" = "Open Element op uw andere apparaat"; +"authentication_qr_login_display_subtitle" = "Scan de onderstaande QR-code met uw apparaat dat is uitgelogd."; +"authentication_qr_login_display_title" = "Een apparaat koppelen"; +"authentication_qr_login_start_display_qr" = "QR-code weergeven op dit apparaat"; +"authentication_qr_login_start_need_alternative" = "Een alternatieve methode nodig?"; +"authentication_qr_login_start_step4" = "Selecteer 'Toon QR-code op dit apparaat'"; +"authentication_qr_login_start_step3" = "Selecteer 'Een apparaat koppelen'"; +"authentication_qr_login_start_step2" = "Ga naar Instellingen -> Beveiliging en privacy"; +"authentication_qr_login_start_step1" = "Open Element op uw andere apparaat"; +"authentication_qr_login_start_subtitle" = "Gebruik de camera op dit apparaat om de QR-code te scannen die op uw andere apparaat wordt weergegeven:"; +"authentication_qr_login_start_title" = "Scan QR-code"; +"authentication_login_with_qr" = "Log in met QR-code"; diff --git a/Riot/Assets/pt_BR.lproj/Vector.strings b/Riot/Assets/pt_BR.lproj/Vector.strings index 5387d9d1c..3741d9841 100644 --- a/Riot/Assets/pt_BR.lproj/Vector.strings +++ b/Riot/Assets/pt_BR.lproj/Vector.strings @@ -1688,7 +1688,7 @@ "invite_user" = "Convidar Usuária(o) matrix"; "reset_to_default" = "Resettar para default"; "resend_message" = "Reenviar a mensagem"; -"select_all" = "Selecionar Todas"; +"select_all" = "Selecionar Todas(os)"; "cancel_upload" = "Cancelar Upload"; "cancel_download" = "Cancelar Download"; "show_details" = "Mostrar Detalhes"; @@ -2615,3 +2615,6 @@ // Mark: - Voice broadcast "voice_broadcast_unauthorized_title" = "Não dá para começar um novo broadcast de voz"; "settings_labs_enable_voice_broadcast" = "Broadcast de voz (sob desenvolvimento ativo)"; +"deselect_all" = "Desselecionar Todas(os)"; +"user_other_session_menu_select_sessions" = "Selecionar sessões"; +"user_other_session_selected_count" = "%@ selecionadas"; diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 4ed6ddf02..63d2afe50 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -2288,9 +2288,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // Stay in launching during the first server sync if the store is empty. isLaunching = (mainSession.rooms.count == 0 && launchAnimationContainerView); - if (mainSession.crypto.crossSigning && mainSession.crypto.crossSigning.state == MXCrossSigningStateCrossSigningExists) + if (mainSession.crypto.crossSigning && mainSession.crypto.crossSigning.state == MXCrossSigningStateCrossSigningExists && [mainSession.crypto isKindOfClass:[MXLegacyCrypto class]]) { - [mainSession.crypto setOutgoingKeyRequestsEnabled:NO onComplete:nil]; + [(MXLegacyCrypto *)mainSession.crypto setOutgoingKeyRequestsEnabled:NO onComplete:nil]; } break; case MXSessionStateRunning: @@ -2503,6 +2503,12 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni - (void)checkLocalPrivateKeysInSession:(MXSession*)mxSession { + if (![mxSession.crypto isKindOfClass:[MXLegacyCrypto class]]) + { + return; + } + MXLegacyCrypto *crypto = (MXLegacyCrypto *)mxSession.crypto; + MXRecoveryService *recoveryService = mxSession.crypto.recoveryService; NSUInteger keysCount = 0; if ([recoveryService hasSecretWithSecretId:MXSecretId.keyBackup]) @@ -2523,7 +2529,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni { // We should have 3 of them. If not, request them again as mitigation MXLogDebug(@"[AppDelegate] checkLocalPrivateKeysInSession: request keys because keysCount = %@", @(keysCount)); - [mxSession.crypto requestAllPrivateKeys]; + [crypto requestAllPrivateKeys]; } } @@ -3483,17 +3489,24 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni MXLogDebug(@"[AppDelegate] checkPendingRoomKeyRequestsInSession called while the app is not active. Ignore it."); return; } + + if (![mxSession.crypto isKindOfClass:[MXLegacyCrypto class]]) + { + MXLogDebug(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: Only legacy crypto allows manually accepting/rejecting key requests"); + return; + } + MXLegacyCrypto *crypto = (MXLegacyCrypto *)mxSession.crypto; MXWeakify(self); - [mxSession.crypto pendingKeyRequests:^(MXUsersDevicesMap *> *pendingKeyRequests) { + [crypto pendingKeyRequests:^(MXUsersDevicesMap *> *pendingKeyRequests) { MXStrongifyAndReturnIfNil(self); MXLogDebug(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: cross-signing state: %ld, pendingKeyRequests.count: %@. Already displayed: %@", - mxSession.crypto.crossSigning.state, + crypto.crossSigning.state, @(pendingKeyRequests.count), self->roomKeyRequestViewController ? @"YES" : @"NO"); - if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state == MXCrossSigningStateNotBootstrapped) + if (!crypto.crossSigning || crypto.crossSigning.state == MXCrossSigningStateNotBootstrapped) { if (self->roomKeyRequestViewController) { @@ -3523,13 +3536,13 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // Give the client a chance to refresh the device list MXWeakify(self); - [mxSession.crypto downloadKeys:@[userId] forceDownload:NO success:^(MXUsersDevicesMap *usersDevicesInfoMap, NSDictionary *crossSigningKeysMap) { + [crypto downloadKeys:@[userId] forceDownload:NO success:^(MXUsersDevicesMap *usersDevicesInfoMap, NSDictionary *crossSigningKeysMap) { MXStrongifyAndReturnIfNil(self); MXDeviceInfo *deviceInfo = [usersDevicesInfoMap objectForDevice:deviceId forUser:userId]; if (deviceInfo) { - if (!mxSession.crypto.crossSigning || mxSession.crypto.crossSigning.state == MXCrossSigningStateNotBootstrapped) + if (!crypto.crossSigning || crypto.crossSigning.state == MXCrossSigningStateNotBootstrapped) { BOOL wasNewDevice = (deviceInfo.trustLevel.localVerificationStatus == MXDeviceUnknown); @@ -3537,7 +3550,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni { MXLogDebug(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: Open dialog for %@", deviceInfo); - self->roomKeyRequestViewController = [[RoomKeyRequestViewController alloc] initWithDeviceInfo:deviceInfo wasNewDevice:wasNewDevice andMatrixSession:mxSession onComplete:^{ + self->roomKeyRequestViewController = [[RoomKeyRequestViewController alloc] initWithDeviceInfo:deviceInfo wasNewDevice:wasNewDevice andMatrixSession:mxSession crypto:crypto onComplete:^{ self->roomKeyRequestViewController = nil; @@ -3551,7 +3564,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // If the device was new before, it's not any more. if (wasNewDevice) { - [mxSession.crypto setDeviceVerification:MXDeviceUnverified forDevice:deviceId ofUser:userId success:openDialog failure:nil]; + [crypto setDeviceVerification:MXDeviceUnverified forDevice:deviceId ofUser:userId success:openDialog failure:nil]; } else { @@ -3560,13 +3573,13 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } else if (deviceInfo.trustLevel.isVerified) { - [mxSession.crypto acceptAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ + [crypto acceptAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ [self checkPendingRoomKeyRequests]; }]; } else { - [mxSession.crypto ignoreAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ + [crypto ignoreAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ [self checkPendingRoomKeyRequests]; }]; } @@ -3574,7 +3587,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni else { MXLogDebug(@"[AppDelegate] checkPendingRoomKeyRequestsInSession: No details found for device %@:%@", userId, deviceId); - [mxSession.crypto ignoreAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ + [crypto ignoreAllPendingKeyRequestsFromUser:userId andDevice:deviceId onComplete:^{ [self checkPendingRoomKeyRequests]; }]; } @@ -3754,10 +3767,10 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni - (void)keyVerificationCoordinatorBridgePresenterDelegateDidComplete:(KeyVerificationCoordinatorBridgePresenter *)coordinatorBridgePresenter otherUserId:(NSString * _Nonnull)otherUserId otherDeviceId:(NSString * _Nonnull)otherDeviceId { id crypto = coordinatorBridgePresenter.session.crypto; - if (!crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled) + if ([crypto isKindOfClass:[MXLegacyCrypto class]] && (!crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled)) { MXLogDebug(@"[AppDelegate][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys"); - [crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; + [(MXLegacyCrypto *)crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; } [self dismissKeyVerificationCoordinatorBridgePresenter]; } diff --git a/Riot/Modules/Authentication/AuthenticationCoordinator.swift b/Riot/Modules/Authentication/AuthenticationCoordinator.swift index 47ed8bfab..5aa6b3731 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinator.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinator.swift @@ -758,8 +758,8 @@ extension AuthenticationCoordinator: AuthenticationServiceDelegate { // MARK: - KeyVerificationCoordinatorDelegate extension AuthenticationCoordinator: KeyVerificationCoordinatorDelegate { func keyVerificationCoordinatorDidComplete(_ coordinator: KeyVerificationCoordinatorType, otherUserId: String, otherDeviceId: String) { - if let crypto = session?.crypto, - !crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled { + if let crypto = session?.crypto as? MXLegacyCrypto, let backup = crypto.backup, + !backup.hasPrivateKeyInCryptoStore || !backup.enabled { MXLog.debug("[AuthenticationCoordinator][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys") crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) } @@ -810,5 +810,4 @@ extension AuthenticationCoordinator: AuthFallBackViewControllerDelegate { func authFallBackViewControllerDidClose(_ authFallBackViewController: AuthFallBackViewController) { dismissFallback() } - } diff --git a/Riot/Modules/Authentication/Legacy/LegacyAuthenticationCoordinator.swift b/Riot/Modules/Authentication/Legacy/LegacyAuthenticationCoordinator.swift index 13b776c4e..e8ca770ab 100644 --- a/Riot/Modules/Authentication/Legacy/LegacyAuthenticationCoordinator.swift +++ b/Riot/Modules/Authentication/Legacy/LegacyAuthenticationCoordinator.swift @@ -219,8 +219,8 @@ extension LegacyAuthenticationCoordinator: AuthenticationViewControllerDelegate // MARK: - KeyVerificationCoordinatorDelegate extension LegacyAuthenticationCoordinator: KeyVerificationCoordinatorDelegate { func keyVerificationCoordinatorDidComplete(_ coordinator: KeyVerificationCoordinatorType, otherUserId: String, otherDeviceId: String) { - if let crypto = session?.crypto, - !crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled { + if let crypto = session?.crypto as? MXLegacyCrypto, let backup = crypto.backup, + !backup.hasPrivateKeyInCryptoStore || !backup.enabled { MXLog.debug("[LegacyAuthenticationCoordinator][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys") crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) } diff --git a/Riot/Modules/Authentication/SessionVerificationListener.swift b/Riot/Modules/Authentication/SessionVerificationListener.swift index 7d5d7f48b..214c76695 100644 --- a/Riot/Modules/Authentication/SessionVerificationListener.swift +++ b/Riot/Modules/Authentication/SessionVerificationListener.swift @@ -69,7 +69,7 @@ class SessionVerificationListener { } if session.state == .storeDataReady { - if let crypto = session.crypto, crypto.crossSigning != nil { + if let crypto = session.crypto as? MXLegacyCrypto { // Do not make key share requests while the "Complete security" is not complete. // If the device is self-verified, the SDK will restore the existing key backup. // Then, it will re-enable outgoing key share requests @@ -78,7 +78,8 @@ class SessionVerificationListener { } else if session.state == .running { unregisterSessionStateChangeNotification() - if let crypto = session.crypto, let crossSigning = crypto.crossSigning { + if let crypto = session.crypto { + let crossSigning = crypto.crossSigning crossSigning.refreshState { [weak self] stateUpdated in guard let self = self else { return } @@ -100,7 +101,7 @@ class SessionVerificationListener { self.completion?(.authenticationIsComplete) } failure: { error in MXLog.error("[SessionVerificationListener] sessionStateDidChange: Bootstrap failed", context: error) - crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + (crypto as? MXLegacyCrypto)?.setOutgoingKeyRequestsEnabled(true, onComplete: nil) self.completion?(.authenticationIsComplete) } } else { @@ -110,12 +111,12 @@ class SessionVerificationListener { self.completion?(.authenticationIsComplete) } failure: { error in MXLog.error("[SessionVerificationListener] sessionStateDidChange: Do not know how to bootstrap cross-signing. Skip it.") - crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + (crypto as? MXLegacyCrypto)?.setOutgoingKeyRequestsEnabled(true, onComplete: nil) self.completion?(.authenticationIsComplete) } } } else { - crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + (crypto as? MXLegacyCrypto)?.setOutgoingKeyRequestsEnabled(true, onComplete: nil) self.completion?(.authenticationIsComplete) } case .crossSigningExists: @@ -124,12 +125,12 @@ class SessionVerificationListener { default: MXLog.debug("[SessionVerificationListener] sessionStateDidChange: Nothing to do") - crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + (crypto as? MXLegacyCrypto)?.setOutgoingKeyRequestsEnabled(true, onComplete: nil) self.completion?(.authenticationIsComplete) } } failure: { [weak self] error in MXLog.error("[SessionVerificationListener] sessionStateDidChange: Fail to refresh crypto state", context: error) - crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + (crypto as? MXLegacyCrypto)?.setOutgoingKeyRequestsEnabled(true, onComplete: nil) self?.completion?(.authenticationIsComplete) } } else { diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 71c52ba72..a8019c06c 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -373,7 +373,12 @@ CallAudioRouteMenuViewDelegate> // Acknowledge the existence of all devices [self startActivityIndicator]; - [self.mainSession.crypto setDevicesKnown:unknownDevices complete:^{ + if (![self.mainSession.crypto isKindOfClass:[MXLegacyCrypto class]]) + { + MXLogFailure(@"[CallViewController] call: Only legacy crypto supports manual setting of known devices"); + return; + } + [(MXLegacyCrypto *)self.mainSession.crypto setDevicesKnown:unknownDevices complete:^{ [self stopActivityIndicator]; diff --git a/Riot/Modules/CrossSigning/CrossSigningService.swift b/Riot/Modules/CrossSigning/CrossSigningService.swift index c063f4b0b..a4df60aaa 100644 --- a/Riot/Modules/CrossSigning/CrossSigningService.swift +++ b/Riot/Modules/CrossSigning/CrossSigningService.swift @@ -85,7 +85,7 @@ final class CrossSigningService: NSObject { @discardableResult func setupCrossSigningWithoutAuthentication(for session: MXSession, success: @escaping (() -> Void), failure: @escaping ((Error) -> Void)) -> MXHTTPOperation? { - guard let crossSigning = session.crypto.crossSigning else { + guard let crossSigning = session.crypto?.crossSigning else { failure(CrossSigningServiceError.unknown) return nil } diff --git a/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinator.swift b/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinator.swift index f545b2e44..2877de09d 100644 --- a/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinator.swift +++ b/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinator.swift @@ -72,7 +72,7 @@ final class CrossSigningSetupCoordinator: CrossSigningSetupCoordinatorType { } private func setupCrossSigning(with authenticationParameters: [String: Any]) { - guard let crossSigning = self.parameters.session.crypto.crossSigning else { + guard let crossSigning = self.parameters.session.crypto?.crossSigning else { return } diff --git a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift index d7d0a9a31..82404834e 100644 --- a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift +++ b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift @@ -22,7 +22,7 @@ final class KeyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType { // MARK: Private - private let session: MXSession + private let keyBackup: MXKeyBackup private let navigationRouter: NavigationRouterType private let keyBackupVersion: MXKeyBackupVersion @@ -34,8 +34,8 @@ final class KeyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType { // MARK: - Setup - init(session: MXSession, keyBackupVersion: MXKeyBackupVersion, navigationRouter: NavigationRouterType? = nil) { - self.session = session + init(keyBackup: MXKeyBackup, keyBackupVersion: MXKeyBackupVersion, navigationRouter: NavigationRouterType? = nil) { + self.keyBackup = keyBackup self.keyBackupVersion = keyBackupVersion if let navigationRouter = navigationRouter { @@ -52,7 +52,7 @@ final class KeyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType { let rootCoordinator: Coordinator & Presentable // Check if we have the private key locally - if self.session.crypto.backup.hasPrivateKeyInCryptoStore { + if keyBackup.hasPrivateKeyInCryptoStore { rootCoordinator = self.createRecoverFromPrivateKeyCoordinator() } else { rootCoordinator = self.createRecoverWithUserInteractionCoordinator() @@ -93,19 +93,19 @@ final class KeyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType { } private func createRecoverFromPrivateKeyCoordinator() -> KeyBackupRecoverFromPrivateKeyCoordinator { - let coordinator = KeyBackupRecoverFromPrivateKeyCoordinator(keyBackup: self.session.crypto.backup, keyBackupVersion: self.keyBackupVersion) + let coordinator = KeyBackupRecoverFromPrivateKeyCoordinator(keyBackup: keyBackup, keyBackupVersion: self.keyBackupVersion) coordinator.delegate = self return coordinator } private func createRecoverFromPassphraseCoordinator() -> KeyBackupRecoverFromPassphraseCoordinator { - let coordinator = KeyBackupRecoverFromPassphraseCoordinator(keyBackup: self.session.crypto.backup, keyBackupVersion: self.keyBackupVersion) + let coordinator = KeyBackupRecoverFromPassphraseCoordinator(keyBackup: keyBackup, keyBackupVersion: self.keyBackupVersion) coordinator.delegate = self return coordinator } private func createRecoverFromRecoveryKeyCoordinator() -> KeyBackupRecoverFromRecoveryKeyCoordinator { - let coordinator = KeyBackupRecoverFromRecoveryKeyCoordinator(keyBackup: self.session.crypto.backup, keyBackupVersion: self.keyBackupVersion) + let coordinator = KeyBackupRecoverFromRecoveryKeyCoordinator(keyBackup: keyBackup, keyBackupVersion: self.keyBackupVersion) coordinator.delegate = self return coordinator } diff --git a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorBridgePresenter.swift b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorBridgePresenter.swift index a06e9befd..2d5be4578 100644 --- a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorBridgePresenter.swift +++ b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorBridgePresenter.swift @@ -49,7 +49,12 @@ final class KeyBackupRecoverCoordinatorBridgePresenter: NSObject { // MARK: - Public func present(from viewController: UIViewController, animated: Bool) { - let keyBackupSetupCoordinator = KeyBackupRecoverCoordinator(session: self.session, keyBackupVersion: keyBackupVersion) + guard let keyBackup = session.crypto?.backup else { + MXLog.failure("[KeyBackupRecoverCoordinatorBridgePresenter] Cannot setup backups without backup module") + return + } + + let keyBackupSetupCoordinator = KeyBackupRecoverCoordinator(keyBackup: keyBackup, keyBackupVersion: keyBackupVersion) keyBackupSetupCoordinator.delegate = self viewController.present(keyBackupSetupCoordinator.toPresentable(), animated: animated, completion: nil) keyBackupSetupCoordinator.start() @@ -58,12 +63,16 @@ final class KeyBackupRecoverCoordinatorBridgePresenter: NSObject { } func push(from navigationController: UINavigationController, animated: Bool) { + guard let keyBackup = session.crypto?.backup else { + MXLog.failure("[KeyBackupRecoverCoordinatorBridgePresenter] Cannot setup backups without backup module") + return + } MXLog.debug("[KeyBackupRecoverCoordinatorBridgePresenter] Push complete security from \(navigationController)") let navigationRouter = NavigationRouterStore.shared.navigationRouter(for: navigationController) - let keyBackupSetupCoordinator = KeyBackupRecoverCoordinator(session: self.session, keyBackupVersion: keyBackupVersion, navigationRouter: navigationRouter) + let keyBackupSetupCoordinator = KeyBackupRecoverCoordinator(keyBackup: keyBackup, keyBackupVersion: keyBackupVersion, navigationRouter: navigationRouter) keyBackupSetupCoordinator.delegate = self keyBackupSetupCoordinator.start() // Will trigger view controller push diff --git a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift index 03171ebd2..aab964c2f 100644 --- a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift +++ b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift @@ -66,7 +66,7 @@ final class KeyBackupSetupCoordinator: KeyBackupSetupCoordinatorType { private func createSetupIntroViewController() -> KeyBackupSetupIntroViewController { - let backupState = self.session.crypto.backup?.state ?? MXKeyBackupStateUnknown + let backupState = self.session.crypto?.backup?.state ?? MXKeyBackupStateUnknown let isABackupAlreadyExists: Bool switch backupState { @@ -99,7 +99,12 @@ final class KeyBackupSetupCoordinator: KeyBackupSetupCoordinatorType { } private func showSetupPassphrase(animated: Bool) { - let keyBackupSetupPassphraseCoordinator = KeyBackupSetupPassphraseCoordinator(session: self.session) + guard let keyBackup = self.session.crypto?.backup else { + MXLog.failure("[KeyBackupSetupCoordinator] Cannot setup backups without backup module") + return + } + + let keyBackupSetupPassphraseCoordinator = KeyBackupSetupPassphraseCoordinator(keyBackup: keyBackup) keyBackupSetupPassphraseCoordinator.delegate = self keyBackupSetupPassphraseCoordinator.start() @@ -130,7 +135,7 @@ final class KeyBackupSetupCoordinator: KeyBackupSetupCoordinatorType { } private func createKeyBackupUsingSecureBackup(privateKey: Data, completion: @escaping (Result) -> Void) { - guard let keyBackup = session.crypto.backup, let recoveryService = session.crypto.recoveryService else { + guard let keyBackup = session.crypto?.backup, let recoveryService = session.crypto?.recoveryService else { return } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift index ea0d2b549..f9c0342be 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift @@ -23,7 +23,6 @@ final class KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordin // MARK: Private - private let session: MXSession private var keyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModelType private let keyBackupSetupPassphraseViewController: KeyBackupSetupPassphraseViewController @@ -35,10 +34,8 @@ final class KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordin // MARK: - Setup - init(session: MXSession) { - self.session = session - - let keyBackupSetupPassphraseViewModel = KeyBackupSetupPassphraseViewModel(keyBackup: self.session.crypto.backup) + init(keyBackup: MXKeyBackup) { + let keyBackupSetupPassphraseViewModel = KeyBackupSetupPassphraseViewModel(keyBackup: keyBackup) let keyBackupSetupPassphraseViewController = KeyBackupSetupPassphraseViewController.instantiate(with: keyBackupSetupPassphraseViewModel) self.keyBackupSetupPassphraseViewModel = keyBackupSetupPassphraseViewModel self.keyBackupSetupPassphraseViewController = keyBackupSetupPassphraseViewController diff --git a/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingViewModel.swift b/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingViewModel.swift index b2874db8f..7db1624c9 100644 --- a/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingViewModel.swift +++ b/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingViewModel.swift @@ -19,7 +19,6 @@ import Foundation enum KeyVerificationDataLoadingViewModelError: Error { - case unknown case transactionCancelled case transactionCancelledByMe(reason: MXTransactionCancelCode) } @@ -137,9 +136,7 @@ final class KeyVerificationDataLoadingViewModel: KeyVerificationDataLoadingViewM return } - let finalError = error ?? KeyVerificationDataLoadingViewModelError.unknown - - sself.update(viewState: .error(finalError)) + sself.update(viewState: .error(error)) }) } else { diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift index 29c312bfc..b064d4f84 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift @@ -92,21 +92,29 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai // be sure that session has completed its first sync if session.state >= .running { - // Always send request instead of waiting for an incoming one as per recent EW changes - MXLog.debug("[KeyVerificationSelfVerifyWaitViewModel] loadData: Send a verification request to all devices instead of waiting") - - let keyVerificationService = KeyVerificationService() - self.verificationManager.requestVerificationByToDevice(withUserId: self.session.myUserId, deviceIds: nil, methods: keyVerificationService.supportedKeyVerificationMethods(), success: { [weak self] (keyVerificationRequest) in - guard let self = self else { - return - } + if let existingRequest = verificationManager.pendingRequests.first(where: { $0.isFromMyUser && !$0.isFromMyDevice && $0.state == MXKeyVerificationRequestStatePending }) { + MXLog.debug("[KeyVerificationSelfVerifyWaitViewModel] loadData: Accepting an existing self-verification request instead of starting a new one") - self.keyVerificationRequest = keyVerificationRequest + registerTransactionDidStateChangeNotification() + acceptKeyVerificationRequest(existingRequest) + } else { - }, failure: { [weak self] error in - self?.update(viewState: .error(error)) - }) - continueLoadData() + // Always send request instead of waiting for an incoming one as per recent EW changes + MXLog.debug("[KeyVerificationSelfVerifyWaitViewModel] loadData: Send a verification request to all devices instead of waiting") + + let keyVerificationService = KeyVerificationService() + self.verificationManager.requestVerificationByToDevice(withUserId: self.session.myUserId, deviceIds: nil, methods: keyVerificationService.supportedKeyVerificationMethods(), success: { [weak self] (keyVerificationRequest) in + guard let self = self else { + return + } + + self.keyVerificationRequest = keyVerificationRequest + + }, failure: { [weak self] error in + self?.update(viewState: .error(error)) + }) + continueLoadData() + } } else { // show loader self.update(viewState: .secretsRecoveryCheckingAvailability(VectorL10n.deviceVerificationSelfVerifyWaitRecoverSecretsCheckingAvailability)) diff --git a/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusViewModel.swift b/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusViewModel.swift index 104da3b32..a46b30555 100644 --- a/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusViewModel.swift +++ b/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusViewModel.swift @@ -18,10 +18,6 @@ import Foundation -enum UserVerificationSessionsStatusViewModelError: Error { - case unknown -} - final class UserVerificationSessionsStatusViewModel: UserVerificationSessionsStatusViewModelType { // MARK: - Properties @@ -103,7 +99,7 @@ final class UserVerificationSessionsStatusViewModel: UserVerificationSessionsSta } private func getDevicesFromCache(for userId: String) -> [MXDeviceInfo] { - guard let deviceInfoMap = self.session.crypto.devices(forUser: self.userId) else { + guard let deviceInfoMap = self.session.crypto?.devices(forUser: self.userId) else { return [] } return Array(deviceInfoMap.values) @@ -128,9 +124,7 @@ final class UserVerificationSessionsStatusViewModel: UserVerificationSessionsSta completion(.success(sessionsViewData)) }, failure: { error in - - let finalError = error ?? UserVerificationSessionsStatusViewModelError.unknown - completion(.failure(finalError)) + completion(.failure(error)) }) return httpOperation diff --git a/Riot/Modules/MatrixKit/Models/Account/MXKAccount.m b/Riot/Modules/MatrixKit/Models/Account/MXKAccount.m index cec79f31c..97cc2fb5c 100644 --- a/Riot/Modules/MatrixKit/Models/Account/MXKAccount.m +++ b/Riot/Modules/MatrixKit/Models/Account/MXKAccount.m @@ -952,7 +952,10 @@ static NSArray *initialSyncSilentErrorsHTTPStatusCodes; { // Force a reload of device keys at the next session start. // This will fix potential UISIs other peoples receive for our messages. - [mxSession.crypto resetDeviceKeys]; + if ([mxSession.crypto isKindOfClass:[MXLegacyCrypto class]]) + { + [(MXLegacyCrypto *)mxSession.crypto resetDeviceKeys]; + } // Clean other stores [mxSession.scanManager deleteAllAntivirusScans]; diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 4782f6fde..2149ecaa4 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -6255,7 +6255,13 @@ static CGSize kThreadListBarButtonItemImageSize; // Acknowledge the existence of all devices [self startActivityIndicator]; - [self.mainSession.crypto setDevicesKnown:self->unknownDevices complete:^{ + + if (![self.mainSession.crypto isKindOfClass:[MXLegacyCrypto class]]) + { + MXLogFailure(@"[RoomVC] eventDidChangeSentState: Only legacy crypto supports manual setting of known devices"); + return; + } + [(MXLegacyCrypto *)self.mainSession.crypto setDevicesKnown:self->unknownDevices complete:^{ self->unknownDevices = nil; [self stopActivityIndicator]; diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h index be19d7b71..e9db3a583 100644 --- a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h +++ b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h @@ -39,10 +39,15 @@ @param deviceInfo the device to share keys to. @param wasNewDevice flag indicating whether this is the first time we meet the device. @param session the related matrix session. + @param crypto the related (legacy) crypto module @param onComplete a block called when the the dialog is closed. @return the newly created instance. */ -- (instancetype)initWithDeviceInfo:(MXDeviceInfo*)deviceInfo wasNewDevice:(BOOL)wasNewDevice andMatrixSession:(MXSession*)session onComplete:(void (^)(void))onComplete; +- (instancetype)initWithDeviceInfo:(MXDeviceInfo*)deviceInfo + wasNewDevice:(BOOL)wasNewDevice + andMatrixSession:(MXSession*)session + crypto:(MXLegacyCrypto *)crypto + onComplete:(void (^)(void))onComplete; /** Show the dialog in a modal way. diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m index 91f62a8d6..6f638bd78 100644 --- a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m +++ b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m @@ -26,16 +26,24 @@ BOOL wasNewDevice; } + +@property (nonatomic, strong) MXLegacyCrypto *crypto; + @end @implementation RoomKeyRequestViewController -- (instancetype)initWithDeviceInfo:(MXDeviceInfo *)deviceInfo wasNewDevice:(BOOL)theWasNewDevice andMatrixSession:(MXSession *)session onComplete:(void (^)(void))onCompleteBlock +- (instancetype)initWithDeviceInfo:(MXDeviceInfo *)deviceInfo + wasNewDevice:(BOOL)theWasNewDevice + andMatrixSession:(MXSession *)session + crypto:(MXLegacyCrypto *)crypto + onComplete:(void (^)(void))onCompleteBlock { self = [super init]; if (self) { _mxSession = session; + _crypto = crypto; _device = deviceInfo; wasNewDevice = theWasNewDevice; onComplete = onCompleteBlock; @@ -90,7 +98,7 @@ self->_alertController = nil; // Accept the received requests from this device - [self.mxSession.crypto acceptAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ + [self.crypto acceptAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ self->onComplete(); }]; @@ -108,7 +116,7 @@ self->_alertController = nil; // Ignore all pending requests from this device - [self.mxSession.crypto ignoreAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ + [self.crypto ignoreAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ self->onComplete(); }]; @@ -160,14 +168,14 @@ keyVerificationCoordinatorBridgePresenter = nil; // Check device new status - [self.mxSession.crypto downloadKeys:@[self.device.userId] forceDownload:NO success:^(MXUsersDevicesMap *usersDevicesInfoMap, NSDictionary *crossSigningKeysMap) { + [self.crypto downloadKeys:@[self.device.userId] forceDownload:NO success:^(MXUsersDevicesMap *usersDevicesInfoMap, NSDictionary *crossSigningKeysMap) { MXDeviceInfo *deviceInfo = [usersDevicesInfoMap objectForDevice:self.device.deviceId forUser:self.device.userId]; if (deviceInfo && deviceInfo.trustLevel.localVerificationStatus == MXDeviceVerified) { // Accept the received requests from this device // As the device is now verified, all other key requests will be automatically accepted. - [self.mxSession.crypto acceptAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ + [self.crypto acceptAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ self->onComplete(); }]; diff --git a/Riot/Modules/Secrets/Reset/SecretsResetViewModel.swift b/Riot/Modules/Secrets/Reset/SecretsResetViewModel.swift index 05b691f3a..2e8e7604c 100644 --- a/Riot/Modules/Secrets/Reset/SecretsResetViewModel.swift +++ b/Riot/Modules/Secrets/Reset/SecretsResetViewModel.swift @@ -63,7 +63,7 @@ final class SecretsResetViewModel: SecretsResetViewModelType { } private func resetSecrets(with authParameters: [String: Any]) { - guard let crossSigning = self.session.crypto.crossSigning else { + guard let crossSigning = self.session.crypto?.crossSigning else { return } MXLog.debug("[SecretsResetViewModel] resetSecrets") diff --git a/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinator.swift b/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinator.swift index 3385063ce..53a03e359 100644 --- a/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinator.swift +++ b/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinator.swift @@ -149,11 +149,11 @@ final class SecureBackupSetupCoordinator: SecureBackupSetupCoordinatorType { } private func showKeyBackupRestore() { - guard let keyBackupVersion = self.keyBackup?.keyBackupVersion else { + guard let backup = keyBackup, let keyBackupVersion = backup.keyBackupVersion else { return } - let coordinator = KeyBackupRecoverCoordinator(session: self.session, keyBackupVersion: keyBackupVersion, navigationRouter: self.navigationRouter) + let coordinator = KeyBackupRecoverCoordinator(keyBackup: backup, keyBackupVersion: keyBackupVersion, navigationRouter: self.navigationRouter) self.add(childCoordinator: coordinator) coordinator.delegate = self diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 915e99e12..54bb95d34 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1445,13 +1445,11 @@ ChangePasswordCoordinatorBridgePresenterDelegate> NSString *sdkVersionInfo = [NSString stringWithFormat:@"Matrix SDK %@", MatrixSDKVersion]; - NSString *olmVersionInfo = [NSString stringWithFormat:@"OLM %@", [OLMKit versionString]]; - [footerText appendFormat:@"%@\n", loggedUserInfo]; [footerText appendFormat:@"%@\n", homeserverInfo]; [footerText appendFormat:@"%@\n", appVersionInfo]; [footerText appendFormat:@"%@\n", sdkVersionInfo]; - [footerText appendFormat:@"%@", olmVersionInfo]; + [footerText appendFormat:@"%@", self.mainSession.crypto.version]; return [footerText copy]; } diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 6e2145c4c..3b5b8c9a8 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -274,7 +274,12 @@ { // Acknowledge the existence of all devices before leaving this screen [self startActivityIndicator]; - [mxSession.crypto setDevicesKnown:usersDevices complete:^{ + if (![self.mainSession.crypto isKindOfClass:[MXLegacyCrypto class]]) + { + MXLogFailure(@"[UsersDevicesViewController] onDone: Only legacy crypto supports manual setting of known devices"); + return; + } + [(MXLegacyCrypto *)mxSession.crypto setDevicesKnown:usersDevices complete:^{ [self stopActivityIndicator]; [self dismissViewControllerAnimated:YES completion:nil]; diff --git a/RiotShareExtension/Shared/ShareManager.m b/RiotShareExtension/Shared/ShareManager.m index 2233b352d..22d0063be 100644 --- a/RiotShareExtension/Shared/ShareManager.m +++ b/RiotShareExtension/Shared/ShareManager.m @@ -102,7 +102,10 @@ static MXSession *fakeSession; [session setStore:self.fileStore success:^{ MXStrongifyAndReturnIfNil(session); - session.crypto.warnOnUnknowDevices = NO; // Do not warn for unknown devices. We have cross-signing now + if ([session.crypto isKindOfClass:[MXLegacyCrypto class]]) + { + ((MXLegacyCrypto *)session.crypto).warnOnUnknowDevices = NO; // Do not warn for unknown devices. We have cross-signing now + } self.selectedRooms = [NSMutableArray array]; for (NSString *roomIdentifier in roomIdentifiers) { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift index 7dfb4d04f..862d07453 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift @@ -61,4 +61,14 @@ class UserSessionOverviewUITests: MockScreenTestCase { XCTAssertTrue(app.staticTexts[VectorL10n.userSessionPushNotifications].exists) XCTAssertTrue(app.staticTexts[VectorL10n.userSessionPushNotificationsMessage].exists) } + + func test_whenSessionSelected_kebabMenuShows() { + app.goToScreenWithIdentifier(MockUserSessionOverviewScreenState.otherSession.title) + let navTitle = VectorL10n.userSessionOverviewSessionTitle + let barButton = app.navigationBars[navTitle].buttons["Menu"] + XCTAssertTrue(barButton.exists) + barButton.tap() + XCTAssertTrue(app.buttons[VectorL10n.signOut].exists) + XCTAssertTrue(app.buttons[VectorL10n.manageSessionRename].exists) + } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift index 83c1adb4e..07192c55c 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift @@ -63,8 +63,23 @@ struct UserSessionOverview: View { .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Menu { - Button { viewModel.send(viewAction: .renameSession) } label: { - Label(VectorL10n.manageSessionRename, systemImage: "pencil") + SwiftUI.Section { + Button { viewModel.send(viewAction: .renameSession) } label: { + Label(VectorL10n.manageSessionRename, systemImage: "pencil") + } + .accessibilityIdentifier(VectorL10n.manageSessionRename) + } + + if #available(iOS 15, *) { + Button(role: .destructive) { viewModel.send(viewAction: .logoutOfSession) } label: { + Label(VectorL10n.signOut, systemImage: "rectangle.portrait.and.arrow.right.fill") + } + .accessibilityIdentifier(VectorL10n.signOut) + } else { + Button { viewModel.send(viewAction: .logoutOfSession) } label: { + Label(VectorL10n.signOut, systemImage: "rectangle.righthalf.inset.fill.arrow.right") + } + .accessibilityIdentifier(VectorL10n.signOut) } } label: { Image(systemName: "ellipsis") @@ -73,6 +88,7 @@ struct UserSessionOverview: View { .padding(.vertical, 12) } .offset(x: 4) // Re-align the symbol after applying padding. + .accessibilityIdentifier("Menu") } } .accentColor(theme.colors.accent) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsDataProvider.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsDataProvider.swift index 84c75b7ea..1028dd3cb 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsDataProvider.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsDataProvider.swift @@ -47,7 +47,7 @@ class UserSessionsDataProvider: UserSessionsDataProviderProtocol { func verificationState(for deviceInfo: MXDeviceInfo?) -> UserSessionInfo.VerificationState { guard let deviceInfo = deviceInfo else { return .unknown } - guard session.crypto?.crossSigning?.canCrossSign == true else { + guard session.crypto?.crossSigning.canCrossSign == true else { return deviceInfo.deviceId == session.myDeviceId ? .unverified : .unknown } diff --git a/RiotTests/UserSessionsDataProviderTests.swift b/RiotTests/UserSessionsDataProviderTests.swift index df504a992..3780dcd65 100644 --- a/RiotTests/UserSessionsDataProviderTests.swift +++ b/RiotTests/UserSessionsDataProviderTests.swift @@ -113,7 +113,7 @@ private class MockSession: MXSession { /// A mock `MXCrypto` that can override the `canCrossSign` state. private class MockCrypto: MXLegacyCrypto { let canCrossSign: Bool - override var crossSigning: MXCrossSigning! { MockCrossSigning(canCrossSign: canCrossSign) } + override var crossSigning: MXCrossSigning { MockCrossSigning(canCrossSign: canCrossSign) } init(canCrossSign: Bool) { self.canCrossSign = canCrossSign diff --git a/SiriIntents/IntentHandlers/SendMessage/SendMessageIntentHandler.m b/SiriIntents/IntentHandlers/SendMessage/SendMessageIntentHandler.m index 84d9dee63..34ebb66e9 100644 --- a/SiriIntents/IntentHandlers/SendMessage/SendMessageIntentHandler.m +++ b/SiriIntents/IntentHandlers/SendMessage/SendMessageIntentHandler.m @@ -118,7 +118,10 @@ self.selectedRoom = [MXRoom loadRoomFromStore:fileStore withRoomId:roomID matrixSession:session]; // Do not warn for unknown devices. We have cross-signing now - session.crypto.warnOnUnknowDevices = NO; + if ([session.crypto isKindOfClass:[MXLegacyCrypto class]]) + { + ((MXLegacyCrypto *)session.crypto).warnOnUnknowDevices = NO; + } MXWeakify(self); [self.selectedRoom sendTextMessage:intent.content diff --git a/changelog.d/5326.bugfix b/changelog.d/5326.bugfix deleted file mode 100644 index 8eaa35254..000000000 --- a/changelog.d/5326.bugfix +++ /dev/null @@ -1 +0,0 @@ -Timeline: Fix layout for SwiftUI content views. diff --git a/changelog.d/6847.bugfix b/changelog.d/6847.bugfix deleted file mode 100644 index 3e8dcd7a1..000000000 --- a/changelog.d/6847.bugfix +++ /dev/null @@ -1 +0,0 @@ -Updates the avatar image loading logics. diff --git a/changelog.d/6849.bugfix b/changelog.d/6849.bugfix deleted file mode 100644 index 2d54bf805..000000000 --- a/changelog.d/6849.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixes input text view height when containing multiple lines of text. diff --git a/changelog.d/6925.misc b/changelog.d/6925.misc deleted file mode 100644 index 4d59fecf3..000000000 --- a/changelog.d/6925.misc +++ /dev/null @@ -1 +0,0 @@ -Updated templates readme file. diff --git a/changelog.d/6928.wip b/changelog.d/6928.wip deleted file mode 100644 index 419a8296e..000000000 --- a/changelog.d/6928.wip +++ /dev/null @@ -1 +0,0 @@ -Device Manager: Multi-session selection. diff --git a/changelog.d/6935.change b/changelog.d/6935.change deleted file mode 100644 index 43807527e..000000000 --- a/changelog.d/6935.change +++ /dev/null @@ -1 +0,0 @@ -Added a responsive placeholder text to the Rich Text Composer diff --git a/changelog.d/6941.feature b/changelog.d/6941.feature deleted file mode 100644 index f9c3d32ea..000000000 --- a/changelog.d/6941.feature +++ /dev/null @@ -1 +0,0 @@ -Added voice message support to the Rich Text Composer \ No newline at end of file diff --git a/changelog.d/6949.bugfix b/changelog.d/6949.bugfix deleted file mode 100644 index 2737193db..000000000 --- a/changelog.d/6949.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed the placeholder flickering in the input toolbar when there is an height change. \ No newline at end of file diff --git a/changelog.d/6954.change b/changelog.d/6954.change deleted file mode 100644 index 40c49aac0..000000000 --- a/changelog.d/6954.change +++ /dev/null @@ -1 +0,0 @@ -Added the maximise/minimise toggle button to the Rich Text Composer \ No newline at end of file diff --git a/changelog.d/pr-6870.feature b/changelog.d/pr-6870.feature deleted file mode 100644 index 2a4ba4edc..000000000 --- a/changelog.d/pr-6870.feature +++ /dev/null @@ -1 +0,0 @@ -Changed the info in the background audio message player. diff --git a/changelog.d/pr-6936.change b/changelog.d/pr-6936.change deleted file mode 100644 index d1e649c9f..000000000 --- a/changelog.d/pr-6936.change +++ /dev/null @@ -1 +0,0 @@ -Improves external links interaction UX. diff --git a/changelog.d/pr-6937.change b/changelog.d/pr-6937.change deleted file mode 100644 index f7a524576..000000000 --- a/changelog.d/pr-6937.change +++ /dev/null @@ -1 +0,0 @@ -Verification: Deprecate legacy device-to-device verification diff --git a/changelog.d/pr-6943.change b/changelog.d/pr-6943.change deleted file mode 100644 index 6e35736b1..000000000 --- a/changelog.d/pr-6943.change +++ /dev/null @@ -1 +0,0 @@ -Crypto: Define MXCrypto and MXCrossSigning as protocols diff --git a/changelog.d/pr-6996.build b/changelog.d/pr-6996.build deleted file mode 100644 index e8750367e..000000000 --- a/changelog.d/pr-6996.build +++ /dev/null @@ -1 +0,0 @@ -Add Z-Labs tag for rich text editor and update to the new label naming. \ No newline at end of file diff --git a/changelog.d/pr-6999.change b/changelog.d/pr-6999.change deleted file mode 100644 index 75f8cf949..000000000 --- a/changelog.d/pr-6999.change +++ /dev/null @@ -1 +0,0 @@ -Hide the old session list when the new device manager is enabled. diff --git a/changelog.d/pr-7001.change b/changelog.d/pr-7001.change new file mode 100644 index 000000000..e9058ad13 --- /dev/null +++ b/changelog.d/pr-7001.change @@ -0,0 +1 @@ +Add the sign out option in the menu in the session overview.