diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index f83649651..3566c54ca 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -96,7 +96,6 @@ 0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; }; 0EE5EBA18BA1FE10254BB489 /* UIFont+AttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */; }; 0EEC614342F823E5BF966C2C /* AppLockTimerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A5B4CD611DE7E94F5BA87B2 /* AppLockTimerTests.swift */; }; - 0F4709282FCCFBEFED427B8A /* AuthenticationClientBuilderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4760CE2128FBC217304272AB /* AuthenticationClientBuilderMock.swift */; }; 0F6C8033FA60CFD36F7CA205 /* AppLockSetupPINScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */; }; 0F81DEE3E02A6549B20DF09A /* DeactivateAccountScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633924B26ACCD29C18BEF4E8 /* DeactivateAccountScreenViewModelProtocol.swift */; }; 0FA03F5A33C0857231B32B44 /* ReportRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDB0B87D925AE830E32621 /* ReportRoomScreenViewModel.swift */; }; @@ -184,7 +183,6 @@ 1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */; }; 208C19811613F9A10F8A7B75 /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; }; 20C16A3F718802B0E4A19C83 /* URLComponentsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76310030C831D4610A705603 /* URLComponentsTests.swift */; }; - 210DB40676DF2A23E69C2D06 /* AuthenticationClientBuilderFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B655A536341D2695158C6664 /* AuthenticationClientBuilderFactory.swift */; }; 2118E35D312951B241067BD5 /* MessageComposerTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 345172AD4377E83A44BD864F /* MessageComposerTextField.swift */; }; 211B5F524E851178EE549417 /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; }; 21813AF91CFC6F3E3896DB53 /* AppLockSetupBiometricsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10F130DF775CE6BC51A4E392 /* AppLockSetupBiometricsScreenModels.swift */; }; @@ -727,7 +725,6 @@ 89DF67AECBF9D0EE0DDB7737 /* Tracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83B574805B9812C111D6215D /* Tracing.swift */; }; 8A0BD60CA4A6004DB06B5403 /* MediaUploadingPreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */; }; 8A5064CAC8E5F3B18645621D /* CallNotificationRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6E082B0507FB28F966516A /* CallNotificationRoomTimelineView.swift */; }; - 8A6CB15C8FC68F557750BF54 /* AuthenticationClientBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F569CFB77E0D40BD82203D9 /* AuthenticationClientBuilder.swift */; }; 8A83D715940378B9BA9F739E /* RoomInviterLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EB58E4E8D6D634C246AD5C2 /* RoomInviterLabel.swift */; }; 8AA84EF202F2EFC8453A97BD /* SecureBackupRecoveryKeyScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 645E027C112740573D27765C /* SecureBackupRecoveryKeyScreenModels.swift */; }; 8AB8ED1051216546CB35FA0E /* UserSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E5E9C044BEB7C70B1378E91 /* UserSession.swift */; }; @@ -913,6 +910,7 @@ AC90434798E7894370E80E66 /* SecureBackupScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D79BB714D28C9F588DD69353 /* SecureBackupScreenViewModelProtocol.swift */; }; AD2A81B65A9F6163012086F1 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; }; AD55E245FE686D7DB4C86406 /* RoomTimelineItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */; }; + AE066FC93E7B707C826B335A /* AuthenticationClientFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBD19057FDB154A44335CE62 /* AuthenticationClientFactory.swift */; }; AE07F215EBC2B9CBF17AA54B /* TimelineItemMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1C3CBBC62C566DDF5E84C1 /* TimelineItemMenuAction.swift */; }; AE1160076F663BF14E0E893A /* EffectsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4548A9BDE5CB3AB864BCA9F /* EffectsView.swift */; }; AE1A73B24D63DA3D63DC4EE3 /* SessionVerificationControllerProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */; }; @@ -977,7 +975,6 @@ BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; }; BA48D6AFF6421D199148C0A1 /* KnockRequestsListScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */; }; BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */; }; - BB04B1D8E7401C90506D401E /* QRCodeLoginServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536C0E2178949B290776EA4E /* QRCodeLoginServiceProtocol.swift */; }; BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */; }; BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */; }; BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */; }; @@ -1041,7 +1038,6 @@ C85C7A201E4CFDA477ACEBEB /* AppLockSetupSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8610C1D21565C950BCA6A454 /* AppLockSetupSettingsScreenViewModelProtocol.swift */; }; C8A9C595038AFA2D707AC8C1 /* NotificationPermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */; }; C8BD80891BAD688EF2C15CDB /* MediaUploadPreviewScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */; }; - C8C7AF33AADF88B306CD2695 /* QRCodeLoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4427AF4B7FB7EF3E3D424C7 /* QRCodeLoginService.swift */; }; C8E0FA0FF2CD6613264FA6B9 /* MessageForwardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEA446F8618DBA79A9239CC /* MessageForwardingScreen.swift */; }; C8E1E4E06B7C7A3A8246FC9B /* MediaEventsTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8512B82404B1751D0BCC82D2 /* MediaEventsTimelineScreenCoordinator.swift */; }; C915347779B3C7FDD073A87A /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E1FF0DFBB3768F79FDBF6D /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift */; }; @@ -1472,7 +1468,6 @@ 0E95B3BDB80531C85CD50AE6 /* InvitedRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitedRoomProxy.swift; sourceTree = ""; }; 0EE9EAF0309A2A1D67D8FAF5 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sv; path = sv.lproj/Localizable.stringsdict; sourceTree = ""; }; 0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = ""; }; - 0F569CFB77E0D40BD82203D9 /* AuthenticationClientBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilder.swift; sourceTree = ""; }; 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenModels.swift; sourceTree = ""; }; 0F71A54CB96DAA1E72C6541D /* AuthenticationStartScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModel.swift; sourceTree = ""; }; 0F793C422BDACE0C60C774F4 /* UserIdentityProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIdentityProxyProtocol.swift; sourceTree = ""; }; @@ -1776,7 +1771,6 @@ 471BB7276C97AF60B3A5463B /* RoomDirectorySearchProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxy.swift; sourceTree = ""; }; 475D47D0BFE961B02BAC5D49 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = id; path = id.lproj/Localizable.stringsdict; sourceTree = ""; }; 475EB595D7527E9A8A14043E /* uz */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uz; path = uz.lproj/Localizable.strings; sourceTree = ""; }; - 4760CE2128FBC217304272AB /* AuthenticationClientBuilderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilderMock.swift; sourceTree = ""; }; 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenModels.swift; sourceTree = ""; }; 47EBB5D698CE9A25BB553A2D /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = ""; }; 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModel.swift; sourceTree = ""; }; @@ -1828,7 +1822,6 @@ 5327E3B3C58BEB0E65F4CF98 /* Observable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = ""; }; 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = ""; }; 5351EBD7A0B9610548E4B7B2 /* EncryptedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedRoomTimelineItem.swift; sourceTree = ""; }; - 536C0E2178949B290776EA4E /* QRCodeLoginServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginServiceProtocol.swift; sourceTree = ""; }; 536E72DCBEEC4A1FE66CFDCE /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 53F41CEAAE2BB4E74CDC2278 /* TimelineMediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewViewModel.swift; sourceTree = ""; }; 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = test_animated_image.gif; sourceTree = ""; }; @@ -2301,7 +2294,6 @@ B40233F2989AD49906BB310D /* RoomPollsHistoryScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModelTests.swift; sourceTree = ""; }; B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenModels.swift; sourceTree = ""; }; B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModel.swift; sourceTree = ""; }; - B4427AF4B7FB7EF3E3D424C7 /* QRCodeLoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginService.swift; sourceTree = ""; }; B4AE42C19EDE64B7CB7BE4D0 /* SecurityAndPrivacyScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreen.swift; sourceTree = ""; }; B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Analytics+SwiftUI.swift"; sourceTree = ""; }; B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyProtocol.swift; sourceTree = ""; }; @@ -2310,7 +2302,6 @@ B5D829FD8958376614504B18 /* TargetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetConfiguration.swift; sourceTree = ""; }; B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = ""; }; - B655A536341D2695158C6664 /* AuthenticationClientBuilderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilderFactory.swift; sourceTree = ""; }; B65DDCF8E41759890355ACBC /* AuthenticationStartScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelProtocol.swift; sourceTree = ""; }; B68B31232312AFC844440BFE /* DeclineAndBlockScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeclineAndBlockScreenModels.swift; sourceTree = ""; }; B69AEA8755382DB34892FB7B /* ThreadTimelineScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadTimelineScreenModels.swift; sourceTree = ""; }; @@ -2575,6 +2566,7 @@ EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = ""; }; EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenModels.swift; sourceTree = ""; }; EB76A9AFC6CCAD4998D9B045 /* IdentityConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenViewModel.swift; sourceTree = ""; }; + EBD19057FDB154A44335CE62 /* AuthenticationClientFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientFactory.swift; sourceTree = ""; }; EBD21AF0131AA38FF9534FAD /* EditRoomAddressScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditRoomAddressScreenModels.swift; sourceTree = ""; }; EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsNotificationCenter.swift; sourceTree = ""; }; EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsViewModelTests.swift; sourceTree = ""; }; @@ -2885,7 +2877,6 @@ 6DE13A7AE6587B079F4049D7 /* Notification */, 114DC16B28140F885FD833E2 /* NotificationSettings */, 599DFFE0805B08454E40D64A /* Polls */, - 70CC0CDA4AFDF8299C56ADE7 /* QRCode */, 40E6246F03D1FE377BC5D963 /* Room */, 4FFDC8D1A752384B4C6EB0EB /* RoomDirectorySearch */, BDCEF7C3BF6D09F5611CFC8B /* SecureBackup */, @@ -3334,7 +3325,6 @@ 69CB8242D69B7E4D0B32E18D /* AggregatedReactionMock.swift */, 3BAC027034248429A438886B /* AppMediatorMock.swift */, 0554FEA301486A8CFA475D5A /* AuthenticationClientBuilderFactoryMock.swift */, - 4760CE2128FBC217304272AB /* AuthenticationClientBuilderMock.swift */, 9FD7E851E2BA8C5A8D284B2A /* BannedRoomProxyMock.swift */, 8F7FC9580CABF797A2E6213A /* BugReportServiceMock.swift */, E2F96CCBEAAA7F2185BFA354 /* ClientProxyMock.swift */, @@ -4330,15 +4320,6 @@ path = Settings; sourceTree = ""; }; - 70CC0CDA4AFDF8299C56ADE7 /* QRCode */ = { - isa = PBXGroup; - children = ( - B4427AF4B7FB7EF3E3D424C7 /* QRCodeLoginService.swift */, - 536C0E2178949B290776EA4E /* QRCodeLoginServiceProtocol.swift */, - ); - path = QRCode; - sourceTree = ""; - }; 70DABA39C844CA931B829395 /* RoomSummary */ = { isa = PBXGroup; children = ( @@ -5305,8 +5286,7 @@ AAFDD509929A0CCF8BCE51EB /* Authentication */ = { isa = PBXGroup; children = ( - 0F569CFB77E0D40BD82203D9 /* AuthenticationClientBuilder.swift */, - B655A536341D2695158C6664 /* AuthenticationClientBuilderFactory.swift */, + EBD19057FDB154A44335CE62 /* AuthenticationClientFactory.swift */, F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */, 5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */, A69869844D2B6F5BD9AABF85 /* OIDCConfigurationProxy.swift */, @@ -7222,10 +7202,8 @@ 88F348E2CB14FF71CBBB665D /* AudioRoomTimelineItemContent.swift in Sources */, 7BD2123144A32F082CECC108 /* AudioRoomTimelineView.swift in Sources */, 9278EC51D24E57445B290521 /* AudioSessionProtocol.swift in Sources */, - 8A6CB15C8FC68F557750BF54 /* AuthenticationClientBuilder.swift in Sources */, - 210DB40676DF2A23E69C2D06 /* AuthenticationClientBuilderFactory.swift in Sources */, A51C65E5A3C9F2464A91A380 /* AuthenticationClientBuilderFactoryMock.swift in Sources */, - 0F4709282FCCFBEFED427B8A /* AuthenticationClientBuilderMock.swift in Sources */, + AE066FC93E7B707C826B335A /* AuthenticationClientFactory.swift in Sources */, 67E9926C4572C54F59FCA91A /* AuthenticationFlowCoordinator.swift in Sources */, 9847B056C1A216C314D21E68 /* AuthenticationService.swift in Sources */, 56DACDD379A86A1F5DEFE7BE /* AuthenticationServiceProtocol.swift in Sources */, @@ -7650,8 +7628,6 @@ 46FCD999E92D9717D24AAB94 /* QRCodeLoginScreenModels.swift in Sources */, 30E5628F74AD3C27A061BF25 /* QRCodeLoginScreenViewModel.swift in Sources */, E9D2ED1C4186931E3D5FDA4E /* QRCodeLoginScreenViewModelProtocol.swift in Sources */, - C8C7AF33AADF88B306CD2695 /* QRCodeLoginService.swift in Sources */, - BB04B1D8E7401C90506D401E /* QRCodeLoginServiceProtocol.swift in Sources */, FDD5B4B616D9FF4DE3E9A418 /* QRCodeScannerView.swift in Sources */, C9A631FD968249B4BA0B7B3C /* ReactionsSummaryView.swift in Sources */, 743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */, diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 00ceaa59b..f515eb12f 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -546,13 +546,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg encryptionKeyProvider: encryptionKeyProvider, appSettings: appSettings, appHooks: appHooks) - let qrCodeLoginService = QRCodeLoginService(encryptionKeyProvider: encryptionKeyProvider, - userSessionStore: userSessionStore, - appSettings: appSettings, - appHooks: appHooks) let coordinator = AuthenticationFlowCoordinator(authenticationService: authenticationService, - qrCodeLoginService: qrCodeLoginService, bugReportService: ServiceLocator.shared.bugReportService, navigationRootCoordinator: navigationRootCoordinator, appMediator: appMediator, diff --git a/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift index a8357f998..4048de6fc 100644 --- a/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift @@ -23,7 +23,6 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { private let appSettings: AppSettings private let analytics: AnalyticsService private let userIndicatorController: UserIndicatorControllerProtocol - private let qrCodeLoginService: QRCodeLoginServiceProtocol enum State: StateType { /// The state machine hasn't started. @@ -102,7 +101,6 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { weak var delegate: AuthenticationFlowCoordinatorDelegate? init(authenticationService: AuthenticationServiceProtocol, - qrCodeLoginService: QRCodeLoginServiceProtocol, bugReportService: BugReportServiceProtocol, navigationRootCoordinator: NavigationRootCoordinator, appMediator: AppMediatorProtocol, @@ -116,7 +114,6 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { self.appSettings = appSettings self.analytics = analytics self.userIndicatorController = userIndicatorController - self.qrCodeLoginService = qrCodeLoginService navigationStackCoordinator = NavigationStackCoordinator() @@ -300,7 +297,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { // MARK: - QR Code private func showQRCodeLoginScreen() { - let coordinator = QRCodeLoginScreenCoordinator(parameters: .init(qrCodeLoginService: qrCodeLoginService, + let coordinator = QRCodeLoginScreenCoordinator(parameters: .init(qrCodeLoginService: authenticationService, canSignInManually: appSettings.allowOtherAccountProviders, // No need to worry about provisioning links as we hide QR login. orientationManager: appMediator.windowManager, appMediator: appMediator)) diff --git a/ElementX/Sources/Mocks/AuthenticationClientBuilderFactoryMock.swift b/ElementX/Sources/Mocks/AuthenticationClientBuilderFactoryMock.swift index 381f25511..87195c65d 100644 --- a/ElementX/Sources/Mocks/AuthenticationClientBuilderFactoryMock.swift +++ b/ElementX/Sources/Mocks/AuthenticationClientBuilderFactoryMock.swift @@ -8,15 +8,39 @@ import Foundation import MatrixRustSDK -extension AuthenticationClientBuilderFactoryMock { +extension AuthenticationClientFactoryMock { struct Configuration { - var builderConfiguration: AuthenticationClientBuilderMock.Configuration = .init() + var homeserverClients = [ + "matrix.org": ClientSDKMock(configuration: .init()), + "example.com": ClientSDKMock(configuration: .init(serverAddress: "example.com", + homeserverURL: "https://matrix.example.com", + slidingSyncVersion: .native, + oidcLoginURL: nil, + supportsOIDCCreatePrompt: false, + supportsPasswordLogin: true)), + "company.com": ClientSDKMock(configuration: .init(serverAddress: "company.com", + homeserverURL: "https://matrix.company.com", + slidingSyncVersion: .native, + oidcLoginURL: "https://auth.company.com/oidc", + supportsOIDCCreatePrompt: false, + supportsPasswordLogin: false)), + "server.net": ClientSDKMock(configuration: .init(serverAddress: "server.net", + homeserverURL: "https://matrix.example.com", + slidingSyncVersion: .native, + oidcLoginURL: nil, + supportsOIDCCreatePrompt: false, + supportsPasswordLogin: false)) + ] } convenience init(configuration: Configuration) { self.init() - let clientBuilder = AuthenticationClientBuilderMock(configuration: configuration.builderConfiguration) - makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReturnValue = clientBuilder + makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure = { address, _, _, _, _, _ in + guard let client = configuration.homeserverClients[address] else { + throw ClientBuildError.ServerUnreachable(message: "Not a known homeserver.") + } + return client + } } } diff --git a/ElementX/Sources/Mocks/AuthenticationClientBuilderMock.swift b/ElementX/Sources/Mocks/AuthenticationClientBuilderMock.swift deleted file mode 100644 index 4e7395e97..000000000 --- a/ElementX/Sources/Mocks/AuthenticationClientBuilderMock.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright 2024 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -// Please see LICENSE files in the repository root for full details. -// - -import Foundation -import MatrixRustSDK - -extension AuthenticationClientBuilderMock { - struct Configuration { - var homeserverClients = [ - "matrix.org": ClientSDKMock(configuration: .init()), - "example.com": ClientSDKMock(configuration: .init(serverAddress: "example.com", - homeserverURL: "https://matrix.example.com", - slidingSyncVersion: .native, - oidcLoginURL: nil, - supportsOIDCCreatePrompt: false, - supportsPasswordLogin: true)), - "company.com": ClientSDKMock(configuration: .init(serverAddress: "company.com", - homeserverURL: "https://matrix.company.com", - slidingSyncVersion: .native, - oidcLoginURL: "https://auth.company.com/oidc", - supportsOIDCCreatePrompt: false, - supportsPasswordLogin: false)), - "server.net": ClientSDKMock(configuration: .init(serverAddress: "server.net", - homeserverURL: "https://matrix.example.com", - slidingSyncVersion: .native, - oidcLoginURL: nil, - supportsOIDCCreatePrompt: false, - supportsPasswordLogin: false)) - ] - } - - convenience init(configuration: Configuration) { - self.init() - - buildHomeserverAddressClosure = { address in - guard let client = configuration.homeserverClients[address] else { - throw ClientBuildError.ServerUnreachable(message: "Not a known homeserver.") - } - return client - } - } -} diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index a17e31a23..6ce4431e8 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -1823,19 +1823,20 @@ class AudioSessionMock: AudioSessionProtocol, @unchecked Sendable { try setActiveOptionsClosure?(active, options) } } -class AuthenticationClientBuilderFactoryMock: AuthenticationClientBuilderFactoryProtocol, @unchecked Sendable { +class AuthenticationClientFactoryMock: AuthenticationClientFactoryProtocol, @unchecked Sendable { - //MARK: - makeBuilder + //MARK: - makeClient - var makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount = 0 - var makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount: Int { + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksThrowableError: Error? + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount = 0 + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount: Int { get { if Thread.isMainThread { - return makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount + return makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount + returnValue = makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount } return returnValue! @@ -1843,103 +1844,29 @@ class AuthenticationClientBuilderFactoryMock: AuthenticationClientBuilderFactory } set { if Thread.isMainThread { - makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount = newValue + makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount = newValue + makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingCallsCount = newValue } } } } - var makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCalled: Bool { - return makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount > 0 + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCalled: Bool { + return makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount > 0 } - var makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedArguments: (sessionDirectories: SessionDirectories, passphrase: String, clientSessionDelegate: ClientSessionDelegate, appSettings: AppSettings, appHooks: AppHooks)? - var makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedInvocations: [(sessionDirectories: SessionDirectories, passphrase: String, clientSessionDelegate: ClientSessionDelegate, appSettings: AppSettings, appHooks: AppHooks)] = [] + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedArguments: (homeserverAddress: String, sessionDirectories: SessionDirectories, passphrase: String, clientSessionDelegate: ClientSessionDelegate, appSettings: AppSettings, appHooks: AppHooks)? + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedInvocations: [(homeserverAddress: String, sessionDirectories: SessionDirectories, passphrase: String, clientSessionDelegate: ClientSessionDelegate, appSettings: AppSettings, appHooks: AppHooks)] = [] - var makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue: AuthenticationClientBuilderProtocol! - var makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReturnValue: AuthenticationClientBuilderProtocol! { + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue: ClientProtocol! + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReturnValue: ClientProtocol! { get { if Thread.isMainThread { - return makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue - } else { - var returnValue: AuthenticationClientBuilderProtocol? = nil - DispatchQueue.main.sync { - returnValue = makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue = newValue - } else { - DispatchQueue.main.sync { - makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue = newValue - } - } - } - } - var makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure: ((SessionDirectories, String, ClientSessionDelegate, AppSettings, AppHooks) -> AuthenticationClientBuilderProtocol)? - - func makeBuilder(sessionDirectories: SessionDirectories, passphrase: String, clientSessionDelegate: ClientSessionDelegate, appSettings: AppSettings, appHooks: AppHooks) -> AuthenticationClientBuilderProtocol { - makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount += 1 - makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedArguments = (sessionDirectories: sessionDirectories, passphrase: passphrase, clientSessionDelegate: clientSessionDelegate, appSettings: appSettings, appHooks: appHooks) - DispatchQueue.main.async { - self.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedInvocations.append((sessionDirectories: sessionDirectories, passphrase: passphrase, clientSessionDelegate: clientSessionDelegate, appSettings: appSettings, appHooks: appHooks)) - } - if let makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure = makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure { - return makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure(sessionDirectories, passphrase, clientSessionDelegate, appSettings, appHooks) - } else { - return makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReturnValue - } - } -} -class AuthenticationClientBuilderMock: AuthenticationClientBuilderProtocol, @unchecked Sendable { - - //MARK: - build - - var buildHomeserverAddressThrowableError: Error? - var buildHomeserverAddressUnderlyingCallsCount = 0 - var buildHomeserverAddressCallsCount: Int { - get { - if Thread.isMainThread { - return buildHomeserverAddressUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = buildHomeserverAddressUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - buildHomeserverAddressUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - buildHomeserverAddressUnderlyingCallsCount = newValue - } - } - } - } - var buildHomeserverAddressCalled: Bool { - return buildHomeserverAddressCallsCount > 0 - } - var buildHomeserverAddressReceivedHomeserverAddress: String? - var buildHomeserverAddressReceivedInvocations: [String] = [] - - var buildHomeserverAddressUnderlyingReturnValue: ClientProtocol! - var buildHomeserverAddressReturnValue: ClientProtocol! { - get { - if Thread.isMainThread { - return buildHomeserverAddressUnderlyingReturnValue + return makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue } else { var returnValue: ClientProtocol? = nil DispatchQueue.main.sync { - returnValue = buildHomeserverAddressUnderlyingReturnValue + returnValue = makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue } return returnValue! @@ -1947,29 +1874,29 @@ class AuthenticationClientBuilderMock: AuthenticationClientBuilderProtocol, @unc } set { if Thread.isMainThread { - buildHomeserverAddressUnderlyingReturnValue = newValue + makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - buildHomeserverAddressUnderlyingReturnValue = newValue + makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksUnderlyingReturnValue = newValue } } } } - var buildHomeserverAddressClosure: ((String) async throws -> ClientProtocol)? + var makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure: ((String, SessionDirectories, String, ClientSessionDelegate, AppSettings, AppHooks) async throws -> ClientProtocol)? - func build(homeserverAddress: String) async throws -> ClientProtocol { - if let error = buildHomeserverAddressThrowableError { + func makeClient(homeserverAddress: String, sessionDirectories: SessionDirectories, passphrase: String, clientSessionDelegate: ClientSessionDelegate, appSettings: AppSettings, appHooks: AppHooks) async throws -> ClientProtocol { + if let error = makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksThrowableError { throw error } - buildHomeserverAddressCallsCount += 1 - buildHomeserverAddressReceivedHomeserverAddress = homeserverAddress + makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount += 1 + makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedArguments = (homeserverAddress: homeserverAddress, sessionDirectories: sessionDirectories, passphrase: passphrase, clientSessionDelegate: clientSessionDelegate, appSettings: appSettings, appHooks: appHooks) DispatchQueue.main.async { - self.buildHomeserverAddressReceivedInvocations.append(homeserverAddress) + self.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReceivedInvocations.append((homeserverAddress: homeserverAddress, sessionDirectories: sessionDirectories, passphrase: passphrase, clientSessionDelegate: clientSessionDelegate, appSettings: appSettings, appHooks: appHooks)) } - if let buildHomeserverAddressClosure = buildHomeserverAddressClosure { - return try await buildHomeserverAddressClosure(homeserverAddress) + if let makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure = makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure { + return try await makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksClosure(homeserverAddress, sessionDirectories, passphrase, clientSessionDelegate, appSettings, appHooks) } else { - return buildHomeserverAddressReturnValue + return makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksReturnValue } } } @@ -13192,13 +13119,13 @@ class QRCodeLoginServiceMock: QRCodeLoginServiceProtocol, @unchecked Sendable { var loginWithQRCodeDataReceivedData: Data? var loginWithQRCodeDataReceivedInvocations: [Data] = [] - var loginWithQRCodeDataUnderlyingReturnValue: Result! - var loginWithQRCodeDataReturnValue: Result! { + var loginWithQRCodeDataUnderlyingReturnValue: Result! + var loginWithQRCodeDataReturnValue: Result! { get { if Thread.isMainThread { return loginWithQRCodeDataUnderlyingReturnValue } else { - var returnValue: Result? = nil + var returnValue: Result? = nil DispatchQueue.main.sync { returnValue = loginWithQRCodeDataUnderlyingReturnValue } @@ -13216,9 +13143,9 @@ class QRCodeLoginServiceMock: QRCodeLoginServiceProtocol, @unchecked Sendable { } } } - var loginWithQRCodeDataClosure: ((Data) async -> Result)? + var loginWithQRCodeDataClosure: ((Data) async -> Result)? - func loginWithQRCode(data: Data) async -> Result { + func loginWithQRCode(data: Data) async -> Result { loginWithQRCodeDataCallsCount += 1 loginWithQRCodeDataReceivedData = data DispatchQueue.main.async { diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift index 70f4d0faa..7b6a382e3 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift @@ -110,13 +110,15 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr case let .success(session): MXLog.info("QR Login completed") actionsSubject.send(.done(userSession: session)) - case .failure(let error): - handleError(error: error) + case .failure(.qrCodeError(let error)): + handleError(error) + case .failure: + handleError(.unknown) } } } - private func handleError(error: QRCodeLoginServiceError) { + private func handleError(_ error: QRCodeLoginError) { MXLog.error("Failed to scan the QR code: \(error)") switch error { case .invalidQRCode: @@ -137,7 +139,7 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr state.state = .error(.expired) case .deviceNotSupported: state.state = .error(.deviceNotSupported) - case .failedLoggingIn, .unknown: + case .unknown: state.state = .error(.unknown) } } diff --git a/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift b/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift deleted file mode 100644 index 3746b4383..000000000 --- a/ElementX/Sources/Services/Authentication/AuthenticationClientBuilder.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright 2024 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -// Please see LICENSE files in the repository root for full details. -// - -import Foundation -import MatrixRustSDK - -// sourcery: AutoMockable -protocol AuthenticationClientBuilderProtocol { - func build(homeserverAddress: String) async throws -> ClientProtocol -} - -/// A wrapper around `ClientBuilder` to share reusable code between Normal and QR logins. -struct AuthenticationClientBuilder: AuthenticationClientBuilderProtocol { - let sessionDirectories: SessionDirectories - let passphrase: String - let clientSessionDelegate: ClientSessionDelegate - - let appSettings: AppSettings - let appHooks: AppHooks - - /// Builds a Client for login using OIDC or password authentication. - func build(homeserverAddress: String) async throws -> ClientProtocol { - try await makeClientBuilder().serverNameOrHomeserverUrl(serverNameOrUrl: homeserverAddress).build() - } - - // MARK: - Private - - /// The base builder configuration used for authentication within the app. - private func makeClientBuilder() -> ClientBuilder { - ClientBuilder - .baseBuilder(httpProxy: appSettings.websiteURL.globalProxy, - slidingSync: .discover, - sessionDelegate: clientSessionDelegate, - appHooks: appHooks, - enableOnlySignedDeviceIsolationMode: appSettings.enableOnlySignedDeviceIsolationMode, - enableKeyShareOnInvite: appSettings.enableKeyShareOnInvite, - threadsEnabled: appSettings.threadsEnabled) - .sessionPaths(dataPath: sessionDirectories.dataPath, - cachePath: sessionDirectories.cachePath) - .sessionPassphrase(passphrase: passphrase) - } -} diff --git a/ElementX/Sources/Services/Authentication/AuthenticationClientBuilderFactory.swift b/ElementX/Sources/Services/Authentication/AuthenticationClientBuilderFactory.swift deleted file mode 100644 index 119acc382..000000000 --- a/ElementX/Sources/Services/Authentication/AuthenticationClientBuilderFactory.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright 2024 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -// Please see LICENSE files in the repository root for full details. -// - -import Foundation -import MatrixRustSDK - -// sourcery: AutoMockable -protocol AuthenticationClientBuilderFactoryProtocol { - func makeBuilder(sessionDirectories: SessionDirectories, - passphrase: String, - clientSessionDelegate: ClientSessionDelegate, - appSettings: AppSettings, - appHooks: AppHooks) -> AuthenticationClientBuilderProtocol -} - -/// A wrapper around `ClientBuilder` to share reusable code between Normal and QR logins. -struct AuthenticationClientBuilderFactory: AuthenticationClientBuilderFactoryProtocol { - func makeBuilder(sessionDirectories: SessionDirectories, - passphrase: String, - clientSessionDelegate: ClientSessionDelegate, - appSettings: AppSettings, - appHooks: AppHooks) -> AuthenticationClientBuilderProtocol { - AuthenticationClientBuilder(sessionDirectories: sessionDirectories, - passphrase: passphrase, - clientSessionDelegate: clientSessionDelegate, - appSettings: appSettings, - appHooks: appHooks) - } -} diff --git a/ElementX/Sources/Services/Authentication/AuthenticationClientFactory.swift b/ElementX/Sources/Services/Authentication/AuthenticationClientFactory.swift new file mode 100644 index 000000000..307e5d27f --- /dev/null +++ b/ElementX/Sources/Services/Authentication/AuthenticationClientFactory.swift @@ -0,0 +1,43 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +// Please see LICENSE files in the repository root for full details. +// + +import Foundation +import MatrixRustSDK + +// sourcery: AutoMockable +protocol AuthenticationClientFactoryProtocol { + func makeClient(homeserverAddress: String, + sessionDirectories: SessionDirectories, + passphrase: String, + clientSessionDelegate: ClientSessionDelegate, + appSettings: AppSettings, + appHooks: AppHooks) async throws -> ClientProtocol +} + +/// A wrapper around `ClientBuilder` to allow for mocked clients to be injected into authentication tests. +struct AuthenticationClientFactory: AuthenticationClientFactoryProtocol { + func makeClient(homeserverAddress: String, + sessionDirectories: SessionDirectories, + passphrase: String, + clientSessionDelegate: ClientSessionDelegate, + appSettings: AppSettings, + appHooks: AppHooks) async throws -> ClientProtocol { + try await ClientBuilder + .baseBuilder(httpProxy: appSettings.websiteURL.globalProxy, + slidingSync: .discover, + sessionDelegate: clientSessionDelegate, + appHooks: appHooks, + enableOnlySignedDeviceIsolationMode: appSettings.enableOnlySignedDeviceIsolationMode, + enableKeyShareOnInvite: appSettings.enableKeyShareOnInvite, + threadsEnabled: appSettings.threadsEnabled) + .sessionPaths(dataPath: sessionDirectories.dataPath, + cachePath: sessionDirectories.cachePath) + .sessionPassphrase(passphrase: passphrase) + .serverNameOrHomeserverUrl(serverNameOrUrl: homeserverAddress) + .build() + } +} diff --git a/ElementX/Sources/Services/Authentication/AuthenticationService.swift b/ElementX/Sources/Services/Authentication/AuthenticationService.swift index 8fbccce81..cca842e68 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationService.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationService.swift @@ -14,7 +14,7 @@ class AuthenticationService: AuthenticationServiceProtocol { private var sessionDirectories: SessionDirectories private let passphrase: String - private let clientBuilderFactory: AuthenticationClientBuilderFactoryProtocol + private let clientFactory: AuthenticationClientFactoryProtocol private let userSessionStore: UserSessionStoreProtocol private let appSettings: AppSettings private let appHooks: AppHooks @@ -23,14 +23,19 @@ class AuthenticationService: AuthenticationServiceProtocol { var homeserver: CurrentValuePublisher { homeserverSubject.asCurrentValuePublisher() } private(set) var flow: AuthenticationFlow + private let qrLoginProgressSubject = PassthroughSubject() + var qrLoginProgressPublisher: AnyPublisher { + qrLoginProgressSubject.eraseToAnyPublisher() + } + init(userSessionStore: UserSessionStoreProtocol, encryptionKeyProvider: EncryptionKeyProviderProtocol, - clientBuilderFactory: AuthenticationClientBuilderFactoryProtocol = AuthenticationClientBuilderFactory(), + clientFactory: AuthenticationClientFactoryProtocol = AuthenticationClientFactory(), appSettings: AppSettings, appHooks: AppHooks) { sessionDirectories = .init() passphrase = encryptionKeyProvider.generateKey().base64EncodedString() - self.clientBuilderFactory = clientBuilderFactory + self.clientFactory = clientFactory self.userSessionStore = userSessionStore self.appSettings = appSettings self.appHooks = appHooks @@ -46,7 +51,7 @@ class AuthenticationService: AuthenticationServiceProtocol { do { var homeserver = LoginHomeserver(address: homeserverAddress, loginMode: .unknown) - let client = try await makeClientBuilder().build(homeserverAddress: homeserverAddress) + let client = try await makeClient(homeserverAddress: homeserverAddress) let loginDetails = await client.homeserverLoginDetails() MXLog.info("Sliding sync: \(client.slidingSyncVersion())") @@ -146,6 +151,45 @@ class AuthenticationService: AuthenticationServiceProtocol { } } + func loginWithQRCode(data: Data) async -> Result { + let qrData: QrCodeData + do { + qrData = try QrCodeData.fromBytes(bytes: data) + } catch { + MXLog.error("QRCode decode error: \(error)") + return .failure(.qrCodeError(.invalidQRCode)) + } + + guard let scannedServerName = qrData.serverName() else { + MXLog.error("The QR code is from a device that is not yet signed in.") + return .failure(.qrCodeError(.deviceNotSignedIn)) + } + + if !appSettings.allowOtherAccountProviders, !appSettings.accountProviders.contains(scannedServerName) { + MXLog.error("The scanned device's server is not allowed: \(scannedServerName)") + return .failure(.qrCodeError(.providerNotAllowed(scannedProvider: scannedServerName, allowedProviders: appSettings.accountProviders))) + } + + let listener = SDKListener { [weak self] progress in + self?.qrLoginProgressSubject.send(progress) + } + + do { + let client = try await makeClient(homeserverAddress: scannedServerName) + try await client.loginWithQrCode(qrCodeData: qrData, + oidcConfiguration: appSettings.oidcConfiguration.rustValue, + progressListener: listener) + MXLog.info("Sliding sync: \(client.slidingSyncVersion())") + return await userSession(for: client) + } catch let error as HumanQrLoginError { + MXLog.error("QRCode login error: \(error)") + return .failure(error.serviceError) + } catch { + MXLog.error("QRCode login unknown error: \(error)") + return .failure(.qrCodeError(.unknown)) + } + } + func reset() { homeserverSubject.send(LoginHomeserver(address: appSettings.accountProviders[0], loginMode: .unknown)) flow = .login @@ -154,16 +198,17 @@ class AuthenticationService: AuthenticationServiceProtocol { // MARK: - Private - private func makeClientBuilder() -> AuthenticationClientBuilderProtocol { + private func makeClient(homeserverAddress: String) async throws -> ClientProtocol { // Use a fresh session directory each time the user enters a different server // so that caches (e.g. server versions) are always fresh for the new server. rotateSessionDirectory() - return clientBuilderFactory.makeBuilder(sessionDirectories: sessionDirectories, - passphrase: passphrase, - clientSessionDelegate: userSessionStore.clientSessionDelegate, - appSettings: appSettings, - appHooks: appHooks) + return try await clientFactory.makeClient(homeserverAddress: homeserverAddress, + sessionDirectories: sessionDirectories, + passphrase: passphrase, + clientSessionDelegate: userSessionStore.clientSessionDelegate, + appSettings: appSettings, + appHooks: appHooks) } private func rotateSessionDirectory() { @@ -181,13 +226,36 @@ class AuthenticationService: AuthenticationServiceProtocol { } } +private extension HumanQrLoginError { + var serviceError: AuthenticationServiceError { + switch self { + case .Cancelled: + .qrCodeError(.cancelled) + case .ConnectionInsecure: + .qrCodeError(.connectionInsecure) + case .Declined: + .qrCodeError(.declined) + case .LinkingNotSupported: + .qrCodeError(.linkingNotSupported) + case .Expired: + .qrCodeError(.expired) + case .SlidingSyncNotAvailable: + .qrCodeError(.deviceNotSupported) + case .OtherDeviceNotSignedIn: + .qrCodeError(.deviceNotSignedIn) + case .Unknown, .OidcMetadataInvalid: + .qrCodeError(.unknown) + } + } +} + // MARK: - Mocks extension AuthenticationService { static var mock: AuthenticationService { AuthenticationService(userSessionStore: UserSessionStoreMock(configuration: .init()), encryptionKeyProvider: EncryptionKeyProvider(), - clientBuilderFactory: AuthenticationClientBuilderFactoryMock(configuration: .init()), + clientFactory: AuthenticationClientFactoryMock(configuration: .init()), appSettings: ServiceLocator.shared.settings, appHooks: AppHooks()) } diff --git a/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift b/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift index 332274cdd..a844a6e62 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationServiceProtocol.swift @@ -5,6 +5,7 @@ // Please see LICENSE files in the repository root for full details. // +import Combine import Foundation import MatrixRustSDK @@ -19,6 +20,9 @@ enum AuthenticationFlow { enum AuthenticationServiceError: Error, Equatable { /// An error occurred during OIDC authentication. case oidcError(OIDCError) + /// An error occurred during login with QR Code. + case qrCodeError(QRCodeLoginError) + case invalidServer case invalidCredentials case invalidHomeserverAddress @@ -32,7 +36,7 @@ enum AuthenticationServiceError: Error, Equatable { case failedUsingWebCredentials } -protocol AuthenticationServiceProtocol { +protocol AuthenticationServiceProtocol: QRCodeLoginServiceProtocol { /// The currently configured homeserver. var homeserver: CurrentValuePublisher { get } /// The type of flow the service is currently configured with. @@ -86,3 +90,25 @@ extension OAuthAuthorizationData: @retroactive Hashable { hasher.combine(loginUrl()) } } + +// MARK: - Login with QR code + +enum QRCodeLoginError: Error, Equatable { + case invalidQRCode + case providerNotAllowed(scannedProvider: String, allowedProviders: [String]) + case cancelled + case connectionInsecure + case declined + case linkingNotSupported + case expired + case deviceNotSupported + case deviceNotSignedIn + case unknown +} + +// sourcery: AutoMockable +protocol QRCodeLoginServiceProtocol { + var qrLoginProgressPublisher: AnyPublisher { get } + + func loginWithQRCode(data: Data) async -> Result +} diff --git a/ElementX/Sources/Services/QRCode/QRCodeLoginService.swift b/ElementX/Sources/Services/QRCode/QRCodeLoginService.swift deleted file mode 100644 index 3ff3cdc59..000000000 --- a/ElementX/Sources/Services/QRCode/QRCodeLoginService.swift +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright 2024 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -// Please see LICENSE files in the repository root for full details. -// - -import Combine -import Foundation - -import MatrixRustSDK - -final class QRCodeLoginService: QRCodeLoginServiceProtocol { - private var sessionDirectories: SessionDirectories - private let passphrase: String - - private let userSessionStore: UserSessionStoreProtocol - private let appSettings: AppSettings - private let appHooks: AppHooks - - private let qrLoginProgressSubject = PassthroughSubject() - var qrLoginProgressPublisher: AnyPublisher { - qrLoginProgressSubject.eraseToAnyPublisher() - } - - init(encryptionKeyProvider: EncryptionKeyProviderProtocol, - userSessionStore: UserSessionStoreProtocol, - appSettings: AppSettings, - appHooks: AppHooks) { - sessionDirectories = .init() - passphrase = encryptionKeyProvider.generateKey().base64EncodedString() - self.userSessionStore = userSessionStore - self.appSettings = appSettings - self.appHooks = appHooks - } - - func loginWithQRCode(data: Data) async -> Result { - let qrData: QrCodeData - do { - qrData = try QrCodeData.fromBytes(bytes: data) - } catch { - MXLog.error("QRCode decode error: \(error)") - return .failure(.invalidQRCode) - } - - guard let scannedServerName = qrData.serverName() else { - MXLog.error("The QR code is from a device that is not yet signed in.") - return .failure(.deviceNotSignedIn) - } - - if !appSettings.allowOtherAccountProviders, !appSettings.accountProviders.contains(scannedServerName) { - MXLog.error("The scanned device's server is not allowed: \(scannedServerName)") - return .failure(.providerNotAllowed(scannedProvider: scannedServerName, allowedProviders: appSettings.accountProviders)) - } - - let listener = SDKListener { [weak self] progress in - self?.qrLoginProgressSubject.send(progress) - } - - do { - let client = try await makeClientBuilder().build(homeserverAddress: scannedServerName) - try await client.loginWithQrCode(qrCodeData: qrData, - oidcConfiguration: appSettings.oidcConfiguration.rustValue, - progressListener: listener) - MXLog.info("Sliding sync: \(client.slidingSyncVersion())") - return await userSession(for: client) - } catch let error as HumanQrLoginError { - MXLog.error("QRCode login error: \(error)") - return .failure(error.serviceError) - } catch { - MXLog.error("QRCode login unknown error: \(error)") - return .failure(.unknown) - } - } - - // MARK: - Private - - private func makeClientBuilder() -> AuthenticationClientBuilder { - // Use a fresh session directory each time the user scans a QR code to ensure caches - // (e.g. server versions) are always fresh in case a different server is used. - rotateSessionDirectory() - - return AuthenticationClientBuilder(sessionDirectories: sessionDirectories, - passphrase: passphrase, - clientSessionDelegate: userSessionStore.clientSessionDelegate, - appSettings: appSettings, - appHooks: appHooks) - } - - private func rotateSessionDirectory() { - sessionDirectories.delete() - sessionDirectories = .init() - } - - private func userSession(for client: ClientProtocol) async -> Result { - switch await userSessionStore.userSession(for: client, sessionDirectories: sessionDirectories, passphrase: passphrase) { - case .success(let session): - return .success(session) - case .failure(let error): - MXLog.error("QRCode login failed error: \(error)") - return .failure(.failedLoggingIn) - } - } -} - -private extension HumanQrLoginError { - var serviceError: QRCodeLoginServiceError { - switch self { - case .Cancelled: - return .cancelled - case .ConnectionInsecure: - return .connectionInsecure - case .Declined: - return .declined - case .LinkingNotSupported: - return .linkingNotSupported - case .Expired: - return .expired - case .SlidingSyncNotAvailable: - return .deviceNotSupported - case .OtherDeviceNotSignedIn: - return .deviceNotSignedIn - case .Unknown, .OidcMetadataInvalid: - return .unknown - } - } -} diff --git a/ElementX/Sources/Services/QRCode/QRCodeLoginServiceProtocol.swift b/ElementX/Sources/Services/QRCode/QRCodeLoginServiceProtocol.swift deleted file mode 100644 index 957de28fe..000000000 --- a/ElementX/Sources/Services/QRCode/QRCodeLoginServiceProtocol.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright 2024 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -// Please see LICENSE files in the repository root for full details. -// - -import Combine -import Foundation - -import MatrixRustSDK - -enum QRCodeLoginServiceError: Error { - case failedLoggingIn - case invalidQRCode - case providerNotAllowed(scannedProvider: String, allowedProviders: [String]) - case cancelled - case connectionInsecure - case declined - case linkingNotSupported - case expired - case deviceNotSupported - case deviceNotSignedIn - case unknown -} - -// sourcery: AutoMockable -protocol QRCodeLoginServiceProtocol { - var qrLoginProgressPublisher: AnyPublisher { get } - - func loginWithQRCode(data: Data) async -> Result -} diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 4d93004d2..fd62cad48 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -146,7 +146,6 @@ class MockScreen: Identifiable { } let flowCoordinator = AuthenticationFlowCoordinator(authenticationService: AuthenticationService.mock, - qrCodeLoginService: QRCodeLoginServiceMock(), bugReportService: BugReportServiceMock(.init()), navigationRootCoordinator: navigationRootCoordinator, appMediator: AppMediatorMock.default, diff --git a/UnitTests/Sources/AuthenticationServiceTests.swift b/UnitTests/Sources/AuthenticationServiceTests.swift index 8644c5e3e..a1413d4d3 100644 --- a/UnitTests/Sources/AuthenticationServiceTests.swift +++ b/UnitTests/Sources/AuthenticationServiceTests.swift @@ -86,8 +86,8 @@ class AuthenticationServiceTests: XCTestCase { // MARK: - Helpers private func setupMocks(serverAddress: String = "matrix.org") { - let configuration: AuthenticationClientBuilderMock.Configuration = .init() - let clientBuilderFactory = AuthenticationClientBuilderFactoryMock(configuration: .init(builderConfiguration: configuration)) + let configuration: AuthenticationClientFactoryMock.Configuration = .init() + let clientFactory = AuthenticationClientFactoryMock(configuration: configuration) client = configuration.homeserverClients[serverAddress] userSessionStore = UserSessionStoreMock(configuration: .init()) @@ -95,7 +95,7 @@ class AuthenticationServiceTests: XCTestCase { service = AuthenticationService(userSessionStore: userSessionStore, encryptionKeyProvider: encryptionKeyProvider, - clientBuilderFactory: clientBuilderFactory, + clientFactory: clientFactory, appSettings: ServiceLocator.shared.settings, appHooks: AppHooks()) } diff --git a/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift b/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift index 4604453d5..62d4509b7 100644 --- a/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift +++ b/UnitTests/Sources/AuthenticationStartScreenViewModelTests.swift @@ -11,7 +11,7 @@ import XCTest @MainActor class AuthenticationStartScreenViewModelTests: XCTestCase { - var clientBuilderFactory: AuthenticationClientBuilderFactoryMock! + var clientFactory: AuthenticationClientFactoryMock! var client: ClientSDKMock! var appSettings: AppSettings! var authenticationService: AuthenticationServiceProtocol! @@ -50,7 +50,7 @@ class AuthenticationStartScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then the authentication service should not be used yet. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) XCTAssertEqual(authenticationService.homeserver.value.loginMode, .unknown) } @@ -68,7 +68,7 @@ class AuthenticationStartScreenViewModelTests: XCTestCase { context.send(viewAction: .login) try await deferred.fulfill() - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdReceivedArguments?.prompt, .consent) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdReceivedArguments?.loginHint, "user@company.com") @@ -88,7 +88,7 @@ class AuthenticationStartScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then a call to configure service should be made. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(authenticationService.homeserver.value.loginMode, .password) } @@ -105,7 +105,7 @@ class AuthenticationStartScreenViewModelTests: XCTestCase { context.send(viewAction: .login) try await deferred.fulfill() - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdReceivedArguments?.prompt, .consent) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdReceivedArguments?.loginHint, nil) @@ -126,7 +126,7 @@ class AuthenticationStartScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then a call to configure service should be made. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(authenticationService.homeserver.value.loginMode, .password) } @@ -137,12 +137,12 @@ class AuthenticationStartScreenViewModelTests: XCTestCase { client = ClientSDKMock(configuration: .init(oidcLoginURL: supportsOIDC ? "https://account.company.com/authorize" : nil, supportsOIDCCreatePrompt: false, supportsPasswordLogin: true)) - let configuration = AuthenticationClientBuilderMock.Configuration(homeserverClients: ["company.com": client]) + let configuration = AuthenticationClientFactoryMock.Configuration(homeserverClients: ["company.com": client]) - clientBuilderFactory = AuthenticationClientBuilderFactoryMock(configuration: .init(builderConfiguration: configuration)) + clientFactory = AuthenticationClientFactoryMock(configuration: configuration) authenticationService = AuthenticationService(userSessionStore: UserSessionStoreMock(configuration: .init()), encryptionKeyProvider: EncryptionKeyProvider(), - clientBuilderFactory: clientBuilderFactory, + clientFactory: clientFactory, appSettings: appSettings, appHooks: AppHooks()) diff --git a/UnitTests/Sources/LoginScreenViewModelTests.swift b/UnitTests/Sources/LoginScreenViewModelTests.swift index e78259859..c95b4f7d8 100644 --- a/UnitTests/Sources/LoginScreenViewModelTests.swift +++ b/UnitTests/Sources/LoginScreenViewModelTests.swift @@ -14,7 +14,7 @@ class LoginScreenViewModelTests: XCTestCase { var viewModel: LoginScreenViewModelProtocol! var context: LoginScreenViewModelType.Context { viewModel.context } - var clientBuilderFactory: AuthenticationClientBuilderFactoryMock! + var clientFactory: AuthenticationClientFactoryMock! var service: AuthenticationServiceProtocol! func testBasicServer() async { @@ -157,10 +157,10 @@ class LoginScreenViewModelTests: XCTestCase { // MARK: - Helpers private func setupViewModel(homeserverAddress: String = "example.com", loginHint: String? = nil) async { - clientBuilderFactory = AuthenticationClientBuilderFactoryMock(configuration: .init()) + clientFactory = AuthenticationClientFactoryMock(configuration: .init()) service = AuthenticationService(userSessionStore: UserSessionStoreMock(configuration: .init()), encryptionKeyProvider: EncryptionKeyProvider(), - clientBuilderFactory: clientBuilderFactory, + clientFactory: clientFactory, appSettings: ServiceLocator.shared.settings, appHooks: AppHooks()) diff --git a/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift b/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift index bdf9ce636..461871d75 100644 --- a/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift +++ b/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift @@ -11,7 +11,7 @@ import XCTest @MainActor class ServerConfirmationScreenViewModelTests: XCTestCase { - var clientBuilderFactory: AuthenticationClientBuilderFactoryMock! + var clientFactory: AuthenticationClientFactoryMock! var client: ClientSDKMock! var service: AuthenticationServiceProtocol! var appSettings: AppSettings! @@ -37,7 +37,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { setupViewModel(authenticationFlow: .login) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) XCTAssertEqual(context.viewState.mode, .confirmation(service.homeserver.value.address)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -46,7 +46,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then a call to configure service should be made. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdReceivedArguments?.prompt, .consent) XCTAssertEqual(service.homeserver.value.loginMode, .oidc(supportsCreatePrompt: true)) @@ -61,7 +61,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { } XCTAssertEqual(service.homeserver.value.loginMode, .oidc(supportsCreatePrompt: true)) XCTAssertEqual(context.viewState.mode, .confirmation(service.homeserver.value.address)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -70,7 +70,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then the configured homeserver should be used and no additional client should be built. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdReceivedArguments?.prompt, .consent) } @@ -80,7 +80,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { setupViewModel(authenticationFlow: .register) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) XCTAssertEqual(context.viewState.mode, .confirmation(service.homeserver.value.address)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -89,7 +89,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then a call to configure service should be made. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 1) // The create prompt is broken: https://github.com/element-hq/matrix-authentication-service/issues/3429 // XCTAssertEqual(client.urlForOidcOidcConfigurationPromptReceivedArguments?.prompt, .create) @@ -105,7 +105,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { } XCTAssertEqual(service.homeserver.value.loginMode, .oidc(supportsCreatePrompt: true)) XCTAssertEqual(context.viewState.mode, .confirmation(service.homeserver.value.address)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -114,7 +114,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then the configured homeserver should be used and no additional client should be built. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) // The create prompt is broken: https://github.com/element-hq/matrix-authentication-service/issues/3429 // XCTAssertEqual(client.urlForOidcOidcConfigurationPromptReceivedArguments?.prompt, .create) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 1) @@ -125,7 +125,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { setupViewModel(authenticationFlow: .login, supportsOIDC: false) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) XCTAssertEqual(context.viewState.mode, .confirmation(service.homeserver.value.address)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -134,7 +134,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then a call to configure service should be made, but not for the OIDC URL. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) XCTAssertEqual(service.homeserver.value.loginMode, .password) } @@ -148,7 +148,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { } XCTAssertEqual(service.homeserver.value.loginMode, .password) XCTAssertEqual(context.viewState.mode, .confirmation(service.homeserver.value.address)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -157,7 +157,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then the configured homeserver should be used and no additional client should be built, nor a call to get the OIDC URL. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) } @@ -166,7 +166,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { // Note: We don't currently take the create prompt into account when determining registration support. setupViewModel(authenticationFlow: .register, supportsOIDC: false, supportsOIDCCreatePrompt: false) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertNil(context.alertInfo) // When continuing from the confirmation screen. @@ -175,7 +175,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then the configuration should fail with an alert about not supporting registration. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(context.alertInfo?.id, .registration) } @@ -183,7 +183,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { // Given a view model for login using a service that hasn't been configured and the default server doesn't support login. setupViewModel(authenticationFlow: .login, supportsOIDC: false, supportsOIDCCreatePrompt: false, supportsPasswordLogin: false) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertNil(context.alertInfo) // When continuing from the confirmation screen. @@ -192,7 +192,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then the configuration should fail with an alert about not supporting login. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(context.alertInfo?.id, .login) } @@ -203,7 +203,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { setupViewModel(authenticationFlow: .login, restrictedFlow: true) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) XCTAssertEqual(context.viewState.mode, .picker(appSettings.accountProviders)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -212,7 +212,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then a call to configure service should be made. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdReceivedArguments?.prompt, .consent) XCTAssertEqual(service.homeserver.value.loginMode, .oidc(supportsCreatePrompt: true)) @@ -227,7 +227,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { } XCTAssertEqual(service.homeserver.value.loginMode, .oidc(supportsCreatePrompt: true)) XCTAssertEqual(context.viewState.mode, .picker(appSettings.accountProviders)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -236,7 +236,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then the configured homeserver should be used and no additional client should be built. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdReceivedArguments?.prompt, .consent) } @@ -246,7 +246,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { setupViewModel(authenticationFlow: .login, supportsOIDC: false, restrictedFlow: true) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) XCTAssertEqual(context.viewState.mode, .picker(appSettings.accountProviders)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -255,7 +255,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then a call to configure service should be made, but not for the OIDC URL. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) XCTAssertEqual(service.homeserver.value.loginMode, .password) } @@ -269,7 +269,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { } XCTAssertEqual(service.homeserver.value.loginMode, .password) XCTAssertEqual(context.viewState.mode, .picker(appSettings.accountProviders)) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) // When continuing from the confirmation screen. @@ -278,7 +278,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then the configured homeserver should be used and no additional client should be built, nor a call to get the OIDC URL. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(client.urlForOidcOidcConfigurationPromptLoginHintDeviceIdCallsCount, 0) } @@ -316,12 +316,12 @@ class ServerConfirmationScreenViewModelTests: XCTestCase { client = ClientSDKMock(configuration: .init(oidcLoginURL: supportsOIDC ? "https://account.matrix.org/authorize" : nil, supportsOIDCCreatePrompt: supportsOIDCCreatePrompt, supportsPasswordLogin: supportsPasswordLogin)) - let configuration = AuthenticationClientBuilderMock.Configuration(homeserverClients: ["matrix.org": client]) + let configuration = AuthenticationClientFactoryMock.Configuration(homeserverClients: ["matrix.org": client]) - clientBuilderFactory = AuthenticationClientBuilderFactoryMock(configuration: .init(builderConfiguration: configuration)) + clientFactory = AuthenticationClientFactoryMock(configuration: configuration) service = AuthenticationService(userSessionStore: UserSessionStoreMock(configuration: .init()), encryptionKeyProvider: EncryptionKeyProvider(), - clientBuilderFactory: clientBuilderFactory, + clientFactory: clientFactory, appSettings: appSettings, appHooks: AppHooks()) diff --git a/UnitTests/Sources/ServerSelectionScreenViewModelTests.swift b/UnitTests/Sources/ServerSelectionScreenViewModelTests.swift index 9fb108124..bf55264f6 100644 --- a/UnitTests/Sources/ServerSelectionScreenViewModelTests.swift +++ b/UnitTests/Sources/ServerSelectionScreenViewModelTests.swift @@ -11,7 +11,7 @@ import XCTest @MainActor class ServerSelectionScreenViewModelTests: XCTestCase { - var clientBuilderFactory: AuthenticationClientBuilderFactoryMock! + var clientFactory: AuthenticationClientFactoryMock! var service: AuthenticationServiceProtocol! var viewModel: ServerSelectionScreenViewModelProtocol! @@ -21,7 +21,7 @@ class ServerSelectionScreenViewModelTests: XCTestCase { // Given a view model for login. setupViewModel(authenticationFlow: .login) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) // When selecting matrix.org. context.homeserverAddress = "matrix.org" @@ -30,7 +30,7 @@ class ServerSelectionScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then selection should succeed. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(service.homeserver.value, .mockMatrixDotOrg) } @@ -38,7 +38,7 @@ class ServerSelectionScreenViewModelTests: XCTestCase { // Given a view model for login. setupViewModel(authenticationFlow: .login) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertNil(context.alertInfo) // When selecting a server that doesn't support login. @@ -48,7 +48,7 @@ class ServerSelectionScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then selection should fail with an alert about not supporting registration. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(context.alertInfo?.id, .loginAlert) } @@ -56,7 +56,7 @@ class ServerSelectionScreenViewModelTests: XCTestCase { // Given a view model for registration. setupViewModel(authenticationFlow: .register) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) // When selecting matrix.org. context.homeserverAddress = "matrix.org" @@ -65,7 +65,7 @@ class ServerSelectionScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then selection should succeed. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(service.homeserver.value, .mockMatrixDotOrg) } @@ -73,7 +73,7 @@ class ServerSelectionScreenViewModelTests: XCTestCase { // Given a view model for registration. setupViewModel(authenticationFlow: .register) XCTAssertEqual(service.homeserver.value.loginMode, .unknown) - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 0) XCTAssertNil(context.alertInfo) // When selecting a server that doesn't support registration. @@ -83,7 +83,7 @@ class ServerSelectionScreenViewModelTests: XCTestCase { try await deferred.fulfill() // Then selection should fail with an alert about not supporting registration. - XCTAssertEqual(clientBuilderFactory.makeBuilderSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) + XCTAssertEqual(clientFactory.makeClientHomeserverAddressSessionDirectoriesPassphraseClientSessionDelegateAppSettingsAppHooksCallsCount, 1) XCTAssertEqual(context.alertInfo?.id, .registrationAlert) } @@ -122,10 +122,10 @@ class ServerSelectionScreenViewModelTests: XCTestCase { // MARK: - Helpers private func setupViewModel(authenticationFlow: AuthenticationFlow) { - clientBuilderFactory = AuthenticationClientBuilderFactoryMock(configuration: .init()) + clientFactory = AuthenticationClientFactoryMock(configuration: .init()) service = AuthenticationService(userSessionStore: UserSessionStoreMock(configuration: .init()), encryptionKeyProvider: EncryptionKeyProvider(), - clientBuilderFactory: clientBuilderFactory, + clientFactory: clientFactory, appSettings: ServiceLocator.shared.settings, appHooks: AppHooks())