diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index e79a6d6a9..37ab005de 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -118,6 +118,7 @@ 2CA6ABBC9A88EB89EA52FCCB /* ConfettiScene.scn in Resources */ = {isa = PBXBuildFile; fileRef = B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */; }; 2CB6787E25B11711518E9588 /* OnboardingCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6281B199D8A8F0892490C2E /* OnboardingCoordinator.swift */; }; 2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */; }; + 2E8C6672D0EE7D5B1BEDB8E2 /* ServerConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */; }; 2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086B997409328F091EBA43CE /* RoomScreenUITests.swift */; }; 2F94054F50E312AF30BE07F3 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B21E611DADDEF00307E7AC /* String.swift */; }; 308BD9343B95657FAA583FB7 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD5B074D7DD44AF4C58BB6 /* SwiftState */; }; @@ -152,6 +153,7 @@ 3F1893D73EEBF6ED4FCF6747 /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85890C78055B786CCABC9194 /* AnalyticsSettingsScreenModels.swift */; }; 3F2148F11164C7C5609984EB /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 2B788C81F6369D164ADEB917 /* GZIP */; }; 3F70E237CE4C3FAB02FC227F /* NotificationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C830A64609CBD152F06E0457 /* NotificationConstants.swift */; }; + 401BB28CD6B7DD6B4E7863E7 /* ServerConfirmationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9342F5D6729627B6393AF853 /* ServerConfirmationScreenModels.swift */; }; 407DCE030E0F9B7C9861D38A /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; }; 40B79D20A873620F7F128A2C /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA991289149D31F4286747 /* UserPreference.swift */; }; 414F50CFCFEEE2611127DCFB /* RestorationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3558A15CFB934F9229301527 /* RestorationToken.swift */; }; @@ -194,6 +196,7 @@ 518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; }; 520EEDAFBC778AB0B41F2F53 /* ClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */; }; 5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; }; + 53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */; }; 53DEF39F0C4DE02E3FC56D91 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 800631D7250B7F93195035F1 /* KeychainAccess */; }; 53F1196F9C69512306A2693F /* TextRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C19F54A0C4FC9AB7ABD583 /* TextRoomTimelineItemContent.swift */; }; 5455147CAC63F71E48F7D699 /* NSELogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3D455BC2423D911A62ACFB2 /* NSELogger.swift */; }; @@ -204,6 +207,7 @@ 56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; }; 5770C4906668C6D3008A2AC9 /* SessionVerificationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B5046BB295AEAFA6FB81655 /* SessionVerificationScreenModels.swift */; }; 588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; }; + 5894C2514400A4FBC9327632 /* ServerConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */; }; 5897A59DDBD3592282092223 /* MediaSourceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */; }; 595965CAD43B4E6CD615C17D /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D116D4633E177BE1AC0E71 /* AnalyticsSettingsScreenViewModel.swift */; }; 59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2245243369B99216C7D84E /* ImageCache.swift */; }; @@ -330,6 +334,7 @@ 890F0D453FE388756479AC97 /* AnalyticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C687844F60BFF532D49A994C /* AnalyticsTests.swift */; }; 8922219C5C934C4155E8CA50 /* SharedUserDefaultsKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA8DC95C079805B0B56E8A9 /* SharedUserDefaultsKeys.swift */; }; 8944548A684F1C837CEC47F4 /* RoomMembersListScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D0946F77B696176E062D037 /* RoomMembersListScreenModels.swift */; }; + 89658A44C9FC19B58FD1C226 /* ServerConfirmationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */; }; 899793EFC63DF93C3E0141E7 /* RoomMemberDetailsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FA60F848D1C14F873F9621A /* RoomMemberDetailsScreenCoordinator.swift */; }; 8A0BD60CA4A6004DB06B5403 /* MediaUploadingPreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */; }; 8AB8ED1051216546CB35FA0E /* UserSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E5E9C044BEB7C70B1378E91 /* UserSession.swift */; }; @@ -400,6 +405,7 @@ A14A9419105A1CD42F0511C4 /* UserIndicatorModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */; }; A17FAD2EBC53E17B5FD384DB /* InviteUsersScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */; }; A182920710146E5BEAA1A705 /* AnalyticsSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DBA101D643B31E813F3AC1 /* AnalyticsSettingsScreen.swift */; }; + A1D4033881320C9EB88196E6 /* ServerConfirmationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE846DDA83BFD7EC5C03760B /* ServerConfirmationScreenUITests.swift */; }; A216C83ADCF32BA5EF8A6FBC /* InviteUsersViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */; }; A23B8B27A1436A1049EEF68E /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; A2434D4DFB49A68E5CD0F53C /* MediaLoaderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */; }; @@ -478,7 +484,6 @@ BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */; }; BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */; }; BCC864190651B3A3CF51E4DF /* MediaFileHandleProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */; }; - BCEC41FB1F2BB663183863E4 /* LoginServerInfoSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D379E13DD9D987470A3C70C /* LoginServerInfoSection.swift */; }; BD203FC6A7AE7637EA003643 /* RoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ABDE6F66532CBEB0E016F94 /* RoomProxyMock.swift */; }; BD6D98676111DA8FC2BE4908 /* InvitesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86873A768B13069BB5CAECF6 /* InvitesScreenViewModelProtocol.swift */; }; BD782053BE4C3D2F0BDE5699 /* ServiceLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57F95CADD0A5DBD76B990FCB /* ServiceLocator.swift */; }; @@ -605,6 +610,7 @@ EF7924005216B8189898F370 /* BackgroundTaskProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CA028DCD4157F9A1F999827 /* BackgroundTaskProtocol.swift */; }; F06CE9132855E81EBB6DDC32 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 940C605265DD82DA0C655E23 /* Kingfisher */; }; F07D88421A9BC4D03D4A5055 /* VideoRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */; }; + F0A26CD502C3A5868353B0FA /* ServerConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */; }; F0F82C3C848C865C3098AA52 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 21C83087604B154AA30E9A8F /* SnapshotTesting */; }; F118DD449066E594F63C697D /* RoomMemberProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */; }; F16109A6F6DF03DA26D59233 /* RoomDetailsEditScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 122186B7CD1BC46A9C629DD9 /* RoomDetailsEditScreenUITests.swift */; }; @@ -640,6 +646,7 @@ FBF09B6C900415800DDF2A21 /* EmojiProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */; }; FC10228E73323BDC09526F97 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; }; FCD3F2B82CAB29A07887A127 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 2B43F2AF7456567FE37270A7 /* KeychainAccess */; }; + FD762761C5D0C30E6255C3D8 /* ServerConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */; }; FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; }; FF149F0A3550A54C50ECBE7A /* AppRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C843CF833BF6485B64AC87E1 /* AppRouter.swift */; }; FFD3E4FF948E06C7585317FC /* TimelineStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892E29C98C4E8182C9037F84 /* TimelineStyler.swift */; }; @@ -699,6 +706,7 @@ 024F7398C5FC12586FB10E9D /* EffectsScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EffectsScene.swift; sourceTree = ""; }; 0287793F11C480E242B03DF5 /* UserDiscoveryServiceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryServiceTest.swift; sourceTree = ""; }; 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenViewModel.swift; sourceTree = ""; }; + 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenCoordinator.swift; sourceTree = ""; }; 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; @@ -783,9 +791,11 @@ 227AC5D71A4CE43512062243 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = ""; }; 24227FF9A2797F6EA7F69CDD /* HomeScreenInvitesButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenInvitesButton.swift; sourceTree = ""; }; 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxyMock.swift; sourceTree = ""; }; + 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModel.swift; sourceTree = ""; }; 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = ""; }; 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; + 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfigurationScreenViewStateTests.swift; sourceTree = ""; }; 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtension.swift; sourceTree = ""; }; 287FC98AF2664EAD79C0D902 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = ""; }; 28C19F54A0C4FC9AB7ABD583 /* TextRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -969,7 +979,6 @@ 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowCoordinatorProtocol.swift; sourceTree = ""; }; 7D0CBC76C80E04345E11F2DB /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactoryProtocol.swift; sourceTree = ""; }; - 7D379E13DD9D987470A3C70C /* LoginServerInfoSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginServerInfoSection.swift; sourceTree = ""; }; 7DDBF99755A9008CF8C8499E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 7DDF49CEBC0DFC59C308335F /* RoomMemberDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModelProtocol.swift; sourceTree = ""; }; 7E0ADE4FAA5A4DB91CB07737 /* SettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreen.swift; sourceTree = ""; }; @@ -1016,6 +1025,7 @@ 92B45A6B13D32A131FCA4EFF /* FilePreviewScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewScreenViewModelProtocol.swift; sourceTree = ""; }; 92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTask.swift; sourceTree = ""; }; 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = ""; }; + 9342F5D6729627B6393AF853 /* ServerConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenModels.swift; sourceTree = ""; }; 9349F590E35CE514A71E6764 /* LoginHomeserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginHomeserver.swift; sourceTree = ""; }; 935C2FB18EFB8EEE96B26330 /* CreateRoomFlowParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomFlowParameters.swift; sourceTree = ""; }; 93B3513E60591237A49EE102 /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = ""; }; @@ -1075,6 +1085,7 @@ AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserProfile+Mock.swift"; sourceTree = ""; }; AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTaskServiceProtocol.swift; sourceTree = ""; }; AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingScreen.swift; sourceTree = ""; }; + ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelProtocol.swift; sourceTree = ""; }; AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageCache.swift; sourceTree = ""; }; AC3F82523D6F48B926D6AF68 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = ""; }; ACB6C5E4950B6C9842F35A38 /* RoomTimelineViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewProvider.swift; sourceTree = ""; }; @@ -1194,6 +1205,7 @@ DBA8DC95C079805B0B56E8A9 /* SharedUserDefaultsKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedUserDefaultsKeys.swift; sourceTree = ""; }; DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXTests.swift; sourceTree = ""; }; DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNNotification+Creator.swift"; sourceTree = ""; }; + DE846DDA83BFD7EC5C03760B /* ServerConfirmationScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenUITests.swift; sourceTree = ""; }; DEC1D382565A4E9CAC2F14EA /* MediaFileHandleProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaFileHandleProxy.swift; sourceTree = ""; }; DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationViewModelTests.swift; sourceTree = ""; }; DF38B69D2C331A499276F400 /* FilePreviewViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewViewModelTests.swift; sourceTree = ""; }; @@ -1240,6 +1252,7 @@ EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewFrameReader.swift; sourceTree = ""; }; EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportServiceTests.swift; sourceTree = ""; }; F012CB5EE3F2B67359F6CC52 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; + F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelTests.swift; sourceTree = ""; }; F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1964EE08550BEDBD0B0F5FD /* FilePreviewScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewScreenViewModel.swift; sourceTree = ""; }; @@ -1255,6 +1268,7 @@ F57C8022B8A871A1DCD1750A /* UserIndicatorToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorToastView.swift; sourceTree = ""; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = ""; }; F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedBodyText.swift; sourceTree = ""; }; + F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreen.swift; sourceTree = ""; }; F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilder.swift; sourceTree = ""; }; F7E8A8047B50E3607ACD354E /* ImageProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageProviderProtocol.swift; sourceTree = ""; }; F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = ""; }; @@ -1560,6 +1574,14 @@ path = RoomMember; sourceTree = ""; }; + 2CAAA563083EAC0FA6BDC4F3 /* View */ = { + isa = PBXGroup; + children = ( + F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */, + ); + path = View; + sourceTree = ""; + }; 2D0D49B0533C4C2EB889BF3A /* ServerSelectionScreen */ = { isa = PBXGroup; children = ( @@ -2056,7 +2078,6 @@ isa = PBXGroup; children = ( 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */, - 7D379E13DD9D987470A3C70C /* LoginServerInfoSection.swift */, ); path = View; sourceTree = ""; @@ -2231,6 +2252,8 @@ 69B63F817FE305548DB4B512 /* RoomMembersListViewModelTests.swift */, 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */, AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */, + 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */, + F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */, EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */, A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */, DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */, @@ -2546,6 +2569,7 @@ 0F19DBE940499D3E3DD405D8 /* RoomMemberDetailsScreenUITests.swift */, C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */, 086B997409328F091EBA43CE /* RoomScreenUITests.swift */, + DE846DDA83BFD7EC5C03760B /* ServerConfirmationScreenUITests.swift */, 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */, 6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */, 8EC57A32ABC80D774CC663DB /* SettingsScreenUITests.swift */, @@ -2793,6 +2817,18 @@ path = RoomMemberDetailsScreen; sourceTree = ""; }; + BA1938A75D8C780F694CEB62 /* ServerConfirmationScreen */ = { + isa = PBXGroup; + children = ( + 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */, + 9342F5D6729627B6393AF853 /* ServerConfirmationScreenModels.swift */, + 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */, + ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */, + 2CAAA563083EAC0FA6BDC4F3 /* View */, + ); + path = ServerConfirmationScreen; + sourceTree = ""; + }; C0937E3B06A8F0E2DB7C8241 /* Other */ = { isa = PBXGroup; children = ( @@ -3067,6 +3103,7 @@ 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */, 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */, 90F48FEF84016ED42A94BA24 /* LoginScreen */, + BA1938A75D8C780F694CEB62 /* ServerConfirmationScreen */, 2D0D49B0533C4C2EB889BF3A /* ServerSelectionScreen */, 5B2C520AB9863B8CBC8EB3CA /* SoftLogoutScreen */, ); @@ -3640,6 +3677,8 @@ CAF8755E152204F55F8D6B5B /* RoomMembersListViewModelTests.swift in Sources */, 46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */, CC0D088F505F33A20DC5590F /* RoomStateEventStringBuilderTests.swift in Sources */, + 53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */, + 89658A44C9FC19B58FD1C226 /* ServerConfirmationScreenViewModelTests.swift in Sources */, 93875ADD456142D20823ED24 /* ServerSelectionViewModelTests.swift in Sources */, 86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */, 755727E0B756430DFFEC4732 /* SessionVerificationViewModelTests.swift in Sources */, @@ -3845,7 +3884,6 @@ C5A07E2D88BE7D51DCECD166 /* LoginScreenModels.swift in Sources */, BDA68E8D95B2B24B28825B8B /* LoginScreenViewModel.swift in Sources */, A5B9EF45C7B8ACEB4954AE36 /* LoginScreenViewModelProtocol.swift in Sources */, - BCEC41FB1F2BB663183863E4 /* LoginServerInfoSection.swift in Sources */, B94368839BDB69172E28E245 /* MXLog.swift in Sources */, B66757D0254843162595B25D /* MXLogger.swift in Sources */, 67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */, @@ -3979,6 +4017,11 @@ 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */, 14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */, 49F2E7DD8CAACE09CEECE3E6 /* SeparatorRoomTimelineView.swift in Sources */, + 2E8C6672D0EE7D5B1BEDB8E2 /* ServerConfirmationScreen.swift in Sources */, + 5894C2514400A4FBC9327632 /* ServerConfirmationScreenCoordinator.swift in Sources */, + 401BB28CD6B7DD6B4E7863E7 /* ServerConfirmationScreenModels.swift in Sources */, + F0A26CD502C3A5868353B0FA /* ServerConfirmationScreenViewModel.swift in Sources */, + FD762761C5D0C30E6255C3D8 /* ServerConfirmationScreenViewModelProtocol.swift in Sources */, 43F35A7E5703D64DB0519C59 /* ServerSelectionScreen.swift in Sources */, E5F4C992845388B50BABACAA /* ServerSelectionScreenCoordinator.swift in Sources */, 6530865EB9A8C0F0AF0216DA /* ServerSelectionScreenModels.swift in Sources */, @@ -4123,6 +4166,7 @@ A8771F5975A82759FA5138AE /* RoomMemberDetailsScreenUITests.swift in Sources */, 44121202B4A260C98BF615A7 /* RoomMembersListScreenUITests.swift in Sources */, 2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */, + A1D4033881320C9EB88196E6 /* ServerConfirmationScreenUITests.swift in Sources */, 77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */, 05EC896A4B9AF4A56670C0BB /* SessionVerificationUITests.swift in Sources */, 9C5A07E7C33F3F40287D7861 /* SettingsScreenUITests.swift in Sources */, diff --git a/ElementX/Resources/Localizations/en.lproj/Untranslated.strings b/ElementX/Resources/Localizations/en.lproj/Untranslated.strings index 7cacc3f86..2b31da559 100644 --- a/ElementX/Resources/Localizations/en.lproj/Untranslated.strings +++ b/ElementX/Resources/Localizations/en.lproj/Untranslated.strings @@ -6,7 +6,6 @@ // MARK: - Soft logout -"soft_logout_forgot_password" = "Forgot password"; "soft_logout_signin_title" = "Sign in"; "soft_logout_signin_notice" = "Your homeserver (%1$s) admin has signed you out of your account %2$s (%3$s)."; "soft_logout_signin_e2e_warning_notice" = "Sign in to recover encryption keys stored exclusively on this device. You need them to read all of your secure messages on any device."; diff --git a/ElementX/Sources/Generated/Strings+Untranslated.swift b/ElementX/Sources/Generated/Strings+Untranslated.swift index 3fbefde12..2fb62c2fa 100644 --- a/ElementX/Sources/Generated/Strings+Untranslated.swift +++ b/ElementX/Sources/Generated/Strings+Untranslated.swift @@ -23,8 +23,6 @@ public enum UntranslatedL10n { public static var softLogoutClearDataSubmit: String { return UntranslatedL10n.tr("Untranslated", "soft_logout_clear_data_submit") } /// Clear personal data public static var softLogoutClearDataTitle: String { return UntranslatedL10n.tr("Untranslated", "soft_logout_clear_data_title") } - /// Forgot password - public static var softLogoutForgotPassword: String { return UntranslatedL10n.tr("Untranslated", "soft_logout_forgot_password") } /// Sign in to recover encryption keys stored exclusively on this device. You need them to read all of your secure messages on any device. public static var softLogoutSigninE2eWarningNotice: String { return UntranslatedL10n.tr("Untranslated", "soft_logout_signin_e2e_warning_notice") } /// Your homeserver (%1$s) admin has signed you out of your account %2$s (%3$s). diff --git a/ElementX/Sources/Other/AccessibilityIdentifiers.swift b/ElementX/Sources/Other/AccessibilityIdentifiers.swift index 509ac75b5..e4185f3bd 100644 --- a/ElementX/Sources/Other/AccessibilityIdentifiers.swift +++ b/ElementX/Sources/Other/AccessibilityIdentifiers.swift @@ -26,6 +26,7 @@ struct A11yIdentifiers { static let reportContent = ReportContent() static let roomScreen = RoomScreen() static let roomDetailsScreen = RoomDetailsScreen() + static let serverConfirmationScreen = ServerConfirmationScreen() static let sessionVerificationScreen = SessionVerificationScreen() static let softLogoutScreen = SoftLogoutScreen() static let startChatScreen = StartChatScreen() @@ -73,7 +74,6 @@ struct A11yIdentifiers { let emailUsername = "login-email_username" let password = "login-password" let `continue` = "login-continue" - let changeServer = "login-change_server" let oidc = "login-oidc" let unsupportedServer = "login-unsupported_server" } @@ -106,6 +106,11 @@ struct A11yIdentifiers { let unignore = "room_member_details-unignore" } + struct ServerConfirmationScreen { + let `continue` = "server_confirmation-continue" + let changeServer = "server_confirmation-change_server" + } + struct SessionVerificationScreen { let requestVerification = "session_verification-request_verification" let startSasVerification = "session_verification-start_sas_verification" @@ -115,7 +120,7 @@ struct A11yIdentifiers { let verificationComplete = "session_verification-verification_complete" let close = "session_verification-close" } - + struct SoftLogoutScreen { let title = "soft_logout-title" let message = "soft_logout-message" diff --git a/ElementX/Sources/Screens/Authentication/AuthenticationCoordinator.swift b/ElementX/Sources/Screens/Authentication/AuthenticationCoordinator.swift index 42d6ebaa1..b5f295b36 100644 --- a/ElementX/Sources/Screens/Authentication/AuthenticationCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/AuthenticationCoordinator.swift @@ -14,6 +14,7 @@ // limitations under the License. // +import Combine import SwiftUI @MainActor @@ -26,6 +27,8 @@ class AuthenticationCoordinator: CoordinatorProtocol { private let authenticationService: AuthenticationServiceProxyProtocol private let navigationStackCoordinator: NavigationStackCoordinator + private var cancellables: Set = [] + weak var delegate: AuthenticationCoordinatorDelegate? init(authenticationService: AuthenticationServiceProxyProtocol, @@ -64,17 +67,20 @@ class AuthenticationCoordinator: CoordinatorProtocol { switch await authenticationService.configure(for: ServiceLocator.shared.settings.defaultHomeserverAddress) { case .success: stopLoading() - showLoginScreen() + showServerConfirmationScreen() case .failure: stopLoading() - showServerSelectionScreen() + showServerSelectionScreen(isModallyPresented: false) } } - private func showServerSelectionScreen() { + private func showServerSelectionScreen(isModallyPresented: Bool) { + let navigationCoordinator = NavigationStackCoordinator() + let userIndicatorController: UserIndicatorControllerProtocol! = isModallyPresented ? UserIndicatorController(rootCoordinator: navigationCoordinator) : ServiceLocator.shared.userIndicatorController + let parameters = ServerSelectionScreenCoordinatorParameters(authenticationService: authenticationService, - userIndicatorController: ServiceLocator.shared.userIndicatorController, - isModallyPresented: false) + userIndicatorController: userIndicatorController, + isModallyPresented: isModallyPresented) let coordinator = ServerSelectionScreenCoordinator(parameters: parameters) coordinator.callback = { [weak self] action in @@ -82,18 +88,46 @@ class AuthenticationCoordinator: CoordinatorProtocol { switch action { case .updated: - self.showLoginScreen() + if isModallyPresented { + navigationStackCoordinator.setSheetCoordinator(nil) + } else { + showLoginScreen() + } case .dismiss: - MXLog.failure("ServerSelectionScreen is requesting dismiss when part of a stack.") + navigationStackCoordinator.setSheetCoordinator(nil) } } + if isModallyPresented { + navigationCoordinator.setRootCoordinator(coordinator) + navigationStackCoordinator.setSheetCoordinator(userIndicatorController) + } else { + navigationStackCoordinator.push(coordinator) + } + } + + private func showServerConfirmationScreen() { + let parameters = ServerConfirmationScreenCoordinatorParameters(authenticationService: authenticationService, + authenticationFlow: .login) + let coordinator = ServerConfirmationScreenCoordinator(parameters: parameters) + + coordinator.actions.sink { [weak self] action in + guard let self else { return } + + switch action { + case .confirm: + self.showLoginScreen() + case .changeServer: + self.showServerSelectionScreen(isModallyPresented: true) + } + } + .store(in: &cancellables) + navigationStackCoordinator.push(coordinator) } private func showLoginScreen() { - let parameters = LoginScreenCoordinatorParameters(authenticationService: authenticationService, - navigationStackCoordinator: navigationStackCoordinator) + let parameters = LoginScreenCoordinatorParameters(authenticationService: authenticationService) let coordinator = LoginScreenCoordinator(parameters: parameters) coordinator.callback = { [weak self] action in diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift index 2e2ede22f..ca5facc90 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift @@ -20,8 +20,6 @@ import SwiftUI struct LoginScreenCoordinatorParameters { /// The service used to authenticate the user. let authenticationService: AuthenticationServiceProxyProtocol - /// The navigation router used to present the server selection screen. - let navigationStackCoordinator: NavigationStackCoordinator } enum LoginScreenCoordinatorAction { @@ -37,7 +35,6 @@ final class LoginScreenCoordinator: CoordinatorProtocol { private let oidcAuthenticationPresenter: OIDCAuthenticationPresenter private var authenticationService: AuthenticationServiceProxyProtocol { parameters.authenticationService } - private var navigationStackCoordinator: NavigationStackCoordinator { parameters.navigationStackCoordinator } var callback: (@MainActor (LoginScreenCoordinatorAction) -> Void)? @@ -46,7 +43,7 @@ final class LoginScreenCoordinator: CoordinatorProtocol { init(parameters: LoginScreenCoordinatorParameters) { self.parameters = parameters - viewModel = LoginScreenViewModel(homeserver: parameters.authenticationService.homeserver) + viewModel = LoginScreenViewModel(homeserver: parameters.authenticationService.homeserver.value) oidcAuthenticationPresenter = OIDCAuthenticationPresenter(authenticationService: parameters.authenticationService) } @@ -58,8 +55,6 @@ final class LoginScreenCoordinator: CoordinatorProtocol { guard let self else { return } switch action { - case .selectServer: - self.presentServerSelectionScreen() case .parseUsername(let username): self.parseUsername(username) case .forgotPassword: @@ -193,35 +188,10 @@ final class LoginScreenCoordinator: CoordinatorProtocol { /// Updates the view model with a different homeserver. private func updateViewModel() { - viewModel.update(homeserver: authenticationService.homeserver) + viewModel.update(homeserver: authenticationService.homeserver.value) indicateSuccess() } - /// Presents the server selection screen as a modal. - private func presentServerSelectionScreen() { - let parameters = ServerSelectionScreenCoordinatorParameters(authenticationService: authenticationService, - userIndicatorController: ServiceLocator.shared.userIndicatorController, - isModallyPresented: false) - - let coordinator = ServerSelectionScreenCoordinator(parameters: parameters) - coordinator.callback = { [weak self, weak coordinator] action in - guard let self, let coordinator else { return } - self.serverSelectionCoordinator(coordinator, didCompleteWith: action) - } - - navigationStackCoordinator.push(coordinator) - } - - /// Handles the result from the server selection modal, dismissing it after updating the view. - private func serverSelectionCoordinator(_ coordinator: ServerSelectionScreenCoordinator, - didCompleteWith action: ServerSelectionScreenCoordinatorAction) { - if action == .updated { - updateViewModel() - } - - navigationStackCoordinator.pop() - } - /// Shows the forgot password screen. private func showForgotPasswordScreen() { viewModel.displayError(.alert("Not implemented.")) diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift index 140974880..17c377a57 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenModels.swift @@ -17,8 +17,6 @@ import Foundation enum LoginScreenViewModelAction: CustomStringConvertible { - /// The user would like to select another server. - case selectServer /// Parse the username and update the homeserver if included. case parseUsername(String) /// The user would like to reset their password. @@ -31,8 +29,6 @@ enum LoginScreenViewModelAction: CustomStringConvertible { /// A string representation of the action, ignoring any associated values that could leak PII. var description: String { switch self { - case .selectServer: - return "selectServer" case .parseUsername: return "parseUsername" case .forgotPassword: @@ -77,8 +73,6 @@ struct LoginScreenBindings { } enum LoginScreenViewAction { - /// The user would like to select another server. - case selectServer /// Parse the username to detect if a homeserver is included. case parseUsername /// The user would like to reset their password. diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift index d327491e2..eaff243f9 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenViewModel.swift @@ -30,8 +30,6 @@ class LoginScreenViewModel: LoginScreenViewModelType, LoginScreenViewModelProtoc override func process(viewAction: LoginScreenViewAction) { switch viewAction { - case .selectServer: - callback?(.selectServer) case .parseUsername: callback?(.parseUsername(state.bindings.username)) case .forgotPassword: diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift index ae8926f91..11e6de4aa 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift @@ -31,9 +31,6 @@ struct LoginScreen: View { .padding(.top, UIConstants.titleTopPaddingToNavigationBar) .padding(.bottom, 32) - serverInfo - .padding(.bottom, 32) - switch context.viewState.loginMode { case .password: loginForm @@ -51,19 +48,18 @@ struct LoginScreen: View { .alert(item: $context.alertInfo) { $0.alert } } - /// The header containing a Welcome Back title. + /// The header containing the title and icon. var header: some View { - Text(L10n.screenLoginTitle) - .font(.compound.headingLGBold) - .multilineTextAlignment(.center) - .foregroundColor(.element.primaryContent) - } - - /// The sever information section that includes a button to select a different server. - var serverInfo: some View { - LoginServerInfoSection(address: context.viewState.homeserver.address) { - context.send(viewAction: .selectServer) + VStack(spacing: 8) { + AuthenticationIconImage(image: Image(systemName: "lock.fill")) + .padding(.bottom, 8) + + Text(L10n.screenLoginTitleWithHomeserver(context.viewState.homeserver.address)) + .font(.compound.headingMDBold) + .multilineTextAlignment(.center) + .foregroundColor(.element.primaryContent) } + .padding(.horizontal, 16) } /// The form with text fields for username and password, along with a submit button. diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginServerInfoSection.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginServerInfoSection.swift deleted file mode 100644 index 2fec37a27..000000000 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginServerInfoSection.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright 2022 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 SwiftUI - -/// A view that shows information about the chosen homeserver, -/// along with an edit button to pick a different one. -struct LoginServerInfoSection: View { - // MARK: - Public - - /// The address shown for the server. - let address: String - /// The action performed when tapping the edit button. - let editAction: () -> Void - - // MARK: - Views - - var body: some View { - VStack(alignment: .leading, spacing: 8) { - Text(L10n.screenLoginServerHeader) - .font(.compound.bodySM) - .foregroundColor(.element.primaryContent) - .padding(.horizontal, 16) - - Button(action: editAction) { - HStack { - Text(address) - .font(.compound.bodyMDSemibold) - .foregroundColor(.element.primaryContent) - .padding(.horizontal, 16) - .padding(.vertical) - - Spacer() - - Image(systemName: "chevron.right") - .font(.compound.bodyMD.bold()) - .foregroundColor(.element.tertiaryContent) - .padding(.trailing, 16) - } - .background(RoundedRectangle(cornerRadius: 14).fill(Color.element.system)) - } - .accessibilityIdentifier(A11yIdentifiers.loginScreen.changeServer) - } - } -} - -struct LoginServerInfoSection_Previews: PreviewProvider { - static var previews: some View { - LoginServerInfoSection(address: "matrix.org", editAction: { }) - .padding() - } -} diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift new file mode 100644 index 000000000..77bfc8dad --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenCoordinator.swift @@ -0,0 +1,64 @@ +// +// Copyright 2022 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 Combine +import SwiftUI + +struct ServerConfirmationScreenCoordinatorParameters { + let authenticationService: AuthenticationServiceProxyProtocol + let authenticationFlow: AuthenticationFlow +} + +enum ServerConfirmationScreenCoordinatorAction { + case confirm + case changeServer +} + +final class ServerConfirmationScreenCoordinator: CoordinatorProtocol { + private let parameters: ServerConfirmationScreenCoordinatorParameters + private var viewModel: ServerConfirmationScreenViewModelProtocol + private let actionsSubject: PassthroughSubject = .init() + private var cancellables: Set = .init() + + var actions: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(parameters: ServerConfirmationScreenCoordinatorParameters) { + self.parameters = parameters + + viewModel = ServerConfirmationScreenViewModel(authenticationService: parameters.authenticationService, + authenticationFlow: parameters.authenticationFlow) + } + + func start() { + viewModel.actions.sink { [weak self] action in + guard let self else { return } + + switch action { + case .confirm: + self.actionsSubject.send(.confirm) + case .changeServer: + self.actionsSubject.send(.changeServer) + } + } + .store(in: &cancellables) + } + + func toPresentable() -> AnyView { + AnyView(ServerConfirmationScreen(context: viewModel.context)) + } +} diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift new file mode 100644 index 000000000..d4cbfe94e --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenModels.swift @@ -0,0 +1,64 @@ +// +// Copyright 2022 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 Foundation + +enum ServerConfirmationScreenViewModelAction { + /// The user would like to continue with the current homeserver. + case confirm + /// The user would like to change to a different homeserver. + case changeServer +} + +struct ServerConfirmationScreenViewState: BindableState { + /// The homeserver address input by the user. + var homeserverAddress: String + /// The flow being attempted on the selected homeserver. + let authenticationFlow: AuthenticationFlow + + /// The screen's title. + var title: String { + switch authenticationFlow { + case .login: + return L10n.screenServerConfirmationTitleLogin(homeserverAddress) + case .register: + return L10n.screenServerConfirmationTitleRegister(homeserverAddress) + } + } + + /// The message shown beneath the title. + var message: String { + switch authenticationFlow { + case .login: + if homeserverAddress == "matrix.org" { + return L10n.screenServerConfirmationMessageLoginMatrixDotOrg + } else if homeserverAddress == "element.io" { + return L10n.screenServerConfirmationMessageLoginElementDotIo + } else { + return "" + } + case .register: + return L10n.screenServerConfirmationMessageRegister + } + } +} + +enum ServerConfirmationScreenViewAction { + /// The user would like to continue with the current homeserver. + case confirm + /// The user would like to change to a different homeserver. + case changeServer +} diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift new file mode 100644 index 000000000..bb71abdcd --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModel.swift @@ -0,0 +1,52 @@ +// +// Copyright 2022 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 Combine +import SwiftUI + +typealias ServerConfirmationScreenViewModelType = StateStoreViewModel + +class ServerConfirmationScreenViewModel: ServerConfirmationScreenViewModelType, ServerConfirmationScreenViewModelProtocol { + private var actionsSubject: PassthroughSubject = .init() + + var actions: AnyPublisher { + actionsSubject.eraseToAnyPublisher() + } + + init(authenticationService: AuthenticationServiceProxyProtocol, authenticationFlow: AuthenticationFlow) { + super.init(initialViewState: ServerConfirmationScreenViewState(homeserverAddress: authenticationService.homeserver.value.address, + authenticationFlow: authenticationFlow)) + + authenticationService.homeserver + .receive(on: DispatchQueue.main) + .sink { [weak self] homeserver in + guard let self else { return } + state.homeserverAddress = homeserver.address + } + .store(in: &cancellables) + } + + // MARK: - Public + + override func process(viewAction: ServerConfirmationScreenViewAction) { + switch viewAction { + case .confirm: + actionsSubject.send(.confirm) + case .changeServer: + actionsSubject.send(.changeServer) + } + } +} diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModelProtocol.swift new file mode 100644 index 000000000..24a7b658d --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/ServerConfirmationScreenViewModelProtocol.swift @@ -0,0 +1,23 @@ +// +// Copyright 2022 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 Combine + +@MainActor +protocol ServerConfirmationScreenViewModelProtocol { + var actions: AnyPublisher { get } + var context: ServerConfirmationScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/View/ServerConfirmationScreen.swift b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/View/ServerConfirmationScreen.swift new file mode 100644 index 000000000..a32c9e7c3 --- /dev/null +++ b/ElementX/Sources/Screens/Authentication/ServerConfirmationScreen/View/ServerConfirmationScreen.swift @@ -0,0 +1,99 @@ +// +// Copyright 2022 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 SwiftUI + +struct ServerConfirmationScreen: View { + @ObservedObject var context: ServerConfirmationScreenViewModel.Context + + var body: some View { + ScrollView { + header + .padding(.top, UIConstants.iconTopPaddingToNavigationBar) + .padding(.horizontal, 16) + .readableFrame() + } + .background(Color.element.background.ignoresSafeArea()) + .safeAreaInset(edge: .bottom) { + buttons + .padding(.horizontal, 16) + .padding(.vertical, 16) + .readableFrame() + .background(Color.element.background.ignoresSafeArea()) + } + } + + /// The main content of the view to be shown in a scroll view. + var header: some View { + VStack(spacing: 8) { + AuthenticationIconImage(image: Image(systemName: "person.crop.circle.fill")) + .padding(.bottom, 8) + + Text(context.viewState.title) + .font(.compound.headingMDBold) + .multilineTextAlignment(.center) + .foregroundColor(.element.primaryContent) + .fixedSize(horizontal: false, vertical: true) + + Text(context.viewState.message) + .font(.compound.bodyMD) + .multilineTextAlignment(.center) + .foregroundColor(.element.tertiaryContent) + } + .padding(.horizontal, 16) + } + + /// The action buttons shown at the bottom of the view. + var buttons: some View { + VStack(spacing: 24) { + Button { context.send(viewAction: .confirm) } label: { + Text(L10n.actionContinue) + } + .buttonStyle(.elementAction(.xLarge)) + .accessibilityIdentifier(A11yIdentifiers.serverConfirmationScreen.continue) + + Button { context.send(viewAction: .changeServer) } label: { + Text(L10n.screenServerConfirmationChangeServer) + .font(.compound.bodyLGSemibold) + .padding(.vertical, 14) + } + .accessibilityIdentifier(A11yIdentifiers.serverConfirmationScreen.changeServer) + } + } +} + +// MARK: - Previews + +struct ServerConfirmationScreen_Previews: PreviewProvider { + static let loginViewModel = ServerConfirmationScreenViewModel(authenticationService: MockAuthenticationServiceProxy(), + authenticationFlow: .login) + static let registerViewModel = ServerConfirmationScreenViewModel(authenticationService: MockAuthenticationServiceProxy(), + authenticationFlow: .register) + + static var previews: some View { + NavigationStack { + ServerConfirmationScreen(context: loginViewModel.context) + .toolbar(.visible, for: .navigationBar) + } + .previewDisplayName("Login") + + NavigationStack { + ServerConfirmationScreen(context: registerViewModel.context) + .toolbar(.visible, for: .navigationBar) + } + .previewDisplayName("Register") + } +} diff --git a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenCoordinator.swift index 801c58377..6365fabaf 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/ServerSelectionScreenCoordinator.swift @@ -39,7 +39,7 @@ final class ServerSelectionScreenCoordinator: CoordinatorProtocol { init(parameters: ServerSelectionScreenCoordinatorParameters) { self.parameters = parameters - viewModel = ServerSelectionScreenViewModel(homeserverAddress: parameters.authenticationService.homeserver.address, + viewModel = ServerSelectionScreenViewModel(homeserverAddress: parameters.authenticationService.homeserver.value.address, isModallyPresented: parameters.isModallyPresented) userIndicatorController = parameters.userIndicatorController } diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift index a86009106..c0ec5f444 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/SoftLogoutScreenCoordinator.swift @@ -53,7 +53,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol { let homeserver = parameters.authenticationService.homeserver viewModel = SoftLogoutScreenViewModel(credentials: parameters.credentials, - homeserver: homeserver, + homeserver: homeserver.value, keyBackupNeeded: parameters.keyBackupNeeded) oidcAuthenticationPresenter = OIDCAuthenticationPresenter(authenticationService: parameters.authenticationService) diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift index df6ef70cf..bb8bec4dd 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift @@ -87,7 +87,7 @@ struct SoftLogoutScreen: View { .accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.password) Button { context.send(viewAction: .forgotPassword) } label: { - Text(UntranslatedL10n.softLogoutForgotPassword) + Text(L10n.actionForgotPassword) .font(.compound.bodyLG) } .frame(maxWidth: .infinity, alignment: .trailing) diff --git a/ElementX/Sources/Services/Authentication/AuthenticationServiceProxy.swift b/ElementX/Sources/Services/Authentication/AuthenticationServiceProxy.swift index 2f02c3649..1e41ce7fd 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationServiceProxy.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationServiceProxy.swift @@ -14,6 +14,7 @@ // limitations under the License. // +import Combine import Foundation import MatrixRustSDK @@ -21,7 +22,9 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol { private let authenticationService: AuthenticationService private let userSessionStore: UserSessionStoreProtocol - private(set) var homeserver = LoginHomeserver(address: ServiceLocator.shared.settings.defaultHomeserverAddress, loginMode: .unknown) + private let homeserverSubject: CurrentValueSubject = .init(LoginHomeserver(address: ServiceLocator.shared.settings.defaultHomeserverAddress, + loginMode: .unknown)) + var homeserver: CurrentValuePublisher { homeserverSubject.asCurrentValuePublisher() } init(userSessionStore: UserSessionStoreProtocol) { self.userSessionStore = userSessionStore @@ -60,7 +63,7 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol { } } - self.homeserver = homeserver + homeserverSubject.send(homeserver) return .success(()) } catch AuthenticationError.SlidingSyncNotAvailable { MXLog.info("User entered a homeserver that isn't configured for sliding sync.") diff --git a/ElementX/Sources/Services/Authentication/AuthenticationServiceProxyProtocol.swift b/ElementX/Sources/Services/Authentication/AuthenticationServiceProxyProtocol.swift index 940863e6e..85a196c85 100644 --- a/ElementX/Sources/Services/Authentication/AuthenticationServiceProxyProtocol.swift +++ b/ElementX/Sources/Services/Authentication/AuthenticationServiceProxyProtocol.swift @@ -17,6 +17,14 @@ import Foundation import MatrixRustSDK +/// Represents a particular authentication flow. +enum AuthenticationFlow { + /// The flow for signing in to an existing account. + case login + /// The flow for creating a new account. + case register +} + enum AuthenticationServiceError: Error { /// An error occurred during OIDC authentication. case oidcError(OIDCError) @@ -29,7 +37,8 @@ enum AuthenticationServiceError: Error { } protocol AuthenticationServiceProxyProtocol { - var homeserver: LoginHomeserver { get } + /// The currently configured homeserver. + var homeserver: CurrentValuePublisher { get } /// Sets up the service for login on the specified homeserver address. func configure(for homeserverAddress: String) async -> Result diff --git a/ElementX/Sources/Services/Authentication/MockAuthenticationServiceProxy.swift b/ElementX/Sources/Services/Authentication/MockAuthenticationServiceProxy.swift index 3e07eea6f..ba36725ac 100644 --- a/ElementX/Sources/Services/Authentication/MockAuthenticationServiceProxy.swift +++ b/ElementX/Sources/Services/Authentication/MockAuthenticationServiceProxy.swift @@ -14,27 +14,33 @@ // limitations under the License. // +import Combine import Foundation import MatrixRustSDK class MockAuthenticationServiceProxy: AuthenticationServiceProxyProtocol { let validCredentials = (username: "alice", password: "12345678") - private(set) var homeserver: LoginHomeserver = .mockMatrixDotOrg + private let homeserverSubject: CurrentValueSubject + var homeserver: CurrentValuePublisher { homeserverSubject.asCurrentValuePublisher() } + + init(homeserver: LoginHomeserver = .mockMatrixDotOrg) { + homeserverSubject = .init(homeserver) + } func configure(for homeserverAddress: String) async -> Result { // Map the address to the mock homeservers if LoginHomeserver.mockMatrixDotOrg.address.contains(homeserverAddress) { - homeserver = .mockMatrixDotOrg + homeserverSubject.send(.mockMatrixDotOrg) return .success(()) } else if LoginHomeserver.mockOIDC.address.contains(homeserverAddress) { - homeserver = .mockOIDC + homeserverSubject.send(.mockOIDC) return .success(()) } else if LoginHomeserver.mockBasicServer.address.contains(homeserverAddress) { - homeserver = .mockBasicServer + homeserverSubject.send(.mockBasicServer) return .success(()) } else if LoginHomeserver.mockUnsupported.address.contains(homeserverAddress) { - homeserver = .mockUnsupported + homeserverSubject.send(.mockUnsupported) return .success(()) } else { // Otherwise fail with an invalid server. diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index cccb2df67..d67f65afd 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -75,8 +75,19 @@ class MockScreen: Identifiable { switch id { case .login: let navigationStackCoordinator = NavigationStackCoordinator() - let coordinator = LoginScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), - navigationStackCoordinator: navigationStackCoordinator)) + let coordinator = LoginScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy())) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator + case .serverConfirmationLogin: + let navigationStackCoordinator = NavigationStackCoordinator() + let coordinator = ServerConfirmationScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(homeserver: .mockMatrixDotOrg), + authenticationFlow: .login)) + navigationStackCoordinator.setRootCoordinator(coordinator) + return navigationStackCoordinator + case .serverConfirmationRegister: + let navigationStackCoordinator = NavigationStackCoordinator() + let coordinator = ServerConfirmationScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(homeserver: .mockOIDC), + authenticationFlow: .register)) navigationStackCoordinator.setRootCoordinator(coordinator) return navigationStackCoordinator case .serverSelection: diff --git a/ElementX/Sources/UITests/UITestsScreenIdentifier.swift b/ElementX/Sources/UITests/UITestsScreenIdentifier.swift index 3f298cef6..53bd0453e 100644 --- a/ElementX/Sources/UITests/UITestsScreenIdentifier.swift +++ b/ElementX/Sources/UITests/UITestsScreenIdentifier.swift @@ -18,6 +18,8 @@ import Foundation enum UITestsScreenIdentifier: String { case login + case serverConfirmationLogin + case serverConfirmationRegister case serverSelection case serverSelectionNonModal case authenticationFlow diff --git a/IntegrationTests/Sources/LoginTests.swift b/IntegrationTests/Sources/LoginTests.swift index fb0b02bd7..cf35d478a 100644 --- a/IntegrationTests/Sources/LoginTests.swift +++ b/IntegrationTests/Sources/LoginTests.swift @@ -42,10 +42,10 @@ class LoginTests: XCTestCase { XCTAssertTrue(getStartedButton.waitForExistence(timeout: 10.0)) getStartedButton.tap() - - let editHomeserverButton = app.buttons[A11yIdentifiers.loginScreen.changeServer] - XCTAssertTrue(editHomeserverButton.waitForExistence(timeout: 10.0)) - editHomeserverButton.tap() + + let changeHomeserverButton = app.buttons[A11yIdentifiers.serverConfirmationScreen.changeServer] + XCTAssertTrue(changeHomeserverButton.waitForExistence(timeout: 10.0)) + changeHomeserverButton.tap() let homeserverTextField = app.textFields[A11yIdentifiers.changeServerScreen.server] XCTAssertTrue(homeserverTextField.waitForExistence(timeout: 10.0)) @@ -56,6 +56,10 @@ class LoginTests: XCTestCase { XCTAssertTrue(confirmButton.waitForExistence(timeout: 10.0)) confirmButton.tap() + let continueButton = app.buttons[A11yIdentifiers.serverConfirmationScreen.continue] + XCTAssertTrue(continueButton.waitForExistence(timeout: 10.0)) + continueButton.tap() + let usernameTextField = app.textFields[A11yIdentifiers.loginScreen.emailUsername] XCTAssertTrue(usernameTextField.waitForExistence(timeout: 10.0)) diff --git a/UITests/Sources/AuthenticationCoordinatorUITests.swift b/UITests/Sources/AuthenticationCoordinatorUITests.swift index 8cbaaa2d6..a721ad7a8 100644 --- a/UITests/Sources/AuthenticationCoordinatorUITests.swift +++ b/UITests/Sources/AuthenticationCoordinatorUITests.swift @@ -27,8 +27,13 @@ class AuthenticationCoordinatorUITests: XCTestCase { // Splash Screen: Tap get started button app.buttons[A11yIdentifiers.onboardingScreen.signIn].tap() - // Login Screen: Enter valid credentials + // Server Confirmation: Tap continue button + app.buttons[A11yIdentifiers.serverConfirmationScreen.continue].tap() + // Login Screen: Confirm password login is available and not OIDC. + XCTAssertFalse(app.buttons[A11yIdentifiers.loginScreen.oidc].exists, "The OIDC button shouldn't be shown before entering a supported homeserver.") + + // Login Screen: Enter valid credentials app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("alice\n") app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("12345678") @@ -47,6 +52,9 @@ class AuthenticationCoordinatorUITests: XCTestCase { // Splash Screen: Tap get started button app.buttons[A11yIdentifiers.onboardingScreen.signIn].tap() + // Server Confirmation: Tap continue button + app.buttons[A11yIdentifiers.serverConfirmationScreen.continue].tap() + // Login Screen: Enter invalid credentials app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("alice") app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("87654321") @@ -68,16 +76,16 @@ class AuthenticationCoordinatorUITests: XCTestCase { // Splash Screen: Tap get started button app.buttons[A11yIdentifiers.onboardingScreen.signIn].tap() - // Login Screen: Tap edit server button. - XCTAssertFalse(app.buttons[A11yIdentifiers.loginScreen.oidc].exists, "The OIDC button shouldn't be shown before entering a supported homeserver.") - app.buttons[A11yIdentifiers.loginScreen.changeServer].tap() + // Server Confirmation: Tap change server button + app.buttons[A11yIdentifiers.serverConfirmationScreen.changeServer].tap() - // Server Selection: Clear the default and enter OIDC server. + // Server Selection: Clear the default, enter OIDC server and continue. app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("company.com") - - // Dismiss server screen. app.buttons[A11yIdentifiers.changeServerScreen.continue].tap() + // Server Confirmation: Tap continue button + app.buttons[A11yIdentifiers.serverConfirmationScreen.continue].tap() + // Then the login form should be updated for OIDC. XCTAssertTrue(app.buttons[A11yIdentifiers.loginScreen.oidc].waitForExistence(timeout: 1), "The OIDC button should be shown after selecting a homeserver with OIDC.") } diff --git a/UITests/Sources/ServerConfirmationScreenUITests.swift b/UITests/Sources/ServerConfirmationScreenUITests.swift new file mode 100644 index 000000000..9d050c457 --- /dev/null +++ b/UITests/Sources/ServerConfirmationScreenUITests.swift @@ -0,0 +1,31 @@ +// +// Copyright 2022 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 ElementX +import XCTest + +@MainActor +class ServerConfirmationScreenUITests: XCTestCase { + func testLoginScreen() async throws { + let app = Application.launch(.serverConfirmationLogin) + try await app.assertScreenshot(.serverConfirmationLogin) + } + + func testRegisterScreen() async throws { + let app = Application.launch(.serverConfirmationRegister) + try await app.assertScreenshot(.serverConfirmationRegister) + } +} diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.authenticationFlow.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.authenticationFlow.png index 800e3cfac..46049cd84 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.authenticationFlow.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.authenticationFlow.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef8332a434d1ee1e8e477baab70db5f21b8e19dabdfec3cb37d8a58a07f2dfa3 -size 87407 +oid sha256:1b6651cc4e5a2ae82dbb0600df7ecb9b80fad83c5d93f4e19294ad812e4a0bff +size 78763 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-0.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-0.png index 52107e7f8..c89284496 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-0.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:231a54d4b7ee98698ec443cf557d6b6d43b200600a24961366e54aa1b05bd12b -size 88208 +oid sha256:f101e9e5f108590affc8912d1232b9638ab043cb81b6caf07022db4119b9864c +size 79639 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-1.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-1.png index b597047bc..edddbfbaa 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-1.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1c86458e7d69a865e1e99b31d6d36eb8ec50b4d9451c8bbcc94dbcd551b7438 -size 75711 +oid sha256:983a85ed153810102033ab63393860e34bfaafa93008221c7561917eeef2716e +size 66743 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-2.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-2.png index e35f2abfb..fc00755b6 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-2.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login-2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afba2a8d37741ade05717616b721d421867d51fa40992909ad0299fd7b0c9c6f -size 88152 +oid sha256:f7c8ca16e04390ab80586512f5ec8bd2a93f7cf4f505e1e6eab655d716483413 +size 79966 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login.png index b6a15239b..0674cdea6 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.login.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:511188a181af1da44b6887f85ccbb88d4e19117f2f87692cf442ce3373c19433 -size 85133 +oid sha256:97bad473cac0e9bcae904de1b96112bfd6fff8dfbb5d107aaf4beaadb929165d +size 76505 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.serverConfirmationLogin.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.serverConfirmationLogin.png new file mode 100644 index 000000000..fb504d46a --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.serverConfirmationLogin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:292f2b8684d4db4b200b9aee8a2bdaa9d69d0d9f94145bb57048a3f2ffe1c5df +size 85863 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.serverConfirmationRegister.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.serverConfirmationRegister.png new file mode 100644 index 000000000..34ebcd1b4 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.serverConfirmationRegister.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62bf793cc8293609b80d153afac4f3c243d3b3fa3679ef75820c7acf87147d76 +size 91885 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.authenticationFlow.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.authenticationFlow.png index b3ee99603..284b44c98 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.authenticationFlow.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.authenticationFlow.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b40ed44328119207df894a5617b29e2b7616b7642b8bc0a8cf1dcfa0551f2491 -size 96064 +oid sha256:47db5f8d5cdebe1168faab3ef6613a23ee8cae13cad8d777370f18847af63f5c +size 84951 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-0.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-0.png index 503eeeb54..a4a22b2a6 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-0.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:834ac755d94df5f3dbc9ac2fc8bfa2a8944e8dacbdc8e1230dc898ad18412c46 -size 97420 +oid sha256:3c4fd4f4937bc6f909ca22d0fd15fb58d7c24d48655e058b30532bc771c5266e +size 85799 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-1.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-1.png index 4b2e916e3..f82e1b1f4 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-1.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dde7a3add93db5eff4bb7fcec66d43e2c467c25b514806f2d5812fb95995c79d -size 77839 +oid sha256:2323bf954c479c1cba9da33d44389875c14538e357e933521b0de7c9c99c6a7f +size 68073 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-2.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-2.png index 63675a1f4..a48e9e78b 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-2.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login-2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e14113da03d4f9ea05553836cfee5f24b002e98c7a771d11e28fe7b90016a2d8 -size 100246 +oid sha256:39f4e0c7d6659d6e0e650cc858bba9979b95d053a5d5504201b4f529ce87a3f3 +size 89379 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login.png index 577da7875..918d5223f 100644 --- a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login.png +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.login.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8dcb69fb081682f8ca9601256b6d24cf1762439ae0d4a3e68ea399e8c2db5788 -size 94481 +oid sha256:dbadc064d77df8bbfc98a358257bab41732f4d9d56497ee66f03f97601edd87b +size 82075 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.serverConfirmationLogin.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.serverConfirmationLogin.png new file mode 100644 index 000000000..752470cde --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.serverConfirmationLogin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2866f698cdc3b7374867990f0dbe7a3a60ea52194bccdc9286bf6f84e2cc7f2d +size 99923 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.serverConfirmationRegister.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.serverConfirmationRegister.png new file mode 100644 index 000000000..64b8ad6e2 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.serverConfirmationRegister.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2fbd0358f11397b58f8cd9d68ac75c51223423841a5da8b94b6cd0015c895b5 +size 107693 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.authenticationFlow.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.authenticationFlow.png index 384c7b141..8f88eb1d4 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.authenticationFlow.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.authenticationFlow.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ad9a2318453d554ae2ec43c985bbae6d5496d03561bf5759c9089592a334480 -size 92066 +oid sha256:64a2a32c9b523499e92fbbfebcddec89ae26b0569dda6e345f914597a89f86b5 +size 82328 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-0.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-0.png index a10cb1a60..227926acf 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-0.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:709dbc0dcb03e61c72900b03f93491da3a8c43ff095b0f628d91b39ec06a94f1 -size 92694 +oid sha256:e61208f06ef5ee719317d35505fd98b5c81ee3e1bf59d5086154d3900647fe07 +size 83082 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-1.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-1.png index 828dfda1a..c86bab697 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-1.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4f95f61c63e0e14193fc1f21c439709508a1c46e54a95806d42f120a2dcf793 -size 79627 +oid sha256:4256cefea1560f7a604c2e1ff9a58095f4a7c90ea84cc1654a200f1499d4939b +size 70140 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-2.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-2.png index 2b8d7be91..14778b22b 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-2.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login-2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2b9a459a16931023f81443d6518581800edbc0d9dd7b198639cfe4e55ad5f2c -size 107330 +oid sha256:7d5c56d3c46647226a54b38ac1b0cfa86bf52deb559cb634a0005c74f6b33424 +size 97924 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login.png index 43ffc7082..db4fc5045 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.login.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05a769fada47570430f9fc16381b01d77bfe3b7e1c950c553a5df3ed728b765f -size 90286 +oid sha256:c0a9e9a97c725e42877c616482014e69cf0dbc324dc98d92bacee9fb8f6e954c +size 80823 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.serverConfirmationLogin.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.serverConfirmationLogin.png new file mode 100644 index 000000000..cf5318d76 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.serverConfirmationLogin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af22b397f7a139a5ef98ec5d9d126f1422c785b8107cfb7fb446475d47cc86f3 +size 101298 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.serverConfirmationRegister.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.serverConfirmationRegister.png new file mode 100644 index 000000000..ce2af9b00 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.serverConfirmationRegister.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:feccad16655d8d39396580e69b0820f3a9700650d9875a5172758e96b6eafe09 +size 113232 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.authenticationFlow.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.authenticationFlow.png index 1b299484c..9fc1929f0 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.authenticationFlow.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.authenticationFlow.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db846fed5cd2472e611beaee52b3e02cc1d70490427e5085bb5d37813924ee32 -size 114993 +oid sha256:17b4a3f72724ab291fdb14b532c108d74e19d9f101fb4e99bab445f4586fa1ce +size 95224 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-0.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-0.png index 16581606e..c3b1ea21f 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-0.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a58acc6d270e9398b0f638fbcd23a968fa88ef968cc5943d95b73cc4883e2a22 -size 116000 +oid sha256:13222b1627ac1ae250255b13eaafce2d4e8ff417f71e01466c122159232d1b53 +size 96170 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-1.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-1.png index cb0cae674..7c70e909c 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-1.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31e489f4fd821ccf142d0cd558e23d78b8bd72f5117b4d4dabc7c5b8efad2fc5 -size 93858 +oid sha256:3bf19067e1d8b000ffd6a5d081054953be94f7f15961d055ee4eac38868f3d0e +size 74768 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-2.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-2.png index 6eecc346b..65e6ab1c6 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-2.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login-2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbedad6a1bded0780796d5e4db07a2f94770cc551ec3e071e0ab89c728c8925b -size 131905 +oid sha256:495068fcb3484f9b1329df608d84c217a019d12b812ebf8676f1987cada089db +size 122325 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login.png index 5a60d28d0..5f5aac50b 100644 --- a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login.png +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.login.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b58ab8bc33ee6ea79a2fd995a38896920e4aa64d19453bdc611365f5f63663c -size 111471 +oid sha256:3d42363d02e2878306b1b0a52a01c4491ad746f1823b0067cb1801ff164d9ff1 +size 92285 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.serverConfirmationLogin.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.serverConfirmationLogin.png new file mode 100644 index 000000000..1a1b72a32 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.serverConfirmationLogin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7162ab99e29f0cb25a3a11d954a259b4e249e4da21920e0d28dd9a72e0c1e76d +size 133333 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.serverConfirmationRegister.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.serverConfirmationRegister.png new file mode 100644 index 000000000..66ef17584 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.serverConfirmationRegister.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3602380207e0162a6677d43b4f2125c6983a41e8a6711369109585ef8f47ae6b +size 150495 diff --git a/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift b/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift new file mode 100644 index 000000000..1126941a2 --- /dev/null +++ b/UnitTests/Sources/ServerConfigurationScreenViewStateTests.swift @@ -0,0 +1,45 @@ +// +// Copyright 2023 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 XCTest + +@testable import ElementX + +class ServerConfirmationScreenViewStateTests: XCTestCase { + func testLoginMessageString() { + let matrixDotOrgLogin = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockMatrixDotOrg.address, + authenticationFlow: .login) + XCTAssertEqual(matrixDotOrgLogin.message, L10n.screenServerConfirmationMessageLoginMatrixDotOrg, "matrix.org should have a custom message.") + + let elementDotIoLogin = ServerConfirmationScreenViewState(homeserverAddress: "element.io", + authenticationFlow: .login) + XCTAssertEqual(elementDotIoLogin.message, L10n.screenServerConfirmationMessageLoginElementDotIo, "element.io should have a custom message.") + + let otherLogin = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockOIDC.address, + authenticationFlow: .login) + XCTAssertTrue(otherLogin.message.isEmpty, "Other servers should not show a message.") + } + + func testRegisterMessageString() { + let matrixDotOrgLogin = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockMatrixDotOrg.address, + authenticationFlow: .register) + XCTAssertEqual(matrixDotOrgLogin.message, L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") + + let otherLogin = ServerConfirmationScreenViewState(homeserverAddress: LoginHomeserver.mockOIDC.address, + authenticationFlow: .register) + XCTAssertEqual(otherLogin.message, L10n.screenServerConfirmationMessageRegister, "The registration message should always be the same.") + } +} diff --git a/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift b/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift new file mode 100644 index 000000000..c18cb2b2d --- /dev/null +++ b/UnitTests/Sources/ServerConfirmationScreenViewModelTests.swift @@ -0,0 +1,24 @@ +// +// Copyright 2022 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 XCTest + +@testable import ElementX + +@MainActor +class ServerConfirmationScreenViewModelTests: XCTestCase { + // Nothing to test, the view model has no mutable state. +}