mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 13:37:11 +00:00
#40: Add UserSessionStoreProtocol.
Only log out of the specific account. Add tests for the keychain controller. Expand test coverage. PR comments
This commit is contained in:
parent
abd6a9c7c0
commit
8653f1dd6b
@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objectVersion = 52;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@ -21,7 +21,6 @@
|
||||
066A1E9B94723EE9F3038044 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; };
|
||||
072BA9DBA932374CCA300125 /* MessageComposerTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE6C10032A77AE7DC5AA4C50 /* MessageComposerTextField.swift */; };
|
||||
0B1F80C2BF7D223159FBA82C /* ImageAnonymizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */; };
|
||||
0C601923A872A87C775B889A /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3689E6F87850DD65DAA45428 /* KeychainControllerProtocol.swift */; };
|
||||
0E8C480700870BB34A2A360F /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; };
|
||||
0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; };
|
||||
0EE5EBA18BA1FE10254BB489 /* UIFont+AttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */; };
|
||||
@ -67,6 +66,7 @@
|
||||
352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */; };
|
||||
35E975CFDA60E05362A7CF79 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1222DB76B917EB8A55365BA5 /* target.yml */; };
|
||||
368C8758FCD079E6AAA18C2C /* NoticeRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */; };
|
||||
36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; };
|
||||
3772354754450F2B54107E17 /* TemplateSimpleScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF4EDB32B97910AAAFE632B2 /* TemplateSimpleScreenViewModelProtocol.swift */; };
|
||||
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; };
|
||||
39AE84C8E5F2FE9D2DC7775C /* EventBasedTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56008790A9C4479A6B31FDF4 /* EventBasedTimelineView.swift */; };
|
||||
@ -125,6 +125,7 @@
|
||||
77E192BA943B90F9F310CA23 /* WeakDictionaryKeyReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFCC48E7F701B6C24484593 /* WeakDictionaryKeyReference.swift */; };
|
||||
78B71D53C1FC55FB7A9B75F0 /* RoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B0C97D2F560BCB72BE73B1 /* RoomTimelineController.swift */; };
|
||||
7963F98CDFDEAC75E072BD81 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6A8C632CEF4600107792899 /* TextRoomTimelineItem.swift */; };
|
||||
79A6E08ADE6E7C460A8A17A5 /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C37FB986891D90BEAA93EAE /* UserSessionStore.swift */; };
|
||||
7A54700193DC1F264368746A /* UserIndicatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E077F76026C85ED96FEBB810 /* UserIndicatorPresenter.swift */; };
|
||||
7B3D3AFD511D496DED18910B /* TemplateSimpleScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C485C186CEC78443DA96BDC8 /* TemplateSimpleScreenViewModelTests.swift */; };
|
||||
7BB31E67648CF32D2AB5E502 /* RoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */; };
|
||||
@ -133,7 +134,6 @@
|
||||
7D1DAAA364A9A29D554BD24E /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0950733DD4BA83EEE752E259 /* PlaceholderAvatarImage.swift */; };
|
||||
7DE5EB4CB2401C672257283C /* WeakKeyDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B12969CEC0051BC750DA5068 /* WeakKeyDictionary.swift */; };
|
||||
7E1EDBA3934E6C29E5BD045B /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77DD2DA5DC8654F2A80FF1D /* Bundle.swift */; };
|
||||
7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; };
|
||||
7F19E97E7985F518C9018B83 /* RootRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF47564C584F614B7287F3EB /* RootRouter.swift */; };
|
||||
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; };
|
||||
7FA4227B2BAAA71560252866 /* UserIndicatorDismissal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D1532B5D9FB0C8461A1453 /* UserIndicatorDismissal.swift */; };
|
||||
@ -174,7 +174,6 @@
|
||||
A851635B3255C6DC07034A12 /* RoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */; };
|
||||
A941EAD7F407F2ED6DA54A31 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA97D630B74B0616C1468CBD /* LoginScreen.swift */; };
|
||||
AB34401E4E1CAD5D2EC3072B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9760103CF316DF68698BCFE6 /* LaunchScreen.storyboard */; };
|
||||
AE5360A13B915F1CAECDE4CC /* AuthenticationMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09DD4E0CB6EE4AD939E46A62 /* AuthenticationMetrics.swift */; };
|
||||
B0EDAF55877DE19B67837C22 /* TemplateSimpleScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C29670CEC77346F31EE94C /* TemplateSimpleScreenModels.swift */; };
|
||||
B245583C63F8F90357B87FAE /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; };
|
||||
B3FDB1D9CF40777695DBBD1D /* AppCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A9AB74614131D6706894E0C /* AppCoordinatorStateMachine.swift */; };
|
||||
@ -209,18 +208,21 @@
|
||||
DCB781BD227CA958809AFADF /* Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95CC95CD75B688E946438165 /* Coordinator.swift */; };
|
||||
DDB80FD2753FEAAE43CC2AAE /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A63815AD6A5C306453342F2 /* ImageRoomTimelineItem.swift */; };
|
||||
DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */; };
|
||||
DF790EF2E4D41D1091AEB263 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317F02B15921BF5CC8486990 /* KeychainController.swift */; };
|
||||
DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = F012CB5EE3F2B67359F6CC52 /* target.yml */; };
|
||||
E81EEC1675F2371D12A880A3 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */; };
|
||||
E9CEAF2C38E4E00459B811D9 /* LoginScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A2082B5226B2A3A4D0798B6 /* LoginScreenModels.swift */; };
|
||||
EA1E7949533E19C6D862680A /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885D8C42DD17625B5261BEFF /* MediaProvider.swift */; };
|
||||
EA31DD9043B91ECB8E45A9A6 /* ScreenshotDetectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03C9D319676F3C0DC6B0203 /* ScreenshotDetectorTests.swift */; };
|
||||
EA65360A0EC026DD83AC0CF5 /* AuthenticationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */; };
|
||||
EBD6C79705B3DDB2F7E5F554 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1B52D0ABBA7091A991CAFE /* UserSessionStoreProtocol.swift */; };
|
||||
ED4F663C783E9A8C0E80B983 /* TemplateSimpleScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47543EB19F3DCF308751F53C /* TemplateSimpleScreenViewModel.swift */; };
|
||||
EE8491AD81F47DF3C192497B /* DecorationTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */; };
|
||||
EEC40663922856C65D1E0DF5 /* KeychainControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */; };
|
||||
EF99A92701E401C4CD5ADC50 /* SplashScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCE978A6118C131D7F2A04B3 /* SplashScreenModels.swift */; };
|
||||
F01DB7DD607015557CD48B33 /* ViewFrameReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 242A3BC7FAE2256930FB8527 /* ViewFrameReader.swift */; };
|
||||
F03E16ED043C62FED5A07AE0 /* MatrixEntitityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B81C8227BBEA95CCE86037 /* MatrixEntitityRegex.swift */; };
|
||||
F2DD8661B5C0BA2BB526FA6C /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD51F9FDC91C231906D76C8 /* KeychainControllerProtocol.swift */; };
|
||||
F4C3FEDB1B3A05376A1723A3 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A4427F9E0571B4E6E048A2B /* KeychainController.swift */; };
|
||||
F56261126E368C831B3DE976 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752DEC02D93AFF46BC13313A /* NavigationRouterType.swift */; };
|
||||
F656F92A63D3DC1978D79427 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 531CE4334AC5CA8DFF6AEB84 /* DTCoreText */; };
|
||||
F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */; };
|
||||
@ -261,14 +263,13 @@
|
||||
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = "<group>"; };
|
||||
0960A7F5C1B0B6679BDF26F9 /* ElementToggleStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementToggleStyle.swift; sourceTree = "<group>"; };
|
||||
09747989908EC5E4AA29F844 /* MemberDetailsProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberDetailsProviderProtocol.swift; sourceTree = "<group>"; };
|
||||
09DD4E0CB6EE4AD939E46A62 /* AuthenticationMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationMetrics.swift; sourceTree = "<group>"; };
|
||||
0A191D3FDB995309C7E2DE7D /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
|
||||
0AB7A0C06CB527A1095DEB33 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = da; path = da.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
0C13A92C1E9C79F055B8133D /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ar; path = ar.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
0CB569EAA5017B5B23970655 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
0CD51F9FDC91C231906D76C8 /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = "<group>"; };
|
||||
0DD16CE9A66C9040B066AD60 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = vi; path = vi.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
0E7062F88E9D5F79C8A80524 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = th; path = th.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStore.swift; sourceTree = "<group>"; };
|
||||
0EE9EAF0309A2A1D67D8FAF5 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sv; path = sv.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
0F7A812F160E75B69A9181A2 /* SplashScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFactory.swift; sourceTree = "<group>"; };
|
||||
@ -308,18 +309,17 @@
|
||||
2AE83A3DD63BCFBB956FE5CB /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nl; path = nl.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
2BEB3259B2208E5AE5BB3F65 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
|
||||
2CF9FE7E0CF9F40D1509E63A /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = bg; path = bg.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
317F02B15921BF5CC8486990 /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = "<group>"; };
|
||||
31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
325A2B3278875554DDEB8A9B /* SplashScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenUITests.swift; sourceTree = "<group>"; };
|
||||
32CE6D4FF64C9A3C18619224 /* SplashScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreen.swift; sourceTree = "<group>"; };
|
||||
33E49C5C6F802B4D94CA78D1 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
36322DD0D4E29D31B0945ADC /* EventBriefFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBriefFactory.swift; sourceTree = "<group>"; };
|
||||
3689E6F87850DD65DAA45428 /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = "<group>"; };
|
||||
3747C96188856006F784BF49 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ko; path = ko.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
3782C506F4FF1AADF61B6212 /* tlh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tlh; path = tlh.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
399427358A80BA2848E698A2 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
39EBB6903EFD4236B8D11A42 /* fr-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "fr-CA"; path = "fr-CA.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
3A4427F9E0571B4E6E048A2B /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = "<group>"; };
|
||||
3ACBDC1D28EFB7789EB467E0 /* MockRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomProxy.swift; sourceTree = "<group>"; };
|
||||
3B5B535DA49C54523FF7A412 /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
3CDF9E55650D6035D6536538 /* nb-NO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "nb-NO"; path = "nb-NO.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
@ -446,6 +446,7 @@
|
||||
8BF686BA36D0C2FA3C63DFDF /* ImageRoomMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomMessage.swift; sourceTree = "<group>"; };
|
||||
8C0AA893D6F8A2F563E01BB9 /* in */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = in; path = in.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
8C2ABC1A9B62BDB3D216E7FD /* MemberDetailProviderManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberDetailProviderManager.swift; sourceTree = "<group>"; };
|
||||
8C37FB986891D90BEAA93EAE /* UserSessionStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStore.swift; sourceTree = "<group>"; };
|
||||
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
90733775209F4D4D366A268F /* RootRouterType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouterType.swift; sourceTree = "<group>"; };
|
||||
92B61C243325DC76D3086494 /* EventBriefFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBriefFactoryProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -463,6 +464,7 @@
|
||||
9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportServiceProtocol.swift; sourceTree = "<group>"; };
|
||||
9C5E81214D27A6B898FC397D /* ElementX.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ElementX.entitlements; sourceTree = "<group>"; };
|
||||
9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = "<group>"; };
|
||||
A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
A1C29670CEC77346F31EE94C /* TemplateSimpleScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateSimpleScreenModels.swift; sourceTree = "<group>"; };
|
||||
A1ED7E89865201EE7D53E6DA /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
@ -510,6 +512,7 @@
|
||||
BE03C54FC7AAE0FC03EC8976 /* SplashScreenPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenPage.swift; sourceTree = "<group>"; };
|
||||
BE6C10032A77AE7DC5AA4C50 /* MessageComposerTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposerTextField.swift; sourceTree = "<group>"; };
|
||||
BEE6BF9BA63FF42F8AF6EEEA /* sr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sr; path = sr.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
BF1B52D0ABBA7091A991CAFE /* UserSessionStoreProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStoreProtocol.swift; sourceTree = "<group>"; };
|
||||
C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXAttributeScope.swift; sourceTree = "<group>"; };
|
||||
C070FD43DC6BF4E50217965A /* LocalizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationTests.swift; sourceTree = "<group>"; };
|
||||
C21ECC295F4DE8DAA86D62AC /* RoomSummaryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -582,6 +585,7 @@
|
||||
F9BA045DC4CA12D030ACF558 /* TemplateSimpleScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateSimpleScreen.swift; sourceTree = "<group>"; };
|
||||
F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
FA154570F693D93513E584C1 /* RoomMessageFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageFactory.swift; sourceTree = "<group>"; };
|
||||
FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerTests.swift; sourceTree = "<group>"; };
|
||||
FE2DF459F1737A594667CC46 /* EmoteRoomMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomMessage.swift; sourceTree = "<group>"; };
|
||||
FF4EDB32B97910AAAFE632B2 /* TemplateSimpleScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateSimpleScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -660,7 +664,7 @@
|
||||
40E6246F03D1FE377BC5D963 /* Room */,
|
||||
82D5AD3EAE3A5C1068A44A88 /* Session */,
|
||||
FCDF06BDB123505F0334B4F9 /* Timeline */,
|
||||
CBBF6127C313A5412E438BC6 /* UserSession */,
|
||||
90C85A862720155C0CF63B02 /* UserSessionStore */,
|
||||
);
|
||||
path = Services;
|
||||
sourceTree = "<group>";
|
||||
@ -716,13 +720,6 @@
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
298F75357B344DE964106404 /* Login */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = Login;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
304D3532D4FFC1F0ABC0626E /* ViewFrameReader */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -956,6 +953,7 @@
|
||||
DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */,
|
||||
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */,
|
||||
6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */,
|
||||
FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */,
|
||||
C070FD43DC6BF4E50217965A /* LocalizationTests.swift */,
|
||||
3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */,
|
||||
5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */,
|
||||
@ -1066,6 +1064,33 @@
|
||||
path = HTMLParsing;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90C85A862720155C0CF63B02 /* UserSessionStore */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3A4427F9E0571B4E6E048A2B /* KeychainController.swift */,
|
||||
0CD51F9FDC91C231906D76C8 /* KeychainControllerProtocol.swift */,
|
||||
8C37FB986891D90BEAA93EAE /* UserSessionStore.swift */,
|
||||
BF1B52D0ABBA7091A991CAFE /* UserSessionStoreProtocol.swift */,
|
||||
);
|
||||
path = UserSessionStore;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90F48FEF84016ED42A94BA24 /* LoginScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = LoginScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
91AC284E285B25BB00B7ADB9 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D77DD2DA5DC8654F2A80FF1D /* Bundle.swift */,
|
||||
4519B90DE2F54443E5F43DA8 /* String.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9413F680ECDFB2B0DDB0DEF2 /* Packages */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1227,11 +1252,10 @@
|
||||
children = (
|
||||
49EAD710A2C16EFF7C3EA16F /* Benchmark.swift */,
|
||||
E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */,
|
||||
D77DD2DA5DC8654F2A80FF1D /* Bundle.swift */,
|
||||
95CC95CD75B688E946438165 /* Coordinator.swift */,
|
||||
12A626D74BBE9F4A60763B45 /* ImageAnonymizer.swift */,
|
||||
F7B81C8227BBEA95CCE86037 /* MatrixEntitityRegex.swift */,
|
||||
4519B90DE2F54443E5F43DA8 /* String.swift */,
|
||||
91AC284E285B25BB00B7ADB9 /* Extensions */,
|
||||
8F9A844EB44B6AD7CA18FD96 /* HTMLParsing */,
|
||||
06501F0E978B2D5C92771DC7 /* Logging */,
|
||||
FE50232944F9E67ADD7A2D21 /* Routers */,
|
||||
@ -1251,16 +1275,6 @@
|
||||
path = UITests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CBBF6127C313A5412E438BC6 /* UserSession */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
317F02B15921BF5CC8486990 /* KeychainController.swift */,
|
||||
3689E6F87850DD65DAA45428 /* KeychainControllerProtocol.swift */,
|
||||
0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */,
|
||||
);
|
||||
path = UserSession;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E59565F441830B19DBAE567C /* Screens */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1305,8 +1319,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */,
|
||||
09DD4E0CB6EE4AD939E46A62 /* AuthenticationMetrics.swift */,
|
||||
298F75357B344DE964106404 /* Login */,
|
||||
9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */,
|
||||
90F48FEF84016ED42A94BA24 /* LoginScreen */,
|
||||
);
|
||||
path = Authentication;
|
||||
sourceTree = "<group>";
|
||||
@ -1650,6 +1664,7 @@
|
||||
9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */,
|
||||
F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */,
|
||||
0B1F80C2BF7D223159FBA82C /* ImageAnonymizerTests.swift in Sources */,
|
||||
EEC40663922856C65D1E0DF5 /* KeychainControllerTests.swift in Sources */,
|
||||
0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */,
|
||||
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */,
|
||||
7434A7F02D587A920B376A9A /* LoginScreenViewModelTests.swift in Sources */,
|
||||
@ -1678,7 +1693,6 @@
|
||||
3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */,
|
||||
A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */,
|
||||
EA65360A0EC026DD83AC0CF5 /* AuthenticationCoordinator.swift in Sources */,
|
||||
AE5360A13B915F1CAECDE4CC /* AuthenticationMetrics.swift in Sources */,
|
||||
CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */,
|
||||
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */,
|
||||
B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */,
|
||||
@ -1719,8 +1733,8 @@
|
||||
DDB80FD2753FEAAE43CC2AAE /* ImageRoomTimelineItem.swift in Sources */,
|
||||
D5EA4C6C80579279770D5804 /* ImageRoomTimelineView.swift in Sources */,
|
||||
A5C8F013ED9FB8AA6FEE18A7 /* InfoPlist.swift in Sources */,
|
||||
DF790EF2E4D41D1091AEB263 /* KeychainController.swift in Sources */,
|
||||
0C601923A872A87C775B889A /* KeychainControllerProtocol.swift in Sources */,
|
||||
F4C3FEDB1B3A05376A1723A3 /* KeychainController.swift in Sources */,
|
||||
F2DD8661B5C0BA2BB526FA6C /* KeychainControllerProtocol.swift in Sources */,
|
||||
9C9E48A627C7C166084E3F5B /* LabelledActivityIndicatorView.swift in Sources */,
|
||||
D826154612415D2A3BB6EBF3 /* ListTableViewAdapter.swift in Sources */,
|
||||
A941EAD7F407F2ED6DA54A31 /* LoginScreen.swift in Sources */,
|
||||
@ -1813,6 +1827,7 @@
|
||||
500CB65ED116B81DA52FDAEE /* TimelineView.swift in Sources */,
|
||||
4669804D0369FBED4E8625D1 /* ToastViewPresenter.swift in Sources */,
|
||||
9CB5129C83F75921E5E28028 /* ToastViewState.swift in Sources */,
|
||||
36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */,
|
||||
0EE5EBA18BA1FE10254BB489 /* UIFont+AttributedStringBuilder.m in Sources */,
|
||||
03CB204C52F18E24A5C3D219 /* UITestsAppCoordinator.swift in Sources */,
|
||||
17CC4FB64F3A670F43ECBE5F /* UITestsRootView.swift in Sources */,
|
||||
@ -1826,7 +1841,8 @@
|
||||
80E04BE80A89A78FBB4863BB /* UserIndicatorViewPresentable.swift in Sources */,
|
||||
8AB8ED1051216546CB35FA0E /* UserSession.swift in Sources */,
|
||||
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */,
|
||||
7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */,
|
||||
79A6E08ADE6E7C460A8A17A5 /* UserSessionStore.swift in Sources */,
|
||||
EBD6C79705B3DDB2F7E5F554 /* UserSessionStoreProtocol.swift in Sources */,
|
||||
F01DB7DD607015557CD48B33 /* ViewFrameReader.swift in Sources */,
|
||||
01F4A40C1EDCEC8DC4EC9CFA /* WeakDictionary.swift in Sources */,
|
||||
77E192BA943B90F9F310CA23 /* WeakDictionaryKeyReference.swift in Sources */,
|
||||
|
@ -18,9 +18,9 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
|
||||
private let navigationRouter: NavigationRouter
|
||||
|
||||
private let userSessionStore: UserSessionStore
|
||||
private let userSessionStore: UserSessionStoreProtocol
|
||||
|
||||
private var userSession: UserSession!
|
||||
private var userSession: UserSessionProtocol!
|
||||
|
||||
private let memberDetailProviderManager: MemberDetailProviderManager
|
||||
|
||||
@ -88,7 +88,7 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
stateMachine.processEvent(.attemptedSignIn)
|
||||
}
|
||||
|
||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator, didLoginWithSession userSession: UserSession) {
|
||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator, didLoginWithSession userSession: UserSessionProtocol) {
|
||||
self.userSession = userSession
|
||||
remove(childCoordinator: authenticationCoordinator)
|
||||
stateMachine.processEvent(.succeededSigningIn)
|
||||
@ -100,14 +100,14 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
// swiftlint:disable cyclomatic_complexity function_body_length
|
||||
private func setupStateMachine() {
|
||||
stateMachine.addTransitionHandler { [weak self] context in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch (context.fromState, context.event, context.toState) {
|
||||
case (.initial, .startWithAuthentication, .signedOut):
|
||||
self.showAuthentication()
|
||||
self.startAuthentication()
|
||||
case (.signedOut, .attemptedSignIn, .signingIn):
|
||||
self.showLoadingIndicator()
|
||||
case (.signingIn, .failedSigningIn, .signedOut):
|
||||
@ -151,7 +151,7 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
fatalError("Failed transition with context: \(context)")
|
||||
}
|
||||
}
|
||||
// swiftlint:enable cyclomatic_complexity
|
||||
// swiftlint:enable cyclomatic_complexity function_body_length
|
||||
|
||||
private func restoreUserSession() {
|
||||
Task {
|
||||
@ -166,7 +166,7 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
}
|
||||
}
|
||||
|
||||
private func showAuthentication() {
|
||||
private func startAuthentication() {
|
||||
let coordinator = AuthenticationCoordinator(userSessionStore: userSessionStore,
|
||||
navigationRouter: navigationRouter)
|
||||
coordinator.delegate = self
|
||||
@ -184,7 +184,7 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
|
||||
mainNavigationController.setViewControllers([splashViewController], animated: false)
|
||||
|
||||
showAuthentication()
|
||||
startAuthentication()
|
||||
}
|
||||
|
||||
private func presentHomeScreen() {
|
||||
|
@ -19,7 +19,7 @@ protocol AuthenticationCoordinatorDelegate: AnyObject {
|
||||
func authenticationCoordinatorDidStartLoading(_ authenticationCoordinator: AuthenticationCoordinator)
|
||||
|
||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator,
|
||||
didLoginWithSession userSession: UserSession)
|
||||
didLoginWithSession userSession: UserSessionProtocol)
|
||||
|
||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator,
|
||||
didFailWithError error: AuthenticationCoordinatorError)
|
||||
@ -27,7 +27,7 @@ protocol AuthenticationCoordinatorDelegate: AnyObject {
|
||||
|
||||
class AuthenticationCoordinator: Coordinator {
|
||||
|
||||
private let userSessionStore: UserSessionStore
|
||||
private let userSessionStore: UserSessionStoreProtocol
|
||||
private let navigationRouter: NavigationRouter
|
||||
|
||||
private(set) var clientProxy: ClientProxyProtocol?
|
||||
@ -35,7 +35,7 @@ class AuthenticationCoordinator: Coordinator {
|
||||
|
||||
weak var delegate: AuthenticationCoordinatorDelegate?
|
||||
|
||||
init(userSessionStore: UserSessionStore,
|
||||
init(userSessionStore: UserSessionStoreProtocol,
|
||||
navigationRouter: NavigationRouter) {
|
||||
self.userSessionStore = userSessionStore
|
||||
self.navigationRouter = navigationRouter
|
||||
|
@ -16,13 +16,11 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Metrics used across the entire onboarding flow.
|
||||
struct AuthenticationMetrics {
|
||||
/// Standard constants used across the app's UI.
|
||||
struct UIConstants {
|
||||
static let maxContentWidth: CGFloat = 600
|
||||
static let maxContentHeight: CGFloat = 750
|
||||
|
||||
/// The padding used between the top of the main content and the navigation bar.
|
||||
static let topPaddingToNavigationBar: CGFloat = 16
|
||||
/// The width/height used for the main icon shown in most of the screens.
|
||||
static let iconSize: CGFloat = 90
|
||||
}
|
@ -16,11 +16,7 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
protocol SplashScreenCoordinatorProtocol: Coordinator, Presentable {
|
||||
var callback: ((SplashScreenCoordinatorAction) -> Void)? { get set }
|
||||
}
|
||||
|
||||
final class SplashScreenCoordinator: SplashScreenCoordinatorProtocol {
|
||||
final class SplashScreenCoordinator: Coordinator, Presentable {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
|
@ -40,7 +40,7 @@ enum SplashScreenViewModelAction {
|
||||
|
||||
// MARK: View
|
||||
|
||||
struct SplashScreenViewState: BindableState, CustomDebugStringConvertible {
|
||||
struct SplashScreenViewState: BindableState {
|
||||
private enum Constants {
|
||||
static let gradientColors = [
|
||||
Color(red: 0.95, green: 0.98, blue: 0.96),
|
||||
@ -55,11 +55,6 @@ struct SplashScreenViewState: BindableState, CustomDebugStringConvertible {
|
||||
let content: [SplashScreenPageContent]
|
||||
var bindings: SplashScreenBindings
|
||||
|
||||
/// Custom debug description to reduce noise in the logs.
|
||||
var debugDescription: String {
|
||||
"SplashScreenViewState at page \(bindings.pageIndex)."
|
||||
}
|
||||
|
||||
init() {
|
||||
// The pun doesn't translate, so we only use it for English.
|
||||
let locale = Locale.current
|
||||
|
@ -51,6 +51,7 @@ struct SplashScreen: View {
|
||||
overlayHeight: overlayFrame.height + geometry.safeAreaInsets.bottom)
|
||||
.frame(width: geometry.size.width)
|
||||
.tag(-1)
|
||||
.accessibilityIdentifier("hiddenPage")
|
||||
|
||||
ForEach(0..<pageCount, id: \.self) { index in
|
||||
SplashScreenPage(content: viewModel.viewState.content[index],
|
||||
@ -90,7 +91,7 @@ struct SplashScreen: View {
|
||||
|
||||
buttons
|
||||
.padding(.horizontal, 16)
|
||||
.frame(maxWidth: AuthenticationMetrics.maxContentWidth)
|
||||
.frame(maxWidth: UIConstants.maxContentWidth)
|
||||
Spacer()
|
||||
}
|
||||
.background(ViewFrameReader(frame: $overlayFrame))
|
||||
|
@ -68,8 +68,8 @@ struct SplashScreenPage: View {
|
||||
Spacer().frame(maxHeight: overlayHeight)
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.frame(maxWidth: AuthenticationMetrics.maxContentWidth,
|
||||
maxHeight: AuthenticationMetrics.maxContentHeight)
|
||||
.frame(maxWidth: UIConstants.maxContentWidth,
|
||||
maxHeight: UIConstants.maxContentHeight)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(backgroundGradient.ignoresSafeArea())
|
||||
|
@ -20,7 +20,7 @@ class KeychainController: KeychainControllerProtocol {
|
||||
do {
|
||||
try keychain.set(accessToken, key: username)
|
||||
} catch {
|
||||
MXLog.error("Failed storing user restore token with error: \(error)")
|
||||
MXLog.error("Failed storing user access token with error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ class KeychainController: KeychainControllerProtocol {
|
||||
do {
|
||||
return try keychain.get(username)
|
||||
} catch {
|
||||
MXLog.error("Failed retrieving user restore token")
|
||||
MXLog.error("Failed retrieving user access token")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -43,6 +43,14 @@ class KeychainController: KeychainControllerProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func removeAccessTokenForUsername(_ username: String) {
|
||||
do {
|
||||
try keychain.remove(username)
|
||||
} catch {
|
||||
MXLog.error("Failed removing access token with error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func removeAllAccessTokens() {
|
||||
do {
|
||||
try keychain.removeAll()
|
@ -12,5 +12,6 @@ protocol KeychainControllerProtocol {
|
||||
func setAccessToken(_ accessToken: String, forUsername username: String)
|
||||
func accessTokenForUsername(_ username: String) -> String?
|
||||
func accessTokens() -> [(username: String, accessToken: String)]
|
||||
func removeAccessTokenForUsername(_ username: String)
|
||||
func removeAllAccessTokens()
|
||||
}
|
@ -18,14 +18,7 @@ import Foundation
|
||||
import MatrixRustSDK
|
||||
import Kingfisher
|
||||
|
||||
enum UserSessionStoreError: Error {
|
||||
case missingCredentials
|
||||
case failedRestoringLogin
|
||||
case failedSettingUpSession
|
||||
}
|
||||
|
||||
@MainActor
|
||||
class UserSessionStore {
|
||||
class UserSessionStore: UserSessionStoreProtocol {
|
||||
|
||||
private let keychainController: KeychainControllerProtocol
|
||||
|
||||
@ -70,8 +63,9 @@ class UserSessionStore {
|
||||
}
|
||||
|
||||
func logout(userSession: UserSessionProtocol) {
|
||||
keychainController.removeAllAccessTokens()
|
||||
deleteBaseDirectory(for: userSession.clientProxy.userIdentifier)
|
||||
let username = userSession.clientProxy.userIdentifier
|
||||
keychainController.removeAccessTokenForUsername(username)
|
||||
deleteBaseDirectory(for: username)
|
||||
}
|
||||
|
||||
private func restorePreviousLogin(_ usernameTokenTuple: (username: String, accessToken: String)) async -> Result<ClientProxyProtocol, UserSessionStoreError> {
|
@ -0,0 +1,42 @@
|
||||
//
|
||||
// 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
|
||||
import MatrixRustSDK
|
||||
|
||||
enum UserSessionStoreError: Error {
|
||||
case missingCredentials
|
||||
case failedRestoringLogin
|
||||
case failedSettingUpSession
|
||||
}
|
||||
|
||||
@MainActor
|
||||
protocol UserSessionStoreProtocol {
|
||||
/// Whether or not there are sessions in the store.
|
||||
var hasSessions: Bool { get }
|
||||
|
||||
/// Restores an existing user session.
|
||||
func restoreUserSession() async -> Result<UserSession, UserSessionStoreError>
|
||||
|
||||
/// Creates a user session for a new client from the SDK.
|
||||
func userSession(for client: Client) async -> Result<UserSession, UserSessionStoreError>
|
||||
|
||||
/// Logs out of the specified session.
|
||||
func logout(userSession: UserSessionProtocol)
|
||||
|
||||
/// Returns the location to store user data for a particular username.
|
||||
func baseDirectoryPath(for username: String) -> String
|
||||
}
|
@ -22,6 +22,8 @@ class UITestsAppCoordinator: Coordinator {
|
||||
window.tintColor = .element.accent
|
||||
|
||||
let screens = mockScreens()
|
||||
screens.forEach { $0.coordinator.start() }
|
||||
|
||||
let rootView = UITestsRootView(mockScreens: screens) { id in
|
||||
guard let screen = screens.first(where: { $0.id == id }) else {
|
||||
fatalError()
|
||||
@ -52,5 +54,5 @@ class UITestsAppCoordinator: Coordinator {
|
||||
|
||||
struct MockScreen: Identifiable {
|
||||
let id: String
|
||||
let coordinator: Presentable
|
||||
let coordinator: Coordinator & Presentable
|
||||
}
|
||||
|
@ -16,11 +16,52 @@
|
||||
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
class SplashScreenUITests: XCTestCase {
|
||||
func testInitialStateComponents() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier("Splash Screen")
|
||||
|
||||
XCTAssert(app.buttons["Get started"].exists)
|
||||
let getStartedButton = app.buttons["Get started"]
|
||||
XCTAssertTrue(getStartedButton.exists, "The primary action button should be shown.")
|
||||
}
|
||||
|
||||
func testSwipingBetweenPages() async throws {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier("Splash Screen")
|
||||
|
||||
// Given the splash screen in its initial state.
|
||||
let page1TitleText = app.staticTexts["Own your conversations."]
|
||||
let page2TitleText = app.staticTexts["You're in control."]
|
||||
let hiddenPageTitleText = app.staticTexts["hiddenPage"].firstMatch
|
||||
|
||||
XCTAssertTrue(page1TitleText.isHittable, "The title from the first page of the carousel should be onscreen.")
|
||||
XCTAssertFalse(page2TitleText.isHittable, "The title from the second page of the carousel should be offscreen.")
|
||||
XCTAssertFalse(hiddenPageTitleText.isHittable, "The hidden page of the carousel should be offscreen.")
|
||||
|
||||
// When swiping to the next screen.
|
||||
page1TitleText.swipeLeft()
|
||||
try await Task.sleep(nanoseconds: 200_000_000) // Wait for the animation.
|
||||
|
||||
// Then the second screen should be shown.
|
||||
XCTAssertFalse(page1TitleText.isHittable, "The title from the first page of the carousel should be offscreen.")
|
||||
XCTAssertTrue(page2TitleText.isHittable, "The title from the second page of the carousel should be onscreen.")
|
||||
|
||||
// When swiping back to the previous screen.
|
||||
page2TitleText.swipeRight()
|
||||
try await Task.sleep(nanoseconds: 200_000_000) // Wait for the animation.
|
||||
|
||||
// Then the first screen should be shown again.
|
||||
XCTAssertTrue(page1TitleText.isHittable, "The title from the first page of the carousel should be onscreen.")
|
||||
XCTAssertFalse(page2TitleText.isHittable, "The title from the second page of the carousel should be offscreen.")
|
||||
|
||||
// When swiping back to the previous screen.
|
||||
page1TitleText.swipeRight()
|
||||
try await Task.sleep(nanoseconds: 200_000_000) // Wait for the animation.
|
||||
|
||||
// Then the screen shouldn't change and the hidden screen should be ignored.
|
||||
XCTAssertTrue(page1TitleText.isHittable, "The title from the first page of the carousel should be still be onscreen.")
|
||||
XCTAssertFalse(page2TitleText.isHittable, "The title from the second page of the carousel should be offscreen.")
|
||||
XCTAssertFalse(hiddenPageTitleText.isHittable, "It shouldn't be possible to swipe to the hidden page of the carousel.")
|
||||
}
|
||||
}
|
||||
|
89
UnitTests/Sources/KeychainControllerTests.swift
Normal file
89
UnitTests/Sources/KeychainControllerTests.swift
Normal file
@ -0,0 +1,89 @@
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import ElementX
|
||||
|
||||
class KeychainControllerTests: XCTestCase {
|
||||
var keychain: KeychainController!
|
||||
|
||||
override func setUp() {
|
||||
keychain = KeychainController(identifier: "\(ElementInfoPlist.cfBundleIdentifier).tests")
|
||||
keychain.removeAllAccessTokens()
|
||||
}
|
||||
|
||||
func testAddAccessToken() {
|
||||
// Given an empty keychain.
|
||||
XCTAssertTrue(keychain.accessTokens().isEmpty, "The keychain should be empty to begin with.")
|
||||
|
||||
// When adding an access token.
|
||||
let username = "@test:example.com"
|
||||
let accessToken = UUID().uuidString
|
||||
keychain.setAccessToken(accessToken, forUsername: username)
|
||||
|
||||
// Then the access token should be stored in the keychain.
|
||||
XCTAssertEqual(keychain.accessTokenForUsername(username), accessToken, "The retrieved access token should match the value that was stored.")
|
||||
}
|
||||
|
||||
func testRemovingAccessToken() {
|
||||
// Given a keychain with a stored access token.
|
||||
let username = "@test:example.com"
|
||||
let accessToken = UUID().uuidString
|
||||
keychain.setAccessToken(accessToken, forUsername: username)
|
||||
XCTAssertEqual(keychain.accessTokens().count, 1, "The keychain should have 1 access token.")
|
||||
XCTAssertEqual(keychain.accessTokenForUsername(username), accessToken, "The initial access token should match the value that was stored.")
|
||||
|
||||
// When deleting the access token.
|
||||
keychain.removeAccessTokenForUsername(username)
|
||||
|
||||
// Then the keychain should be empty.
|
||||
XCTAssertTrue(keychain.accessTokens().isEmpty, "The keychain should be empty after deleting the token.")
|
||||
XCTAssertNil(keychain.accessTokenForUsername(username), "There access token should not be returned after removal.")
|
||||
}
|
||||
|
||||
func testRemovingAllAccessTokens() {
|
||||
// Given a keychain with 5 stored access tokens.
|
||||
for index in 0..<5 {
|
||||
keychain.setAccessToken(UUID().uuidString, forUsername: "@test\(index):example.com")
|
||||
}
|
||||
XCTAssertEqual(keychain.accessTokens().count, 5, "The keychain should have 5 access tokens.")
|
||||
|
||||
// When deleting all of the access tokens.
|
||||
keychain.removeAllAccessTokens()
|
||||
|
||||
// Then the keychain should be empty.
|
||||
XCTAssertTrue(keychain.accessTokens().isEmpty, "The keychain should be empty after deleting the token.")
|
||||
}
|
||||
|
||||
func testRemovingSingleAccessTokens() {
|
||||
// Given a keychain with 5 stored access tokens.
|
||||
for index in 0..<5 {
|
||||
keychain.setAccessToken(UUID().uuidString, forUsername: "@test\(index):example.com")
|
||||
}
|
||||
XCTAssertEqual(keychain.accessTokens().count, 5, "The keychain should have 5 access tokens.")
|
||||
|
||||
// When deleting one of the access tokens.
|
||||
keychain.removeAccessTokenForUsername("@test2:example.com")
|
||||
|
||||
// Then the other 4 items should remain untouched.
|
||||
XCTAssertEqual(keychain.accessTokens().count, 4, "The keychain have 4 remaining access tokens.")
|
||||
XCTAssertNotNil(keychain.accessTokenForUsername("@test0:example.com"), "The access token should not have been deleted.")
|
||||
XCTAssertNotNil(keychain.accessTokenForUsername("@test1:example.com"), "The access token should not have been deleted.")
|
||||
XCTAssertNil(keychain.accessTokenForUsername("@test2:example.com"), "The access token should have been deleted.")
|
||||
XCTAssertNotNil(keychain.accessTokenForUsername("@test3:example.com"), "The access token should not have been deleted.")
|
||||
XCTAssertNotNil(keychain.accessTokenForUsername("@test4:example.com"), "The access token should not have been deleted.")
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user