mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-28 20:26:57 +02:00
1e8b2f4f26
* Renamed sign out to logout * Renamed sign out to logout * Renamed sign out to logout * Sign out of all other sessions * Fix typo in issue automation * Fixed unit tests * Translations update from Weblate (#7017) * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (German) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (German) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Dutch) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ Co-authored-by: lvre <7uu3qrbvm@relay.firefox.com> Co-authored-by: Priit Jõerüüt <riot@joeruut.com> Co-authored-by: Vri <element@vrifox.cc> Co-authored-by: Johan Smits <johan@smitsmail.net> * Prepare for new sprint * Prepare for new sprint * Threads: added support to read receipts (MSC3771) - Update after review * Threads: added support to notifications count (MSC3773) * Update RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Test/UI/UserOtherSessionsUITests.swift Co-authored-by: aringenbach <80891108+aringenbach@users.noreply.github.com> * Update RiotSwiftUI/Modules/UserSessions/UserOtherSessions/Test/UI/UserOtherSessionsUITests.swift Co-authored-by: aringenbach <80891108+aringenbach@users.noreply.github.com> * Comment fix * the test may fail on CI without blocking the task/check * tests may fail on CI * test improvement * test may fail on CI * Hide push toggles for http pushers when there is no server support * changelog * Code review fixes * Threads: added support to read receipts (MSC3771) - Update after review * Synchronise composer and toolbar resizing animation duration * Add kResizeComposerAnimationDuration constant description * fix for 6946 * Threads: add support to labs flag for read receipts * Cleanup * Code review fixes, created DestructiveButton * Update issue automation Stop using deprecated ProjectNext API in favour of the new ProjectV2 one * Update PR automation Stop using deprecated ProjectNext API in favour of the new ProjectV2 one * Code review fixes * Map location info * Map location info * Add location feature in UserSessionsOverview * Add “show location” feature in other sessions list * Add “show location“ feature in session overview * Fix Package.resolved * Cleanup merge leftovers * Cleanup code * Cleanup * Add show/hide ip persistency * Add location info in UserOtherSessions * Refine settings logic * Mock settings in UserSessionsOverviewViewModel * Add settings service in UserOtherSessionsViewModel * Inject setting service in UserSessionOverviewViewModel * Add changelog.d file * Fix UTs * Cleanup merge leftovers * Add animations * Fix failing test * another possible impl * this solution looks promising * Amend title font * fixed the positioning * Amend copies * trick without using the window but the nav controller * Device Manager: Session list item is not tappable everywhere * changelog * Threads notification count in main timeline including un participated threads * Changed title and body * Removed "Do not ask again" button * Remove indication about plain text mode coming soon * Prevent `Unable to activate constraint with anchors .. because they have no common ancestor.` crashes. Only link toasts to the top safe area instead of the navigation controller * Revert "Replace attributed string height calculation with a more reliable implementation" This reverts commit47512127ec. * Revert "Fix timeline items text height calculation" This reverts commit27f4feb8d9. * Revert "Fixes vector-im/element-ios/issues/6441 - Incorrect timeline item text height calculation (#6679)" This reverts commitbd017d1a77. * Fixes vector-im/element-ios/issues/6441 - Incorrect timeline item text height calculation * Prepare for new sprint * fullscreen mode with navigation controller superview * full screen improvements * Refine bottom sheet layout * fix for iPad * fix for iPad * updated pod * changelog * Switch to using an API key for interactions with AppStoreConnect while on CI; update fastlane and dependencies * Rich-text editor: Fix text formatting enabled inconsistent state * Labs: Rich-text editor - Fix text formatting switch losing the current content of the composer * Re-order View computed properties and move to private mark * Add intrinsic sized bottom sheet * Snooze controller * Changelog * pan gesture * Fix composer view model tests * some pr suggestions * Rich-text editor: enable translations between Markdown and HTML when toggling text formatting * improved the pan animation to be as the designs * Force a layout on the room bubble cell messageTextView to get a correct frame * Move Move UserAgentParserTests * Add UserSessionDetailsUITests * Improve UserSessionNameUITests * Cleanup tests * Improve UserSessionNameViewModelTests * Test empty state for UserOtherSessions * Fix typo * Cleanup unused code * Add changelog.d file * Threads: removed "unread_thread_notifications" from sync filters for server that doesn't support MSC3773 * keyboard dismissal issue fixed * this works but we need to expose also the maxCompressed height and the minHeight * code improvements * Remove 10s wait on failed initial sync * updated to the latest version of the swiftpm * swipe animation improvements * Threads: removed "unread_thread_notifications" from sync filters for server that doesn't support MSC3773 - Update after review * Revert "Device Manager: Session list item is not tappable everywhere" This reverts commit221f4ad106. * Fixup session list item is not tappable everywhere * improving animations * animation improvement with and without keyboard * Fix accessibility id in UserOtherSessions * fullscreen mode implemented * fixing a bad indentation * Poll not usable after logging out and back in * Changelog * Removed init * voice dictation now works * changelog * plain text * Add voice broadcast slider (#7010) * Display number of unread messages above threads button * Import progress for room keys * Translations update from Weblate (#7080) * Translated using Weblate (Dutch) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Dutch) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Albanian) Currently translated at 99.6% (2303 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Italian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (German) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Dutch) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ * Translated using Weblate (Italian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Albanian) Currently translated at 99.5% (2305 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ * Translated using Weblate (German) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Japanese) Currently translated at 66.2% (1534 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Japanese) Currently translated at 66.2% (1534 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ * Translated using Weblate (German) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (German) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Italian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (French) Currently translated at 97.6% (2272 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fr/ * Translated using Weblate (Russian) Currently translated at 80.5% (1873 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/ * Translated using Weblate (Russian) Currently translated at 80.7% (1879 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/ Co-authored-by: Roel ter Maat <roel.termaat@nedap.com> Co-authored-by: Vri <element@vrifox.cc> Co-authored-by: Besnik Bleta <besnik@programeshqip.org> Co-authored-by: lvre <7uu3qrbvm@relay.firefox.com> Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com> Co-authored-by: Priit Jõerüüt <riot@joeruut.com> Co-authored-by: Linerly <linerly@protonmail.com> Co-authored-by: Jozef Gaal <preklady@mayday.sk> Co-authored-by: random <dictionary@tutamail.com> Co-authored-by: Szimszon <github@oregpreshaz.eu> Co-authored-by: Suguru Hirahara <ovestekona@protonmail.com> Co-authored-by: Thibault Martin <mail@thibaultmart.in> Co-authored-by: Platon Terekhov <ockenfels_vevent@aleeas.com> * Prepare for new sprint * first type of fix * Fix Weblate conflict * dismiss fullscreen when sending a message * improvements * full screen improvements * improving the dismiss of the keyboard * improved code and stability * Fix verification state algorithm * Add localisation for UserSessionCardViewData * Add tests * Improve unit tests * Add changelog.d file * scrollable bottom sheet, with custom size on iOS 16 * changelog * Add VerificationState.isUnverified * some more documentation on how to use the custom detent * Update Rich text editor library version * Fix a crash when a voice message finishes. * hide button and revert state when rotating on an iPhone, also fixed the positioning of the strikethrough and underline, and the maxCompressed size in landscape mode is always adapted to be visible. * changelog * fix to make the function run on RiotSwiftUI * removed a reference to a constraint that was not needed but only created a constraint issue when restored during the animation for dismissal * Add Voice Broadcast left time countdown * Display sync progress on the loading screen * Allow alpha builds to run, if tagged accordingly, when pushing new commits * suggest PR changes * better naming * Update on VoiceBroadcast currentRecordingState creation * fixing tests * Fix scroll issues with VoiceBroadcastPlayback cells (by fixing SizableBaseRoomCell) * Refactor InfoSheet presentation * Add changelog.d file * Add Towncrier file * Add Towncrier file * Update Voice Broadcast Time left asset * Support live playback * update comments * Fix PR comments * Fix the live icon must be displayed (in grey) if the record is paused - It is hidden currently * Update live indicator * Display the playback duration in the default state * Remove useless check condition * Add VBAggregatorLaunchState in Aggregator * Remove useless error states * Add missing buffering state * Support voice broadcast live playback (#7094) * Fix build after automatic rebase from GH * Add Towncrier file * Fix PR comments * Update from latest PR changes requests * Debounce poll messages more * Add changelog.d file * fix * changelog * better changelog * VoiceBroadcast: Fix chunk processing (#7113) * Translated using Weblate (Dutch) (#7119) Currently translated at 100.0% (49 of 49 strings) Translation: Element iOS/Element iOS (Push) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-push/nl/ Co-authored-by: Roel ter Maat <roel.termaat@nedap.com> * Translations update from Weblate (#7120) * Translated using Weblate (Dutch) Currently translated at 100.0% (8 of 8 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/nl/ * Translated using Weblate (Albanian) Currently translated at 100.0% (8 of 8 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/sq/ * Translated using Weblate (Russian) Currently translated at 100.0% (8 of 8 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/ru/ * Translated using Weblate (Spanish) Currently translated at 100.0% (8 of 8 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/es/ Co-authored-by: Roel ter Maat <roel.termaat@nedap.com> Co-authored-by: Besnik Bleta <besnik@programeshqip.org> Co-authored-by: Platon Terekhov <ockenfels_vevent@aleeas.com> Co-authored-by: iaiz <git@iapellaniz.com> * Translations update from Weblate (#7121) * Translated using Weblate (Dutch) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Dutch) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Albanian) Currently translated at 99.6% (2303 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Italian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (German) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Dutch) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ * Translated using Weblate (Italian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Albanian) Currently translated at 99.5% (2305 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ * Translated using Weblate (German) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Japanese) Currently translated at 66.2% (1534 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Japanese) Currently translated at 66.2% (1534 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ * Translated using Weblate (German) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (German) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Italian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (French) Currently translated at 97.6% (2272 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fr/ * Translated using Weblate (Russian) Currently translated at 80.5% (1873 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/ * Translated using Weblate (Russian) Currently translated at 80.7% (1879 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/ * Translated using Weblate (Albanian) Currently translated at 98.9% (2302 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ Co-authored-by: Roel ter Maat <roel.termaat@nedap.com> Co-authored-by: Vri <element@vrifox.cc> Co-authored-by: Besnik Bleta <besnik@programeshqip.org> Co-authored-by: lvre <7uu3qrbvm@relay.firefox.com> Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com> Co-authored-by: Priit Jõerüüt <riot@joeruut.com> Co-authored-by: Linerly <linerly@protonmail.com> Co-authored-by: Jozef Gaal <preklady@mayday.sk> Co-authored-by: random <dictionary@tutamail.com> Co-authored-by: Szimszon <github@oregpreshaz.eu> Co-authored-by: Suguru Hirahara <ovestekona@protonmail.com> Co-authored-by: Thibault Martin <mail@thibaultmart.in> Co-authored-by: Platon Terekhov <ockenfels_vevent@aleeas.com> Co-authored-by: Ismail Gulek <ismailg@matrix.org> Co-authored-by: Weblate <noreply@weblate.org> * Translations update from Weblate (#7122) * Translated using Weblate (Dutch) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2311 of 2311 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Dutch) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Albanian) Currently translated at 99.6% (2303 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Italian) Currently translated at 100.0% (2312 of 2312 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (German) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2313 of 2313 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Dutch) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ * Translated using Weblate (Italian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2315 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Albanian) Currently translated at 99.5% (2305 of 2315 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ * Translated using Weblate (German) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Japanese) Currently translated at 66.2% (1534 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2317 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Japanese) Currently translated at 66.2% (1534 of 2317 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ * Translated using Weblate (German) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (German) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Ukrainian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Estonian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Translated using Weblate (Slovak) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ * Translated using Weblate (Italian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (2326 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ * Translated using Weblate (French) Currently translated at 97.6% (2272 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fr/ * Translated using Weblate (Russian) Currently translated at 80.5% (1873 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/ * Translated using Weblate (Russian) Currently translated at 80.7% (1879 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/ * Translated using Weblate (Albanian) Currently translated at 98.9% (2302 of 2326 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ Co-authored-by: Roel ter Maat <roel.termaat@nedap.com> Co-authored-by: Vri <element@vrifox.cc> Co-authored-by: Besnik Bleta <besnik@programeshqip.org> Co-authored-by: lvre <7uu3qrbvm@relay.firefox.com> Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com> Co-authored-by: Priit Jõerüüt <riot@joeruut.com> Co-authored-by: Linerly <linerly@protonmail.com> Co-authored-by: Jozef Gaal <preklady@mayday.sk> Co-authored-by: random <dictionary@tutamail.com> Co-authored-by: Szimszon <github@oregpreshaz.eu> Co-authored-by: Suguru Hirahara <ovestekona@protonmail.com> Co-authored-by: Thibault Martin <mail@thibaultmart.in> Co-authored-by: Platon Terekhov <ockenfels_vevent@aleeas.com> Co-authored-by: Ismail Gulek <ismailg@matrix.org> Co-authored-by: Weblate <noreply@weblate.org> * changelog.d: Upgrade MatrixSDK version ([v0.24.5](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.24.5)). * version++ Co-authored-by: paleksandrs <paleksandrs@gmail.com> Co-authored-by: Kat Gerasimova <ekaterinag@element.io> Co-authored-by: Anderas <andyuhnak@gmail.com> Co-authored-by: Element Translate Bot <admin@riot.im> Co-authored-by: lvre <7uu3qrbvm@relay.firefox.com> Co-authored-by: Priit Jõerüüt <riot@joeruut.com> Co-authored-by: Vri <element@vrifox.cc> Co-authored-by: Johan Smits <johan@smitsmail.net> Co-authored-by: gulekismail <ismailgulek0@gmail.com> Co-authored-by: Gil Eluard <gile@element.io> Co-authored-by: Aleksandrs Proskurins <aleksandrsp@element.io> Co-authored-by: aringenbach <80891108+aringenbach@users.noreply.github.com> Co-authored-by: Mauro Romito <mauro.romito@element.io> Co-authored-by: Alfonso Grillo <alfogrillo@element.io> Co-authored-by: Velin92 <34335419+Velin92@users.noreply.github.com> Co-authored-by: aringenbach <arnaudr@element.io> Co-authored-by: Alfonso Grillo <alfogrillo@gmail.com> Co-authored-by: Stefan Ceriu <stefanc@matrix.org> Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com> Co-authored-by: Yoan Pintas <y.pintas@gmail.com> Co-authored-by: Roel ter Maat <roel.termaat@nedap.com> Co-authored-by: Besnik Bleta <besnik@programeshqip.org> Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com> Co-authored-by: Linerly <linerly@protonmail.com> Co-authored-by: Jozef Gaal <preklady@mayday.sk> Co-authored-by: random <dictionary@tutamail.com> Co-authored-by: Szimszon <github@oregpreshaz.eu> Co-authored-by: Suguru Hirahara <ovestekona@protonmail.com> Co-authored-by: Thibault Martin <mail@thibaultmart.in> Co-authored-by: Platon Terekhov <ockenfels_vevent@aleeas.com> Co-authored-by: Doug <douglase@element.io> Co-authored-by: Philippe Loriaux <philippel@element.io> Co-authored-by: Phl-Pro <philippe.loriaux@niji.fr> Co-authored-by: Giom Foret <giom@matrix.org> Co-authored-by: iaiz <git@iapellaniz.com> Co-authored-by: Weblate <noreply@weblate.org>
815 lines
36 KiB
Swift
815 lines
36 KiB
Swift
// File created from ScreenTemplate
|
|
// $ createScreen.sh Onboarding Authentication
|
|
/*
|
|
Copyright 2021 New Vector Ltd
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
import UIKit
|
|
import CommonKit
|
|
|
|
struct AuthenticationCoordinatorParameters {
|
|
let navigationRouter: NavigationRouterType
|
|
/// The screen that should be shown when starting the flow.
|
|
let initialScreen: AuthenticationCoordinator.EntryPoint
|
|
/// Whether or not the coordinator should show the loading spinner, key verification etc.
|
|
let canPresentAdditionalScreens: Bool
|
|
}
|
|
|
|
/// A coordinator that handles authentication, verification and setting a PIN.
|
|
final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtocol {
|
|
|
|
enum EntryPoint {
|
|
case registration
|
|
case login
|
|
}
|
|
|
|
// MARK: - Properties
|
|
|
|
// MARK: Private
|
|
|
|
private let navigationRouter: NavigationRouterType
|
|
private let authenticationService = AuthenticationService.shared
|
|
|
|
/// The initial screen to be shown when starting the coordinator.
|
|
private let initialScreen: EntryPoint
|
|
/// The type of authentication that was used to complete the flow.
|
|
private var authenticationType: AuthenticationType?
|
|
|
|
/// The presenter used to handler authentication via SSO.
|
|
private var ssoAuthenticationPresenter: SSOAuthenticationPresenter?
|
|
/// The transaction ID used when presenting the SSO screen. Used when completing via a deep link.
|
|
private var ssoTransactionID: String?
|
|
|
|
/// Whether the coordinator can present further screens after a successful login has occurred.
|
|
private var canPresentAdditionalScreens: Bool
|
|
/// `true` if presentation of the verification screen is blocked by `canPresentAdditionalScreens`.
|
|
private var isWaitingToPresentCompleteSecurity = false
|
|
|
|
/// The listener object that informs the coordinator whether verification needs to be presented or not.
|
|
private var verificationListener: SessionVerificationListener?
|
|
|
|
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
|
private var successIndicator: UserIndicator?
|
|
|
|
/// The password entered, for use when setting up cross-signing.
|
|
private var password: String?
|
|
/// The session created when successfully authenticated.
|
|
private var session: MXSession?
|
|
|
|
// MARK: Public
|
|
|
|
// Must be used only internally
|
|
var childCoordinators: [Coordinator] = []
|
|
var callback: ((AuthenticationCoordinatorResult) -> Void)?
|
|
|
|
// MARK: - Setup
|
|
|
|
init(parameters: AuthenticationCoordinatorParameters) {
|
|
self.navigationRouter = parameters.navigationRouter
|
|
self.initialScreen = parameters.initialScreen
|
|
self.canPresentAdditionalScreens = parameters.canPresentAdditionalScreens
|
|
|
|
indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: parameters.navigationRouter.toPresentable())
|
|
|
|
super.init()
|
|
}
|
|
|
|
// MARK: - Public
|
|
|
|
func start() {
|
|
Task { @MainActor in
|
|
await startAuthenticationFlow()
|
|
callback?(.didStart)
|
|
authenticationService.delegate = self
|
|
}
|
|
}
|
|
|
|
func toPresentable() -> UIViewController {
|
|
navigationRouter.toPresentable()
|
|
}
|
|
|
|
func presentPendingScreensIfNecessary() {
|
|
canPresentAdditionalScreens = true
|
|
|
|
showLoadingAnimation()
|
|
|
|
if isWaitingToPresentCompleteSecurity {
|
|
isWaitingToPresentCompleteSecurity = false
|
|
presentCompleteSecurity()
|
|
}
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
/// Starts the authentication flow.
|
|
@MainActor private func startAuthenticationFlow() async {
|
|
if let softLogoutCredentials = authenticationService.softLogoutCredentials,
|
|
let homeserverAddress = softLogoutCredentials.homeServer {
|
|
do {
|
|
try await authenticationService.startFlow(.login, for: homeserverAddress)
|
|
} catch {
|
|
MXLog.error("[AuthenticationCoordinator] start: Failed to start")
|
|
displayError(message: error.localizedDescription)
|
|
}
|
|
|
|
await showSoftLogoutScreen(softLogoutCredentials)
|
|
|
|
return
|
|
}
|
|
|
|
let flow: AuthenticationFlow = initialScreen == .login ? .login : .register
|
|
do {
|
|
// Start the flow using the default server (or a provisioning link if set).
|
|
try await authenticationService.startFlow(flow)
|
|
} catch {
|
|
MXLog.error("[AuthenticationCoordinator] start: Failed to start, showing server selection.")
|
|
showServerSelectionScreen(for: flow)
|
|
return
|
|
}
|
|
|
|
switch initialScreen {
|
|
case .registration:
|
|
if authenticationService.state.homeserver.needsRegistrationFallback {
|
|
showFallback(for: flow)
|
|
} else {
|
|
showRegistrationScreen()
|
|
}
|
|
case .login:
|
|
if authenticationService.state.homeserver.needsLoginFallback {
|
|
showFallback(for: flow)
|
|
} else {
|
|
showLoginScreen()
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Pushes the server selection screen into the flow (other screens may also present it modally later).
|
|
@MainActor private func showServerSelectionScreen(for flow: AuthenticationFlow) {
|
|
MXLog.debug("[AuthenticationCoordinator] showServerSelectionScreen")
|
|
let parameters = AuthenticationServerSelectionCoordinatorParameters(authenticationService: authenticationService,
|
|
flow: flow,
|
|
hasModalPresentation: false)
|
|
let coordinator = AuthenticationServerSelectionCoordinator(parameters: parameters)
|
|
coordinator.callback = { [weak self, weak coordinator] result in
|
|
guard let self = self, let coordinator = coordinator else { return }
|
|
self.serverSelectionCoordinator(coordinator, didCompleteWith: result, for: flow)
|
|
}
|
|
|
|
coordinator.start()
|
|
add(childCoordinator: coordinator)
|
|
|
|
navigationRouter.push(coordinator, animated: true) { [weak self] in
|
|
self?.remove(childCoordinator: coordinator)
|
|
}
|
|
}
|
|
|
|
/// Shows the next screen in the flow after the server selection screen.
|
|
@MainActor private func serverSelectionCoordinator(_ coordinator: AuthenticationServerSelectionCoordinator,
|
|
didCompleteWith result: AuthenticationServerSelectionCoordinatorResult,
|
|
for flow: AuthenticationFlow) {
|
|
switch result {
|
|
case .updated:
|
|
if flow == .register {
|
|
showRegistrationScreen()
|
|
} else {
|
|
showLoginScreen()
|
|
}
|
|
case .dismiss:
|
|
MXLog.failure("[AuthenticationCoordinator] AuthenticationServerSelectionScreen is requesting dismiss when part of a stack.")
|
|
}
|
|
}
|
|
|
|
/// Presents an alert on top of the navigation router with the supplied error message.
|
|
@MainActor private func displayError(message: String) {
|
|
let alert = UIAlertController(title: VectorL10n.error, message: message, preferredStyle: .alert)
|
|
alert.addAction(UIAlertAction(title: VectorL10n.ok, style: .default))
|
|
toPresentable().present(alert, animated: true)
|
|
}
|
|
|
|
/// Prompts the user to confirm that they would like to cancel the registration flow.
|
|
@MainActor private func displayCancelConfirmation() {
|
|
let alert = UIAlertController(title: VectorL10n.warning,
|
|
message: VectorL10n.authenticationCancelFlowConfirmationMessage,
|
|
preferredStyle: .alert)
|
|
|
|
alert.addAction(UIAlertAction(title: VectorL10n.no, style: .cancel))
|
|
alert.addAction(UIAlertAction(title: VectorL10n.yes, style: .default) { [weak self] _ in
|
|
self?.cancelRegistration()
|
|
})
|
|
|
|
toPresentable().present(alert, animated: true)
|
|
}
|
|
|
|
/// Prompts the user to trust a certificate by displaying its fingerprint (SHA256).
|
|
@MainActor private func displayUnrecognizedCertificateAlert(for certificate: Data) async -> Bool {
|
|
await withCheckedContinuation { continuation in
|
|
let title = VectorL10n.sslCouldNotVerify
|
|
let homeserverURLString = VectorL10n.sslHomeserverUrl(authenticationService.state.homeserver.displayableAddress)
|
|
let fingerprint = VectorL10n.sslFingerprintHash("SHA256")
|
|
let certificateFingerprint = (certificate as NSData).mx_SHA256AsHexString() ?? VectorL10n.error
|
|
|
|
let message = [VectorL10n.sslCertNotTrust,
|
|
VectorL10n.sslCertNewAccountExpl,
|
|
homeserverURLString,
|
|
fingerprint,
|
|
certificateFingerprint,
|
|
VectorL10n.sslOnlyAccept]
|
|
.joined(separator: "\n\n")
|
|
|
|
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
|
|
|
alert.addAction(UIAlertAction(title: VectorL10n.cancel, style: .cancel) { action in
|
|
continuation.resume(with: .success(false))
|
|
})
|
|
|
|
alert.addAction(UIAlertAction(title: VectorL10n.sslTrust, style: .default) { action in
|
|
continuation.resume(with: .success(true))
|
|
})
|
|
|
|
// The alert will be encountered on the current stack or when server selection is being presented.
|
|
let presentingViewController = toPresentable().presentedViewController ?? toPresentable()
|
|
presentingViewController.present(alert, animated: true, completion: nil)
|
|
}
|
|
}
|
|
|
|
/// Cancels the registration flow, handing control back to the onboarding coordinator.
|
|
@MainActor private func cancelRegistration() {
|
|
authenticationService.reset()
|
|
callback?(.cancel(.register))
|
|
}
|
|
|
|
// MARK: - Login
|
|
|
|
/// Shows the login screen.
|
|
@MainActor private func showLoginScreen() {
|
|
MXLog.debug("[AuthenticationCoordinator] showLoginScreen")
|
|
|
|
let homeserver = authenticationService.state.homeserver
|
|
let parameters = AuthenticationLoginCoordinatorParameters(navigationRouter: navigationRouter,
|
|
authenticationService: authenticationService,
|
|
loginMode: homeserver.preferredLoginMode)
|
|
let coordinator = AuthenticationLoginCoordinator(parameters: parameters)
|
|
coordinator.callback = { [weak self, weak coordinator] result in
|
|
guard let self = self, let coordinator = coordinator else { return }
|
|
self.loginCoordinator(coordinator, didCallbackWith: result)
|
|
}
|
|
|
|
coordinator.start()
|
|
add(childCoordinator: coordinator)
|
|
|
|
if navigationRouter.modules.isEmpty {
|
|
navigationRouter.setRootModule(coordinator, popCompletion: nil)
|
|
} else {
|
|
navigationRouter.push(coordinator, animated: true) { [weak self] in
|
|
self?.remove(childCoordinator: coordinator)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Shows the soft logout screen.
|
|
@MainActor private func showSoftLogoutScreen(_ credentials: MXCredentials) async {
|
|
MXLog.debug("[AuthenticationCoordinator] showSoftLogoutScreen")
|
|
|
|
guard let userId = credentials.userId else {
|
|
MXLog.failure("[AuthenticationCoordinator] showSoftLogoutScreen: Missing userId.")
|
|
displayError(message: VectorL10n.errorCommonMessage)
|
|
return
|
|
}
|
|
|
|
let store = MXFileStore(credentials: credentials)
|
|
let userDisplayName = await store.displayName(ofUserWithId: userId) ?? ""
|
|
|
|
let cryptoStore = MXRealmCryptoStore(credentials: credentials)
|
|
let keyBackupNeeded = (cryptoStore?.inboundGroupSessions(toBackup: 1) ?? []).count > 0
|
|
|
|
let softLogoutCredentials = SoftLogoutCredentials(userId: userId,
|
|
homeserverName: credentials.homeServerName() ?? "",
|
|
userDisplayName: userDisplayName,
|
|
deviceId: credentials.deviceId)
|
|
|
|
let parameters = AuthenticationSoftLogoutCoordinatorParameters(navigationRouter: navigationRouter,
|
|
authenticationService: authenticationService,
|
|
credentials: softLogoutCredentials,
|
|
keyBackupNeeded: keyBackupNeeded)
|
|
let coordinator = AuthenticationSoftLogoutCoordinator(parameters: parameters)
|
|
coordinator.callback = { [weak self] result in
|
|
guard let self = self else { return }
|
|
switch result {
|
|
case .success(let session, let loginPassword):
|
|
self.password = loginPassword
|
|
self.authenticationType = .password
|
|
self.onSessionCreated(session: session, flow: .login)
|
|
case .clearAllData:
|
|
self.callback?(.clearAllData)
|
|
case .continueWithSSO(let provider):
|
|
self.presentSSOAuthentication(for: provider)
|
|
case .fallback:
|
|
self.showFallback(for: .login, deviceId: softLogoutCredentials.deviceId)
|
|
}
|
|
}
|
|
|
|
coordinator.start()
|
|
add(childCoordinator: coordinator)
|
|
|
|
navigationRouter.setRootModule(coordinator, popCompletion: nil)
|
|
}
|
|
|
|
/// Displays the next view in the flow based on the result from the registration screen.
|
|
@MainActor private func loginCoordinator(_ coordinator: AuthenticationLoginCoordinator,
|
|
didCallbackWith result: AuthenticationLoginCoordinatorResult) {
|
|
switch result {
|
|
case .continueWithSSO(let provider):
|
|
presentSSOAuthentication(for: provider)
|
|
case .success(let session, let loginPassword):
|
|
password = loginPassword
|
|
authenticationType = .password
|
|
onSessionCreated(session: session, flow: .login)
|
|
case .loggedInWithQRCode(let session, let securityCompleted):
|
|
authenticationType = .other
|
|
onSessionCreated(session: session, flow: .login, securityCompleted: securityCompleted)
|
|
case .fallback:
|
|
showFallback(for: .login)
|
|
}
|
|
}
|
|
|
|
// MARK: - Registration
|
|
|
|
/// Shows the registration screen.
|
|
@MainActor private func showRegistrationScreen() {
|
|
MXLog.debug("[AuthenticationCoordinator] showRegistrationScreen")
|
|
let homeserver = authenticationService.state.homeserver
|
|
let parameters = AuthenticationRegistrationCoordinatorParameters(navigationRouter: navigationRouter,
|
|
authenticationService: authenticationService,
|
|
registrationFlow: homeserver.registrationFlow,
|
|
loginMode: homeserver.preferredLoginMode)
|
|
let coordinator = AuthenticationRegistrationCoordinator(parameters: parameters)
|
|
coordinator.callback = { [weak self, weak coordinator] result in
|
|
guard let self = self, let coordinator = coordinator else { return }
|
|
self.registrationCoordinator(coordinator, didCallbackWith: result)
|
|
}
|
|
|
|
coordinator.start()
|
|
add(childCoordinator: coordinator)
|
|
|
|
if navigationRouter.modules.isEmpty {
|
|
navigationRouter.setRootModule(coordinator, popCompletion: nil)
|
|
} else {
|
|
navigationRouter.push(coordinator, animated: true) { [weak self] in
|
|
self?.remove(childCoordinator: coordinator)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Displays the next view in the flow based on the result from the registration screen.
|
|
@MainActor private func registrationCoordinator(_ coordinator: AuthenticationRegistrationCoordinator,
|
|
didCallbackWith result: AuthenticationRegistrationCoordinatorResult) {
|
|
switch result {
|
|
case .continueWithSSO(let provider):
|
|
presentSSOAuthentication(for: provider)
|
|
case .completed(let result, let registerPassword):
|
|
password = registerPassword
|
|
authenticationType = .password
|
|
handleRegistrationResult(result)
|
|
case .fallback:
|
|
showFallback(for: .register)
|
|
}
|
|
}
|
|
|
|
/// Shows the verify email screen.
|
|
@MainActor private func showVerifyEmailScreen(registrationWizard: RegistrationWizard) {
|
|
MXLog.debug("[AuthenticationCoordinator] showVerifyEmailScreen")
|
|
|
|
let parameters = AuthenticationVerifyEmailCoordinatorParameters(registrationWizard: registrationWizard,
|
|
homeserver: authenticationService.state.homeserver)
|
|
let coordinator = AuthenticationVerifyEmailCoordinator(parameters: parameters)
|
|
coordinator.callback = { [weak self] result in
|
|
self?.registrationStageDidComplete(with: result)
|
|
}
|
|
|
|
coordinator.start()
|
|
add(childCoordinator: coordinator)
|
|
|
|
navigationRouter.setRootModule(coordinator, hideNavigationBar: false, animated: true) { [weak self] in
|
|
self?.remove(childCoordinator: coordinator)
|
|
}
|
|
}
|
|
|
|
/// Shows the terms screen.
|
|
@MainActor private func showTermsScreen(terms: MXLoginTerms?, registrationWizard: RegistrationWizard) {
|
|
MXLog.debug("[AuthenticationCoordinator] showTermsScreen")
|
|
|
|
let localizedPolicies = terms?.policiesData(forLanguage: Bundle.mxk_language(), defaultLanguage: Bundle.mxk_fallbackLanguage())
|
|
let parameters = AuthenticationTermsCoordinatorParameters(registrationWizard: registrationWizard,
|
|
localizedPolicies: localizedPolicies ?? [],
|
|
homeserver: authenticationService.state.homeserver)
|
|
let coordinator = AuthenticationTermsCoordinator(parameters: parameters)
|
|
coordinator.callback = { [weak self] result in
|
|
self?.registrationStageDidComplete(with: result)
|
|
}
|
|
|
|
coordinator.start()
|
|
add(childCoordinator: coordinator)
|
|
|
|
navigationRouter.setRootModule(coordinator, hideNavigationBar: false, animated: true) { [weak self] in
|
|
self?.remove(childCoordinator: coordinator)
|
|
}
|
|
}
|
|
|
|
@MainActor private func showReCaptchaScreen(siteKey: String, registrationWizard: RegistrationWizard) {
|
|
MXLog.debug("[AuthenticationCoordinator] showReCaptchaScreen")
|
|
|
|
guard let homeserverURL = URL(string: authenticationService.state.homeserver.address) else {
|
|
MXLog.failure("[AuthenticationCoordinator] showReCaptchaScreen: The homeserver address is no longer a valid URL.")
|
|
displayError(message: VectorL10n.errorCommonMessage)
|
|
return
|
|
}
|
|
|
|
let parameters = AuthenticationReCaptchaCoordinatorParameters(registrationWizard: registrationWizard,
|
|
siteKey: siteKey,
|
|
homeserverURL: homeserverURL)
|
|
let coordinator = AuthenticationReCaptchaCoordinator(parameters: parameters)
|
|
coordinator.callback = { [weak self] result in
|
|
self?.registrationStageDidComplete(with: result)
|
|
}
|
|
|
|
coordinator.start()
|
|
add(childCoordinator: coordinator)
|
|
|
|
navigationRouter.setRootModule(coordinator, hideNavigationBar: false, animated: true) { [weak self] in
|
|
self?.remove(childCoordinator: coordinator)
|
|
}
|
|
}
|
|
|
|
/// Shows the verify email screen.
|
|
@MainActor private func showVerifyMSISDNScreen(registrationWizard: RegistrationWizard) {
|
|
MXLog.debug("[AuthenticationCoordinator] showVerifyMSISDNScreen")
|
|
|
|
let parameters = AuthenticationVerifyMsisdnCoordinatorParameters(registrationWizard: registrationWizard,
|
|
homeserver: authenticationService.state.homeserver)
|
|
let coordinator = AuthenticationVerifyMsisdnCoordinator(parameters: parameters)
|
|
coordinator.callback = { [weak self] result in
|
|
self?.registrationStageDidComplete(with: result)
|
|
}
|
|
|
|
coordinator.start()
|
|
add(childCoordinator: coordinator)
|
|
|
|
navigationRouter.setRootModule(coordinator, hideNavigationBar: false, animated: true) { [weak self] in
|
|
self?.remove(childCoordinator: coordinator)
|
|
}
|
|
}
|
|
|
|
/// Displays the next view in the registration flow.
|
|
@MainActor private func registrationStageDidComplete(with result: AuthenticationRegistrationStageResult) {
|
|
switch result {
|
|
case .completed(let result):
|
|
handleRegistrationResult(result)
|
|
case .cancel:
|
|
displayCancelConfirmation()
|
|
}
|
|
}
|
|
|
|
// MARK: - Registration Handlers
|
|
/// Determines the next screen to show from the flow result and pushes it.
|
|
@MainActor private func handleRegistrationResult(_ result: RegistrationResult) {
|
|
switch result {
|
|
case .success(let mxSession):
|
|
onSessionCreated(session: mxSession, flow: .register)
|
|
case .flowResponse(let flowResult):
|
|
MXLog.debug("[AuthenticationCoordinator] handleRegistrationResult: Missing stages - \(flowResult.missingStages)")
|
|
|
|
let homeserver = authenticationService.state.homeserver
|
|
guard let nextStage = homeserver.isMatrixDotOrg ? flowResult.nextUncompletedStageOrdered : flowResult.nextUncompletedStage else {
|
|
MXLog.failure("[AuthenticationCoordinator] There are no remaining stages.")
|
|
return
|
|
}
|
|
|
|
showStage(nextStage)
|
|
}
|
|
}
|
|
|
|
@MainActor private func showStage(_ stage: FlowResult.Stage) {
|
|
guard let registrationWizard = authenticationService.registrationWizard else {
|
|
MXLog.failure("[AuthenticationCoordinator] showStage: Missing the RegistrationWizard needed to complete the stage.")
|
|
displayError(message: VectorL10n.errorCommonMessage)
|
|
return
|
|
}
|
|
|
|
switch stage {
|
|
case .email:
|
|
showVerifyEmailScreen(registrationWizard: registrationWizard)
|
|
case .terms(_, let terms):
|
|
showTermsScreen(terms: terms, registrationWizard: registrationWizard)
|
|
case .reCaptcha(_, let siteKey):
|
|
showReCaptchaScreen(siteKey: siteKey, registrationWizard: registrationWizard)
|
|
case .msisdn:
|
|
showVerifyMSISDNScreen(registrationWizard: registrationWizard)
|
|
case .dummy:
|
|
MXLog.failure("[AuthenticationCoordinator] Attempting to perform the dummy stage.")
|
|
case .other:
|
|
MXLog.failure("[AuthenticationCoordinator] Attempting to perform an unsupported stage.")
|
|
showFallback(for: .register)
|
|
}
|
|
}
|
|
|
|
/// Handles the creation of a new session following on from a successful authentication.
|
|
@MainActor private func onSessionCreated(session: MXSession, flow: AuthenticationFlow, securityCompleted: Bool = false) {
|
|
self.session = session
|
|
|
|
guard !securityCompleted else {
|
|
callback?(.didLogin(session: session, authenticationFlow: flow, authenticationType: authenticationType ?? .other))
|
|
callback?(.didComplete)
|
|
return
|
|
}
|
|
|
|
if canPresentAdditionalScreens {
|
|
showLoadingAnimation()
|
|
}
|
|
|
|
let verificationListener = SessionVerificationListener(session: session, password: password)
|
|
|
|
verificationListener.completion = { [weak self] result in
|
|
guard let self = self else { return }
|
|
switch result {
|
|
case .needsVerification:
|
|
guard self.canPresentAdditionalScreens else {
|
|
MXLog.debug("[AuthenticationCoordinator] Delaying presentCompleteSecurity during onboarding.")
|
|
self.isWaitingToPresentCompleteSecurity = true
|
|
return
|
|
}
|
|
|
|
MXLog.debug("[AuthenticationCoordinator] Complete security")
|
|
self.presentCompleteSecurity()
|
|
case .authenticationIsComplete:
|
|
self.authenticationDidComplete()
|
|
}
|
|
}
|
|
|
|
verificationListener.start()
|
|
self.verificationListener = verificationListener
|
|
|
|
callback?(.didLogin(session: session, authenticationFlow: flow, authenticationType: authenticationType ?? .other))
|
|
}
|
|
|
|
// MARK: - Additional Screens
|
|
|
|
private func showFallback(for flow: AuthenticationFlow, deviceId: String? = nil) {
|
|
var url = authenticationService.fallbackURL(for: flow)
|
|
|
|
if let deviceId = deviceId {
|
|
// add deviceId as `device_id` into the url
|
|
guard var urlComponents = URLComponents(string: url.absoluteString) else {
|
|
MXLog.error("[AuthenticationCoordinator] showFallback: could not create url components")
|
|
return
|
|
}
|
|
var queryItems = urlComponents.queryItems ?? []
|
|
queryItems.append(URLQueryItem(name: "device_id", value: deviceId))
|
|
urlComponents.queryItems = queryItems
|
|
|
|
if let newUrl = urlComponents.url {
|
|
url = newUrl
|
|
} else {
|
|
MXLog.error("[AuthenticationCoordinator] showFallback: could not create url from components")
|
|
return
|
|
}
|
|
}
|
|
|
|
MXLog.debug("[AuthenticationCoordinator] showFallback for: \(flow), url: \(url)")
|
|
|
|
guard let fallbackVC = AuthFallBackViewController(url: url.absoluteString) else {
|
|
MXLog.error("[AuthenticationCoordinator] showFallback: could not create fallback view controller")
|
|
return
|
|
}
|
|
fallbackVC.delegate = self
|
|
let navController = RiotNavigationController(rootViewController: fallbackVC)
|
|
navController.navigationBar.topItem?.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
|
|
target: self,
|
|
action: #selector(dismissFallback))
|
|
navigationRouter.present(navController, animated: true)
|
|
}
|
|
|
|
@objc
|
|
private func dismissFallback() {
|
|
MXLog.debug("[AuthenticationCoorrdinator] dismissFallback")
|
|
|
|
guard let fallbackNavigationVC = navigationRouter.toPresentable().presentedViewController as? RiotNavigationController else {
|
|
return
|
|
}
|
|
fallbackNavigationVC.dismiss(animated: true)
|
|
authenticationService.reset()
|
|
}
|
|
|
|
/// Replace the contents of the navigation router with a loading animation.
|
|
private func showLoadingAnimation() {
|
|
let syncProgress: MXSessionSyncProgress? = MXSDKOptions.sharedInstance().enableSyncProgress ? session?.syncProgress : nil
|
|
let loadingViewController = LaunchLoadingViewController(syncProgress: syncProgress)
|
|
loadingViewController.modalPresentationStyle = .fullScreen
|
|
|
|
// Replace the navigation stack with the loading animation
|
|
// as there is nothing to navigate back to.
|
|
navigationRouter.setRootModule(loadingViewController)
|
|
}
|
|
|
|
/// Present the key verification screen modally.
|
|
private func presentCompleteSecurity() {
|
|
guard let session = session else {
|
|
MXLog.error("[AuthenticationCoordinator] presentCompleteSecurity: Unable to present security due to missing session.")
|
|
authenticationDidComplete()
|
|
return
|
|
}
|
|
|
|
let isNewSignIn = true
|
|
let cancellable = !session.vc_homeserverConfiguration().encryption.isSecureBackupRequired
|
|
let keyVerificationCoordinator = KeyVerificationCoordinator(session: session, flow: .completeSecurity(isNewSignIn), cancellable: cancellable)
|
|
|
|
keyVerificationCoordinator.delegate = self
|
|
let presentable = keyVerificationCoordinator.toPresentable()
|
|
presentable.presentationController?.delegate = self
|
|
navigationRouter.present(presentable, animated: true)
|
|
keyVerificationCoordinator.start()
|
|
add(childCoordinator: keyVerificationCoordinator)
|
|
}
|
|
|
|
/// Complete the authentication flow.
|
|
private func authenticationDidComplete() {
|
|
Task {
|
|
await MainActor.run { callback?(.didComplete) }
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - SSO
|
|
|
|
extension AuthenticationCoordinator: SSOAuthenticationPresenterDelegate {
|
|
/// Presents SSO authentication for the specified identity provider.
|
|
@MainActor private func presentSSOAuthentication(for identityProvider: SSOIdentityProvider) {
|
|
let service = SSOAuthenticationService(homeserverStringURL: authenticationService.state.homeserver.address)
|
|
let presenter = SSOAuthenticationPresenter(ssoAuthenticationService: service)
|
|
presenter.delegate = self
|
|
|
|
let transactionID = MXTools.generateTransactionId()
|
|
presenter.present(forIdentityProvider: identityProvider, with: transactionID, from: toPresentable(), animated: true)
|
|
|
|
ssoAuthenticationPresenter = presenter
|
|
ssoTransactionID = transactionID
|
|
authenticationType = .sso(identityProvider)
|
|
}
|
|
|
|
func ssoAuthenticationPresenter(_ presenter: SSOAuthenticationPresenter, authenticationSucceededWithToken token: String, usingIdentityProvider identityProvider: SSOIdentityProvider?) {
|
|
MXLog.debug("[AuthenticationCoordinator] SSO authentication succeeded.")
|
|
|
|
guard let loginWizard = authenticationService.loginWizard else {
|
|
MXLog.failure("[AuthenticationCoordinator] The login wizard was requested before getting the login flow.")
|
|
return
|
|
}
|
|
|
|
Task { await handleLoginToken(token, using: loginWizard) }
|
|
}
|
|
|
|
func ssoAuthenticationPresenter(_ presenter: SSOAuthenticationPresenter, authenticationDidFailWithError error: Error) {
|
|
MXLog.debug("[AuthenticationCoordinator] SSO authentication failed.")
|
|
|
|
Task { @MainActor in
|
|
displayError(message: error.localizedDescription)
|
|
ssoAuthenticationPresenter = nil
|
|
ssoTransactionID = nil
|
|
authenticationType = nil
|
|
}
|
|
}
|
|
|
|
func ssoAuthenticationPresenterDidCancel(_ presenter: SSOAuthenticationPresenter) {
|
|
MXLog.debug("[AuthenticationCoordinator] SSO authentication cancelled.")
|
|
ssoAuthenticationPresenter = nil
|
|
ssoTransactionID = nil
|
|
authenticationType = nil
|
|
}
|
|
|
|
/// Performs the last step of the login process for a flow that authenticated via SSO.
|
|
@MainActor private func handleLoginToken(_ token: String, using loginWizard: LoginWizard) async {
|
|
do {
|
|
let session = try await loginWizard.login(with: token)
|
|
onSessionCreated(session: session, flow: authenticationService.state.flow)
|
|
} catch {
|
|
MXLog.error("[AuthenticationCoordinator] Login with SSO token failed.")
|
|
displayError(message: error.localizedDescription)
|
|
authenticationType = nil
|
|
}
|
|
|
|
ssoAuthenticationPresenter = nil
|
|
ssoTransactionID = nil
|
|
}
|
|
}
|
|
|
|
// MARK: - AuthenticationServiceDelegate
|
|
extension AuthenticationCoordinator: AuthenticationServiceDelegate {
|
|
|
|
func authenticationService(_ service: AuthenticationService, needsPromptFor unrecognizedCertificate: Data?, completion: @escaping (Bool) -> Void) {
|
|
guard let certificate = unrecognizedCertificate else {
|
|
completion(false)
|
|
return
|
|
}
|
|
|
|
Task {
|
|
let trusted = await self.displayUnrecognizedCertificateAlert(for: certificate)
|
|
completion(trusted)
|
|
}
|
|
}
|
|
|
|
func authenticationService(_ service: AuthenticationService, didReceive ssoLoginToken: String, with transactionID: String) -> Bool {
|
|
guard let presenter = ssoAuthenticationPresenter, transactionID == ssoTransactionID else {
|
|
Task { await displayError(message: VectorL10n.errorCommonMessage) }
|
|
return false
|
|
}
|
|
|
|
guard let loginWizard = authenticationService.loginWizard else {
|
|
MXLog.failure("[AuthenticationCoordinator] The login wizard was requested before getting the login flow.")
|
|
return false
|
|
}
|
|
|
|
Task {
|
|
await handleLoginToken(ssoLoginToken, using: loginWizard)
|
|
await MainActor.run { presenter.dismiss(animated: true, completion: nil) }
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func authenticationService(_ service: AuthenticationService, didUpdateStateWithLink link: UniversalLink) {
|
|
if link.pathParams.first == "register" {
|
|
callback?(.cancel(.register))
|
|
} else {
|
|
callback?(.cancel(.login))
|
|
}
|
|
successIndicator = indicatorPresenter.present(.success(label: VectorL10n.done))
|
|
}
|
|
}
|
|
|
|
// MARK: - KeyVerificationCoordinatorDelegate
|
|
extension AuthenticationCoordinator: KeyVerificationCoordinatorDelegate {
|
|
func keyVerificationCoordinatorDidComplete(_ coordinator: KeyVerificationCoordinatorType, otherUserId: String, otherDeviceId: String) {
|
|
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)
|
|
}
|
|
|
|
navigationRouter.dismissModule(animated: true) { [weak self] in
|
|
self?.authenticationDidComplete()
|
|
}
|
|
}
|
|
|
|
func keyVerificationCoordinatorDidCancel(_ coordinator: KeyVerificationCoordinatorType) {
|
|
navigationRouter.dismissModule(animated: true) { [weak self] in
|
|
self?.authenticationDidComplete()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - UIAdaptivePresentationControllerDelegate
|
|
extension AuthenticationCoordinator: UIAdaptivePresentationControllerDelegate {
|
|
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
|
|
// Prevent Key Verification from using swipe to dismiss
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Unused conformances
|
|
extension AuthenticationCoordinator {
|
|
func update(authenticationFlow: AuthenticationFlow) {
|
|
// unused
|
|
}
|
|
}
|
|
|
|
// MARK: - AuthFallBackViewControllerDelegate
|
|
extension AuthenticationCoordinator: AuthFallBackViewControllerDelegate {
|
|
func authFallBackViewController(_ authFallBackViewController: AuthFallBackViewController,
|
|
didLoginWith loginResponse: MXLoginResponse) {
|
|
let credentials = MXCredentials(loginResponse: loginResponse, andDefaultCredentials: nil)
|
|
let client = MXRestClient(credentials: credentials)
|
|
guard let session = MXSession(matrixRestClient: client) else {
|
|
MXLog.failure("[AuthenticationCoordinator] authFallBackViewController:didLogin: session could not be created")
|
|
return
|
|
}
|
|
authenticationType = .other
|
|
Task { await onSessionCreated(session: session, flow: authenticationService.state.flow) }
|
|
}
|
|
|
|
func authFallBackViewControllerDidClose(_ authFallBackViewController: AuthFallBackViewController) {
|
|
dismissFallback()
|
|
}
|
|
}
|