mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:12:26 +00:00
#40: Use the Rust AuthenticationService.
* Update SDK package to 1.0.12-alpha. * Use an app group for storage and stop stripping the http from the homeserver when configuring the service. * Rename access token to restore token. * Remove matrix.org server description inline with latest FTUE changes.
This commit is contained in:
@@ -37,6 +37,7 @@
|
|||||||
132D241B09F9044711FD70A5 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 91DE43B8815918E590912DDA /* InfoPlist.strings */; };
|
132D241B09F9044711FD70A5 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 91DE43B8815918E590912DDA /* InfoPlist.strings */; };
|
||||||
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */; };
|
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */; };
|
||||||
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */; };
|
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */; };
|
||||||
|
152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */; };
|
||||||
1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */; };
|
1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */; };
|
||||||
157E5FDDF419C0B2CA7E2C28 /* TimelineItemBubbledStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */; };
|
157E5FDDF419C0B2CA7E2C28 /* TimelineItemBubbledStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */; };
|
||||||
15D1F9C415D9C921643BA82E /* UserIndicatorRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61B73D5E21F524A9BE44448D /* UserIndicatorRequest.swift */; };
|
15D1F9C415D9C921643BA82E /* UserIndicatorRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61B73D5E21F524A9BE44448D /* UserIndicatorRequest.swift */; };
|
||||||
@@ -73,7 +74,7 @@
|
|||||||
2FE4EEF780553B25A446BBFB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFA5FD06AAAC4AF544B594E /* AppDelegate.swift */; };
|
2FE4EEF780553B25A446BBFB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFA5FD06AAAC4AF544B594E /* AppDelegate.swift */; };
|
||||||
30122AB3484AC6C3A7F6A717 /* ActivityIndicatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B64F3A3D0DF86ED5A241AB05 /* ActivityIndicatorView.xib */; };
|
30122AB3484AC6C3A7F6A717 /* ActivityIndicatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B64F3A3D0DF86ED5A241AB05 /* ActivityIndicatorView.xib */; };
|
||||||
3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; };
|
3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; };
|
||||||
32FC143630CE22A9E403370B /* MockAuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA38899517F08FE2AF34EB45 /* MockAuthenticationService.swift */; };
|
313382FC5D38064EAAA35CB2 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D1CC633517D695FEC54208 /* FileManager.swift */; };
|
||||||
33B4E59D408AE6E02323EE41 /* NoticeRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDA364DFFC3AC71C4771251 /* NoticeRoomMessage.swift */; };
|
33B4E59D408AE6E02323EE41 /* NoticeRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDA364DFFC3AC71C4771251 /* NoticeRoomMessage.swift */; };
|
||||||
344AF4CBB6D8786214878642 /* NavigationRouterStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9D5F812E5AD6DC786DBC9B /* NavigationRouterStoreProtocol.swift */; };
|
344AF4CBB6D8786214878642 /* NavigationRouterStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9D5F812E5AD6DC786DBC9B /* NavigationRouterStoreProtocol.swift */; };
|
||||||
34966D4C1C2C6D37FE3F7F50 /* SettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2D50A7EAA4FC78417730E /* SettingsCoordinator.swift */; };
|
34966D4C1C2C6D37FE3F7F50 /* SettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2D50A7EAA4FC78417730E /* SettingsCoordinator.swift */; };
|
||||||
@@ -116,7 +117,6 @@
|
|||||||
5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; };
|
5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; };
|
||||||
53B9C2240C2F5533246EE230 /* RectangleToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6235E1CE00A6D989D7DB6D47 /* RectangleToastView.swift */; };
|
53B9C2240C2F5533246EE230 /* RectangleToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6235E1CE00A6D989D7DB6D47 /* RectangleToastView.swift */; };
|
||||||
541374590CA7E8318BD480FD /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; };
|
541374590CA7E8318BD480FD /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; };
|
||||||
56DACDD379A86A1F5DEFE7BE /* AuthenticationServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */; };
|
|
||||||
56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; };
|
56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; };
|
||||||
59C41313AED7566C3AC51163 /* RoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */; };
|
59C41313AED7566C3AC51163 /* RoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A953B6C0C431DBF4DD00B4 /* RoomSummary.swift */; };
|
||||||
5B2C4C17888FC095ED6880B2 /* SplashViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 48971F1FFD7FC5C466889FC7 /* SplashViewController.xib */; };
|
5B2C4C17888FC095ED6880B2 /* SplashViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 48971F1FFD7FC5C466889FC7 /* SplashViewController.xib */; };
|
||||||
@@ -129,6 +129,7 @@
|
|||||||
617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */; };
|
617624A97BDBB75ED3DD8156 /* RoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */; };
|
||||||
62BBF5BE7B905222F0477FF2 /* MediaSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8210612D17A39369480FC183 /* MediaSource.swift */; };
|
62BBF5BE7B905222F0477FF2 /* MediaSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8210612D17A39369480FC183 /* MediaSource.swift */; };
|
||||||
63C9AF0FB8278AF1C0388A0C /* TemplateModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB10E673916D2B8D21FD197 /* TemplateModels.swift */; };
|
63C9AF0FB8278AF1C0388A0C /* TemplateModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB10E673916D2B8D21FD197 /* TemplateModels.swift */; };
|
||||||
|
64FF5CB4E35971255872E1BB /* AuthenticationServiceProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F0CB536D1C3CC15AA740CC6 /* AuthenticationServiceProxyProtocol.swift */; };
|
||||||
6647430A45B4A8E692909A8F /* EmoteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77C060C2ACC4CB7336A29E7 /* EmoteRoomTimelineItem.swift */; };
|
6647430A45B4A8E692909A8F /* EmoteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77C060C2ACC4CB7336A29E7 /* EmoteRoomTimelineItem.swift */; };
|
||||||
67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
|
67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
|
||||||
67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */; };
|
67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */; };
|
||||||
@@ -165,6 +166,7 @@
|
|||||||
7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; };
|
7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; };
|
||||||
7D1DAAA364A9A29D554BD24E /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0950733DD4BA83EEE752E259 /* PlaceholderAvatarImage.swift */; };
|
7D1DAAA364A9A29D554BD24E /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0950733DD4BA83EEE752E259 /* PlaceholderAvatarImage.swift */; };
|
||||||
7DE5EB4CB2401C672257283C /* WeakKeyDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B12969CEC0051BC750DA5068 /* WeakKeyDictionary.swift */; };
|
7DE5EB4CB2401C672257283C /* WeakKeyDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B12969CEC0051BC750DA5068 /* WeakKeyDictionary.swift */; };
|
||||||
|
7F08F4BC1312075E2B5EAEFA /* AuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */; };
|
||||||
7F19E97E7985F518C9018B83 /* RootRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF47564C584F614B7287F3EB /* RootRouter.swift */; };
|
7F19E97E7985F518C9018B83 /* RootRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF47564C584F614B7287F3EB /* RootRouter.swift */; };
|
||||||
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; };
|
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; };
|
||||||
7FA4227B2BAAA71560252866 /* UserIndicatorDismissal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D1532B5D9FB0C8461A1453 /* UserIndicatorDismissal.swift */; };
|
7FA4227B2BAAA71560252866 /* UserIndicatorDismissal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D1532B5D9FB0C8461A1453 /* UserIndicatorDismissal.swift */; };
|
||||||
@@ -192,7 +194,6 @@
|
|||||||
964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; };
|
964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; };
|
||||||
9738F894DB1BD383BE05767A /* ElementSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1027BB9A852F445B7623897F /* ElementSettings.swift */; };
|
9738F894DB1BD383BE05767A /* ElementSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1027BB9A852F445B7623897F /* ElementSettings.swift */; };
|
||||||
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
|
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
|
||||||
9847B056C1A216C314D21E68 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */; };
|
|
||||||
989029A28C9E2F828AD6658A /* AppIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 16DC8C5B2991724903F1FA6A /* AppIcon.pdf */; };
|
989029A28C9E2F828AD6658A /* AppIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 16DC8C5B2991724903F1FA6A /* AppIcon.pdf */; };
|
||||||
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
|
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
|
||||||
99ED42B8F8D6BFB1DBCF4C45 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
|
99ED42B8F8D6BFB1DBCF4C45 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
|
||||||
@@ -436,6 +437,7 @@
|
|||||||
4D6E4C37E9F0E53D3DF951AC /* HomeScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenUITests.swift; sourceTree = "<group>"; };
|
4D6E4C37E9F0E53D3DF951AC /* HomeScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
4DF56C3239EA3C16951E1E66 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Localizable.strings; sourceTree = "<group>"; };
|
4DF56C3239EA3C16951E1E66 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
4E854E7CF531DAC5CBEBDC75 /* ListTableViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTableViewAdapter.swift; sourceTree = "<group>"; };
|
4E854E7CF531DAC5CBEBDC75 /* ListTableViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTableViewAdapter.swift; sourceTree = "<group>"; };
|
||||||
|
4F0CB536D1C3CC15AA740CC6 /* AuthenticationServiceProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxyProtocol.swift; sourceTree = "<group>"; };
|
||||||
4F49CDE349C490D617332770 /* NoticeRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItem.swift; sourceTree = "<group>"; };
|
4F49CDE349C490D617332770 /* NoticeRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
4F5F0662483ED69791D63B16 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = et; path = et.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
4F5F0662483ED69791D63B16 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = et; path = et.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
|
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
@@ -455,7 +457,6 @@
|
|||||||
5D26A086A8278D39B5756D6F /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = "<group>"; };
|
5D26A086A8278D39B5756D6F /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = "<group>"; };
|
||||||
5D2D0A6F1ABC99D29462FB84 /* AuthenticationCoordinatorUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinatorUITests.swift; sourceTree = "<group>"; };
|
5D2D0A6F1ABC99D29462FB84 /* AuthenticationCoordinatorUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinatorUITests.swift; sourceTree = "<group>"; };
|
||||||
5D8EA85D4F10D7445BB6368A /* UserIndicatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorTests.swift; sourceTree = "<group>"; };
|
5D8EA85D4F10D7445BB6368A /* UserIndicatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorTests.swift; sourceTree = "<group>"; };
|
||||||
5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProtocol.swift; sourceTree = "<group>"; };
|
|
||||||
5F12E996BFBEB43815189ABF /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = uk; path = uk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
5F12E996BFBEB43815189ABF /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = uk; path = uk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionProtocol.swift; sourceTree = "<group>"; };
|
5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionProtocol.swift; sourceTree = "<group>"; };
|
||||||
5F77E8010D41AA3F5F9A1FCA /* NavigationModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationModule.swift; sourceTree = "<group>"; };
|
5F77E8010D41AA3F5F9A1FCA /* NavigationModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationModule.swift; sourceTree = "<group>"; };
|
||||||
@@ -472,6 +473,7 @@
|
|||||||
6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = "<group>"; };
|
6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
64B23371BC8BF6164D9F6A05 /* WeakDictionaryReference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakDictionaryReference.swift; sourceTree = "<group>"; };
|
64B23371BC8BF6164D9F6A05 /* WeakDictionaryReference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakDictionaryReference.swift; sourceTree = "<group>"; };
|
||||||
653610CB5F9776EAAAB98155 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fr; path = fr.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
653610CB5F9776EAAAB98155 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fr; path = fr.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
|
65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAuthenticationServiceProxy.swift; sourceTree = "<group>"; };
|
||||||
6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
|
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
|
||||||
@@ -569,6 +571,7 @@
|
|||||||
A65F140F9FE5E8D4DAEFF354 /* RoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxy.swift; sourceTree = "<group>"; };
|
A65F140F9FE5E8D4DAEFF354 /* RoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxy.swift; sourceTree = "<group>"; };
|
||||||
A72232816DCE2B76D48E1367 /* nb-NO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "nb-NO"; path = "nb-NO.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
A72232816DCE2B76D48E1367 /* nb-NO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "nb-NO"; path = "nb-NO.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
A8903A9F615BBD0E6D7CD133 /* ApplicationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationProtocol.swift; sourceTree = "<group>"; };
|
A8903A9F615BBD0E6D7CD133 /* ApplicationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
A8D1CC633517D695FEC54208 /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = "<group>"; };
|
||||||
A9873374E72AA53260AE90A2 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = "<group>"; };
|
A9873374E72AA53260AE90A2 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
AA19C32BD97F45847724E09A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Untranslated.strings; sourceTree = "<group>"; };
|
AA19C32BD97F45847724E09A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Untranslated.strings; sourceTree = "<group>"; };
|
||||||
AAC9344689121887B74877AF /* UnitTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
AAC9344689121887B74877AF /* UnitTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -636,6 +639,7 @@
|
|||||||
CED34C87277BA3CCC6B6EC7A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Localizable.strings; sourceTree = "<group>"; };
|
CED34C87277BA3CCC6B6EC7A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
CF3EDF23226895776553F04A /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = "<group>"; };
|
CF3EDF23226895776553F04A /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = "<group>"; };
|
||||||
CF47564C584F614B7287F3EB /* RootRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouter.swift; sourceTree = "<group>"; };
|
CF47564C584F614B7287F3EB /* RootRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouter.swift; sourceTree = "<group>"; };
|
||||||
|
CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxy.swift; sourceTree = "<group>"; };
|
||||||
CF4B39D52CAE7D21D276ABEE /* ElementNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementNavigationController.swift; sourceTree = "<group>"; };
|
CF4B39D52CAE7D21D276ABEE /* ElementNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementNavigationController.swift; sourceTree = "<group>"; };
|
||||||
CF847B3C1873B8E81CEE7FAC /* SplashScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenViewModel.swift; sourceTree = "<group>"; };
|
CF847B3C1873B8E81CEE7FAC /* SplashScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
|
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
|
||||||
@@ -649,7 +653,6 @@
|
|||||||
D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinator.swift; sourceTree = "<group>"; };
|
D6CA5F386C7701C129398945 /* AuthenticationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationCoordinator.swift; sourceTree = "<group>"; };
|
||||||
D6D094C15E8DB424F1C6FC94 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
D6D094C15E8DB424F1C6FC94 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
D6DC38E64A5ED3FDB201029A /* BugReportService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportService.swift; sourceTree = "<group>"; };
|
D6DC38E64A5ED3FDB201029A /* BugReportService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportService.swift; sourceTree = "<group>"; };
|
||||||
DA38899517F08FE2AF34EB45 /* MockAuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAuthenticationService.swift; sourceTree = "<group>"; };
|
|
||||||
DBD460ED7ED1E03B85DEA25C /* TemplateCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateCoordinator.swift; sourceTree = "<group>"; };
|
DBD460ED7ED1E03B85DEA25C /* TemplateCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateCoordinator.swift; sourceTree = "<group>"; };
|
||||||
DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXTests.swift; sourceTree = "<group>"; };
|
DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXTests.swift; sourceTree = "<group>"; };
|
||||||
DCE978A6118C131D7F2A04B3 /* SplashScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenModels.swift; sourceTree = "<group>"; };
|
DCE978A6118C131D7F2A04B3 /* SplashScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenModels.swift; sourceTree = "<group>"; };
|
||||||
@@ -686,7 +689,6 @@
|
|||||||
F0E7BF8F7BB1021F889C6483 /* MockBugReportService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBugReportService.swift; sourceTree = "<group>"; };
|
F0E7BF8F7BB1021F889C6483 /* MockBugReportService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBugReportService.swift; sourceTree = "<group>"; };
|
||||||
F23BA6D4842D53C5AC9B7584 /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nn; path = nn.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
F23BA6D4842D53C5AC9B7584 /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nn; path = nn.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
F2D58333B377888012740101 /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; };
|
F2D58333B377888012740101 /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; };
|
||||||
F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = "<group>"; };
|
|
||||||
F506C6ADB1E1DA6638078E11 /* UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
F506C6ADB1E1DA6638078E11 /* UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
F5C4AF6E3885730CD560311C /* ScreenshotDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotDetector.swift; sourceTree = "<group>"; };
|
F5C4AF6E3885730CD560311C /* ScreenshotDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotDetector.swift; sourceTree = "<group>"; };
|
||||||
F6A8C632CEF4600107792899 /* TextRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItem.swift; sourceTree = "<group>"; };
|
F6A8C632CEF4600107792899 /* TextRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
@@ -842,6 +844,13 @@
|
|||||||
path = Resources;
|
path = Resources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
3180C73BA7B8F5F7447C99B0 /* React */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
);
|
||||||
|
path = React;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
328DD5DA1281F758B72006C7 /* Views */ = {
|
328DD5DA1281F758B72006C7 /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1218,6 +1227,7 @@
|
|||||||
90C85A862720155C0CF63B02 /* UserSessionStore */ = {
|
90C85A862720155C0CF63B02 /* UserSessionStore */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
A8D1CC633517D695FEC54208 /* FileManager.swift */,
|
||||||
3A4427F9E0571B4E6E048A2B /* KeychainController.swift */,
|
3A4427F9E0571B4E6E048A2B /* KeychainController.swift */,
|
||||||
0CD51F9FDC91C231906D76C8 /* KeychainControllerProtocol.swift */,
|
0CD51F9FDC91C231906D76C8 /* KeychainControllerProtocol.swift */,
|
||||||
8C37FB986891D90BEAA93EAE /* UserSessionStore.swift */,
|
8C37FB986891D90BEAA93EAE /* UserSessionStore.swift */,
|
||||||
@@ -1364,9 +1374,9 @@
|
|||||||
AAFDD509929A0CCF8BCE51EB /* Authentication */ = {
|
AAFDD509929A0CCF8BCE51EB /* Authentication */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
F3A1AB5A84D843B6AC8D5F1E /* AuthenticationService.swift */,
|
CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */,
|
||||||
5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */,
|
4F0CB536D1C3CC15AA740CC6 /* AuthenticationServiceProxyProtocol.swift */,
|
||||||
DA38899517F08FE2AF34EB45 /* MockAuthenticationService.swift */,
|
65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */,
|
||||||
);
|
);
|
||||||
path = Authentication;
|
path = Authentication;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1486,6 +1496,7 @@
|
|||||||
E74CD7681375AD2EAA34D66B /* Authentication */,
|
E74CD7681375AD2EAA34D66B /* Authentication */,
|
||||||
4009BE2E791C16AC6EE39A7E /* BugReport */,
|
4009BE2E791C16AC6EE39A7E /* BugReport */,
|
||||||
B53CA9BECD3F97805E1432D0 /* HomeScreen */,
|
B53CA9BECD3F97805E1432D0 /* HomeScreen */,
|
||||||
|
3180C73BA7B8F5F7447C99B0 /* React */,
|
||||||
679E9837ECA8D6776079D16E /* RoomScreen */,
|
679E9837ECA8D6776079D16E /* RoomScreen */,
|
||||||
D958761758AA1110476DE6A3 /* SessionVerification */,
|
D958761758AA1110476DE6A3 /* SessionVerification */,
|
||||||
70B74A432C241E56A7ACE610 /* Settings */,
|
70B74A432C241E56A7ACE610 /* Settings */,
|
||||||
@@ -1948,8 +1959,8 @@
|
|||||||
A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */,
|
A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */,
|
||||||
EA65360A0EC026DD83AC0CF5 /* AuthenticationCoordinator.swift in Sources */,
|
EA65360A0EC026DD83AC0CF5 /* AuthenticationCoordinator.swift in Sources */,
|
||||||
B037C365CF8A58A0D149A2DB /* AuthenticationIconImage.swift in Sources */,
|
B037C365CF8A58A0D149A2DB /* AuthenticationIconImage.swift in Sources */,
|
||||||
9847B056C1A216C314D21E68 /* AuthenticationService.swift in Sources */,
|
7F08F4BC1312075E2B5EAEFA /* AuthenticationServiceProxy.swift in Sources */,
|
||||||
56DACDD379A86A1F5DEFE7BE /* AuthenticationServiceProtocol.swift in Sources */,
|
64FF5CB4E35971255872E1BB /* AuthenticationServiceProxyProtocol.swift in Sources */,
|
||||||
E0A4DCA633D174EB43AD599F /* BackgroundTaskProtocol.swift in Sources */,
|
E0A4DCA633D174EB43AD599F /* BackgroundTaskProtocol.swift in Sources */,
|
||||||
6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */,
|
6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */,
|
||||||
CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */,
|
CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */,
|
||||||
@@ -1981,6 +1992,7 @@
|
|||||||
3D325A1147F6281C57BFCDF6 /* EventBrief.swift in Sources */,
|
3D325A1147F6281C57BFCDF6 /* EventBrief.swift in Sources */,
|
||||||
418B4AEFD03DC7A6D2C9D5C8 /* EventBriefFactory.swift in Sources */,
|
418B4AEFD03DC7A6D2C9D5C8 /* EventBriefFactory.swift in Sources */,
|
||||||
F78C57B197DA74735FEBB42C /* EventBriefFactoryProtocol.swift in Sources */,
|
F78C57B197DA74735FEBB42C /* EventBriefFactoryProtocol.swift in Sources */,
|
||||||
|
313382FC5D38064EAAA35CB2 /* FileManager.swift in Sources */,
|
||||||
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */,
|
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */,
|
||||||
85AFBB433AD56704A880F8A0 /* FramePreferenceKey.swift in Sources */,
|
85AFBB433AD56704A880F8A0 /* FramePreferenceKey.swift in Sources */,
|
||||||
6A367F3D7A437A79B7D9A31C /* FullscreenLoadingViewPresenter.swift in Sources */,
|
6A367F3D7A437A79B7D9A31C /* FullscreenLoadingViewPresenter.swift in Sources */,
|
||||||
@@ -2017,7 +2029,7 @@
|
|||||||
A5EC21A071F58FC1229C20D0 /* MemberDetailsProviderProtocol.swift in Sources */,
|
A5EC21A071F58FC1229C20D0 /* MemberDetailsProviderProtocol.swift in Sources */,
|
||||||
24906A1E82D0046655958536 /* MessageComposer.swift in Sources */,
|
24906A1E82D0046655958536 /* MessageComposer.swift in Sources */,
|
||||||
072BA9DBA932374CCA300125 /* MessageComposerTextField.swift in Sources */,
|
072BA9DBA932374CCA300125 /* MessageComposerTextField.swift in Sources */,
|
||||||
32FC143630CE22A9E403370B /* MockAuthenticationService.swift in Sources */,
|
152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */,
|
||||||
28410F3DE89C2C44E4F75C92 /* MockBugReportService.swift in Sources */,
|
28410F3DE89C2C44E4F75C92 /* MockBugReportService.swift in Sources */,
|
||||||
EE4F5601356228FF72FC56B6 /* MockClientProxy.swift in Sources */,
|
EE4F5601356228FF72FC56B6 /* MockClientProxy.swift in Sources */,
|
||||||
67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */,
|
67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */,
|
||||||
@@ -2357,6 +2369,7 @@
|
|||||||
62E1B7866DF0ED442C39A83B /* Release */ = {
|
62E1B7866DF0ED442C39A83B /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
APP_GROUP_IDENTIFIER = group.io.element;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
@@ -2379,6 +2392,7 @@
|
|||||||
6897D5BC19A2EA6ABD57DE7E /* Debug */ = {
|
6897D5BC19A2EA6ABD57DE7E /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
APP_GROUP_IDENTIFIER = group.io.element;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
@@ -2674,7 +2688,7 @@
|
|||||||
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
|
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = exactVersion;
|
kind = exactVersion;
|
||||||
version = "1.0.11-alpha";
|
version = "1.0.12-alpha";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {
|
9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {
|
||||||
|
|||||||
@@ -57,10 +57,10 @@
|
|||||||
{
|
{
|
||||||
"identity" : "matrix-rust-components-swift",
|
"identity" : "matrix-rust-components-swift",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/matrix-org/matrix-rust-components-swift.git",
|
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "7d5bdf05ff97e2229cb504982162fc02c37c58e5",
|
"revision" : "3dbb1533d1c27dcd311a8c9751de7c020ccf2d8c",
|
||||||
"version" : "1.0.11-alpha"
|
"version" : "1.0.12-alpha"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func startAuthentication() {
|
private func startAuthentication() {
|
||||||
let authenticationService = AuthenticationService(userSessionStore: userSessionStore)
|
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore)
|
||||||
let coordinator = AuthenticationCoordinator(authenticationService: authenticationService,
|
let coordinator = AuthenticationCoordinator(authenticationService: authenticationService,
|
||||||
navigationRouter: navigationRouter)
|
navigationRouter: navigationRouter)
|
||||||
coordinator.delegate = self
|
coordinator.delegate = self
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Foundation
|
|||||||
final class BuildSettings {
|
final class BuildSettings {
|
||||||
// MARK: - Servers
|
// MARK: - Servers
|
||||||
|
|
||||||
static let defaultHomeserverURLString = "https://matrix.org"
|
static let defaultHomeserverAddress = "matrix.org"
|
||||||
|
|
||||||
// MARK: - Bug report
|
// MARK: - Bug report
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ internal enum ElementInfoPlist {
|
|||||||
internal static let cfBundleVersion: String = _document["CFBundleVersion"]
|
internal static let cfBundleVersion: String = _document["CFBundleVersion"]
|
||||||
internal static let uiLaunchStoryboardName: String = _document["UILaunchStoryboardName"]
|
internal static let uiLaunchStoryboardName: String = _document["UILaunchStoryboardName"]
|
||||||
internal static let uiSupportedInterfaceOrientations: [String] = _document["UISupportedInterfaceOrientations"]
|
internal static let uiSupportedInterfaceOrientations: [String] = _document["UISupportedInterfaceOrientations"]
|
||||||
|
internal static let appGroupIdentifier: String = _document["appGroupIdentifier"]
|
||||||
}
|
}
|
||||||
// swiftlint:enable identifier_name line_length type_body_length
|
// swiftlint:enable identifier_name line_length type_body_length
|
||||||
|
|
||||||
|
|||||||
@@ -16,18 +16,21 @@ protocol AuthenticationCoordinatorDelegate: AnyObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AuthenticationCoordinator: Coordinator, Presentable {
|
class AuthenticationCoordinator: Coordinator, Presentable {
|
||||||
private let authenticationService: AuthenticationServiceProtocol
|
private let authenticationService: AuthenticationServiceProxyProtocol
|
||||||
private let navigationRouter: NavigationRouter
|
private let navigationRouter: NavigationRouter
|
||||||
|
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
||||||
|
private var activityIndicator: UserIndicator?
|
||||||
|
|
||||||
private(set) var clientProxy: ClientProxyProtocol?
|
|
||||||
var childCoordinators: [Coordinator] = []
|
var childCoordinators: [Coordinator] = []
|
||||||
|
|
||||||
weak var delegate: AuthenticationCoordinatorDelegate?
|
weak var delegate: AuthenticationCoordinatorDelegate?
|
||||||
|
|
||||||
init(authenticationService: AuthenticationServiceProtocol,
|
init(authenticationService: AuthenticationServiceProxyProtocol,
|
||||||
navigationRouter: NavigationRouter) {
|
navigationRouter: NavigationRouter) {
|
||||||
self.authenticationService = authenticationService
|
self.authenticationService = authenticationService
|
||||||
self.navigationRouter = navigationRouter
|
self.navigationRouter = navigationRouter
|
||||||
|
|
||||||
|
indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: navigationRouter.toPresentable())
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
@@ -47,7 +50,7 @@ class AuthenticationCoordinator: Coordinator, Presentable {
|
|||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
switch action {
|
switch action {
|
||||||
case .login:
|
case .login:
|
||||||
self.showLoginScreen()
|
Task { await self.startAuthentication() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,19 +62,54 @@ class AuthenticationCoordinator: Coordinator, Presentable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func startAuthentication() async {
|
||||||
|
startLoading()
|
||||||
|
|
||||||
|
switch await authenticationService.configure(for: BuildSettings.defaultHomeserverAddress) {
|
||||||
|
case .success:
|
||||||
|
stopLoading()
|
||||||
|
showLoginScreen()
|
||||||
|
case .failure:
|
||||||
|
stopLoading()
|
||||||
|
showServerSelectionScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showServerSelectionScreen() {
|
||||||
|
let parameters = ServerSelectionCoordinatorParameters(authenticationService: authenticationService,
|
||||||
|
hasModalPresentation: false)
|
||||||
|
let coordinator = ServerSelectionCoordinator(parameters: parameters)
|
||||||
|
|
||||||
|
coordinator.callback = { [weak self] action in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case .updated:
|
||||||
|
self.showLoginScreen()
|
||||||
|
case .dismiss:
|
||||||
|
MXLog.failure("[AuthenticationCoordinator] ServerSelectionScreen is requesting dismiss when part of a stack.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coordinator.start()
|
||||||
|
add(childCoordinator: coordinator)
|
||||||
|
|
||||||
|
navigationRouter.push(coordinator) { [weak self] in
|
||||||
|
self?.remove(childCoordinator: coordinator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func showLoginScreen() {
|
private func showLoginScreen() {
|
||||||
let parameters = LoginCoordinatorParameters(authenticationService: authenticationService,
|
let parameters = LoginCoordinatorParameters(authenticationService: authenticationService,
|
||||||
navigationRouter: navigationRouter)
|
navigationRouter: navigationRouter)
|
||||||
let coordinator = LoginCoordinator(parameters: parameters)
|
let coordinator = LoginCoordinator(parameters: parameters)
|
||||||
|
|
||||||
coordinator.callback = { [weak self, weak coordinator] action in
|
coordinator.callback = { [weak self] action in
|
||||||
guard let self = self, let coordinator = coordinator else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case .signedIn(let userSession):
|
case .signedIn(let userSession):
|
||||||
self.delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
self.delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
||||||
self.remove(childCoordinator: coordinator)
|
|
||||||
self.navigationRouter.dismissModule()
|
|
||||||
case .continueWithOIDC:
|
case .continueWithOIDC:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -84,4 +122,14 @@ class AuthenticationCoordinator: Coordinator, Presentable {
|
|||||||
self?.remove(childCoordinator: coordinator)
|
self?.remove(childCoordinator: coordinator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Show a blocking activity indicator.
|
||||||
|
private func startLoading() {
|
||||||
|
activityIndicator = indicatorPresenter.present(.loading(label: ElementL10n.loading, isInteractionBlocking: true))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hide the currently displayed activity indicator.
|
||||||
|
private func stopLoading() {
|
||||||
|
activityIndicator = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct LoginCoordinatorParameters {
|
struct LoginCoordinatorParameters {
|
||||||
/// The service used to authenticate the user.
|
/// The service used to authenticate the user.
|
||||||
let authenticationService: AuthenticationServiceProtocol
|
let authenticationService: AuthenticationServiceProxyProtocol
|
||||||
/// The navigation router used to present the server selection screen.
|
/// The navigation router used to present the server selection screen.
|
||||||
let navigationRouter: NavigationRouterType
|
let navigationRouter: NavigationRouterType
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ final class LoginCoordinator: Coordinator, Presentable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var authenticationService: AuthenticationServiceProtocol { parameters.authenticationService }
|
private var authenticationService: AuthenticationServiceProxyProtocol { parameters.authenticationService }
|
||||||
private var navigationRouter: NavigationRouterType { parameters.navigationRouter }
|
private var navigationRouter: NavigationRouterType { parameters.navigationRouter }
|
||||||
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
||||||
private var activityIndicator: UserIndicator?
|
private var activityIndicator: UserIndicator?
|
||||||
@@ -163,7 +163,7 @@ final class LoginCoordinator: Coordinator, Presentable {
|
|||||||
startLoading(isInteractionBlocking: false)
|
startLoading(isInteractionBlocking: false)
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
switch await authenticationService.startLogin(for: homeserverDomain) {
|
switch await authenticationService.configure(for: homeserverDomain) {
|
||||||
case .success:
|
case .success:
|
||||||
updateViewModel()
|
updateViewModel()
|
||||||
stopLoading()
|
stopLoading()
|
||||||
|
|||||||
@@ -20,20 +20,15 @@ import Foundation
|
|||||||
struct LoginHomeserver: Equatable {
|
struct LoginHomeserver: Equatable {
|
||||||
/// The homeserver string to be shown to the user.
|
/// The homeserver string to be shown to the user.
|
||||||
let address: String
|
let address: String
|
||||||
/// Whether or not the homeserver is matrix.org.
|
|
||||||
let isMatrixDotOrg: Bool
|
|
||||||
/// The types login supported by the homeserver.
|
/// The types login supported by the homeserver.
|
||||||
let loginMode: LoginMode
|
var loginMode: LoginMode
|
||||||
}
|
|
||||||
|
|
||||||
extension LoginHomeserver {
|
/// Creates a new homeserver value.
|
||||||
/// Temporary initialiser for use until the FFI has homeserver discovery etc.
|
init(address: String, loginMode: LoginMode) {
|
||||||
init(address: String) {
|
|
||||||
let address = Self.sanitized(address).components(separatedBy: "://").last ?? address
|
let address = Self.sanitized(address).components(separatedBy: "://").last ?? address
|
||||||
|
|
||||||
self.address = address
|
self.address = address
|
||||||
isMatrixDotOrg = address == "matrix.org"
|
self.loginMode = loginMode
|
||||||
loginMode = .password
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sanitizes a user entered homeserver address with the following rules
|
/// Sanitizes a user entered homeserver address with the following rules
|
||||||
@@ -59,30 +54,23 @@ extension LoginHomeserver {
|
|||||||
extension LoginHomeserver {
|
extension LoginHomeserver {
|
||||||
/// A mock homeserver that is configured just like matrix.org.
|
/// A mock homeserver that is configured just like matrix.org.
|
||||||
static var mockMatrixDotOrg: LoginHomeserver {
|
static var mockMatrixDotOrg: LoginHomeserver {
|
||||||
LoginHomeserver(address: "matrix.org",
|
LoginHomeserver(address: "matrix.org", loginMode: .password)
|
||||||
isMatrixDotOrg: true,
|
|
||||||
loginMode: .password)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mock homeserver that supports login and registration via a password but has no SSO providers.
|
/// A mock homeserver that supports login and registration via a password but has no SSO providers.
|
||||||
static var mockBasicServer: LoginHomeserver {
|
static var mockBasicServer: LoginHomeserver {
|
||||||
LoginHomeserver(address: "example.com",
|
LoginHomeserver(address: "example.com", loginMode: .password)
|
||||||
isMatrixDotOrg: false,
|
|
||||||
loginMode: .password)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mock homeserver that supports only supports authentication via a single SSO provider.
|
/// A mock homeserver that supports only supports authentication via a single SSO provider.
|
||||||
static var mockOIDC: LoginHomeserver {
|
static var mockOIDC: LoginHomeserver {
|
||||||
LoginHomeserver(address: "company.com",
|
|
||||||
isMatrixDotOrg: false,
|
|
||||||
// swiftlint:disable:next force_unwrapping
|
// swiftlint:disable:next force_unwrapping
|
||||||
loginMode: .oidc(URL(string: "https://auth.company.com")!))
|
let issuerURL = URL(string: "https://auth.company.com")!
|
||||||
|
return LoginHomeserver(address: "company.com", loginMode: .oidc(issuerURL))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mock homeserver that only with no supported login flows.
|
/// A mock homeserver that only with no supported login flows.
|
||||||
static var mockUnsupported: LoginHomeserver {
|
static var mockUnsupported: LoginHomeserver {
|
||||||
LoginHomeserver(address: "server.net",
|
LoginHomeserver(address: "server.net", loginMode: .unsupported)
|
||||||
isMatrixDotOrg: false,
|
|
||||||
loginMode: .unsupported)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,8 +72,7 @@ struct LoginScreen: View {
|
|||||||
|
|
||||||
/// The sever information section that includes a button to select a different server.
|
/// The sever information section that includes a button to select a different server.
|
||||||
var serverInfo: some View {
|
var serverInfo: some View {
|
||||||
LoginServerInfoSection(address: context.viewState.homeserver.address,
|
LoginServerInfoSection(address: context.viewState.homeserver.address) {
|
||||||
showMatrixDotOrgInfo: context.viewState.homeserver.isMatrixDotOrg) {
|
|
||||||
context.send(viewAction: .selectServer)
|
context.send(viewAction: .selectServer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ struct LoginServerInfoSection: View {
|
|||||||
|
|
||||||
/// The address shown for the server.
|
/// The address shown for the server.
|
||||||
let address: String
|
let address: String
|
||||||
/// Whether or not to show the matrix.org description.
|
|
||||||
let showMatrixDotOrgInfo: Bool
|
|
||||||
/// The action performed when tapping the edit button.
|
/// The action performed when tapping the edit button.
|
||||||
let editAction: () -> Void
|
let editAction: () -> Void
|
||||||
|
|
||||||
@@ -37,19 +35,10 @@ struct LoginServerInfoSection: View {
|
|||||||
.foregroundColor(.element.secondaryContent)
|
.foregroundColor(.element.secondaryContent)
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
VStack(alignment: .leading, spacing: 2) {
|
|
||||||
Text(address)
|
Text(address)
|
||||||
.font(.element.body)
|
.font(.element.body)
|
||||||
.foregroundColor(.element.primaryContent)
|
.foregroundColor(.element.primaryContent)
|
||||||
|
|
||||||
if showMatrixDotOrgInfo {
|
|
||||||
Text(ElementL10n.authenticationServerInfoMatrixDescription)
|
|
||||||
.font(.element.caption1)
|
|
||||||
.foregroundColor(.element.tertiaryContent)
|
|
||||||
.accessibilityIdentifier("serverDescriptionText")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Button(action: editAction) {
|
Button(action: editAction) {
|
||||||
|
|||||||
+4
-4
@@ -18,7 +18,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct ServerSelectionCoordinatorParameters {
|
struct ServerSelectionCoordinatorParameters {
|
||||||
/// The service used to authenticate the user.
|
/// The service used to authenticate the user.
|
||||||
let authenticationService: AuthenticationServiceProtocol
|
let authenticationService: AuthenticationServiceProxyProtocol
|
||||||
/// Whether the screen is presented modally or within a navigation stack.
|
/// Whether the screen is presented modally or within a navigation stack.
|
||||||
let hasModalPresentation: Bool
|
let hasModalPresentation: Bool
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ final class ServerSelectionCoordinator: Coordinator, Presentable {
|
|||||||
private let serverSelectionHostingController: UIViewController
|
private let serverSelectionHostingController: UIViewController
|
||||||
private var serverSelectionViewModel: ServerSelectionViewModelProtocol
|
private var serverSelectionViewModel: ServerSelectionViewModelProtocol
|
||||||
|
|
||||||
private var authenticationService: AuthenticationServiceProtocol { parameters.authenticationService }
|
private var authenticationService: AuthenticationServiceProxyProtocol { parameters.authenticationService }
|
||||||
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
||||||
private var loadingIndicator: UserIndicator?
|
private var loadingIndicator: UserIndicator?
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ final class ServerSelectionCoordinator: Coordinator, Presentable {
|
|||||||
startLoading()
|
startLoading()
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
switch await authenticationService.startLogin(for: homeserverAddress) {
|
switch await authenticationService.configure(for: homeserverAddress) {
|
||||||
case .success:
|
case .success:
|
||||||
callback?(.updated)
|
callback?(.updated)
|
||||||
stopLoading()
|
stopLoading()
|
||||||
@@ -117,7 +117,7 @@ final class ServerSelectionCoordinator: Coordinator, Presentable {
|
|||||||
/// Processes an error to either update the flow or display it to the user.
|
/// Processes an error to either update the flow or display it to the user.
|
||||||
private func handleError(_ error: AuthenticationServiceError) {
|
private func handleError(_ error: AuthenticationServiceError) {
|
||||||
switch error {
|
switch error {
|
||||||
case .invalidServer:
|
case .invalidServer, .invalidHomeserverAddress:
|
||||||
serverSelectionViewModel.displayError(.footerMessage(ElementL10n.loginErrorHomeserverNotFound))
|
serverSelectionViewModel.displayError(.footerMessage(ElementL10n.loginErrorHomeserverNotFound))
|
||||||
default:
|
default:
|
||||||
serverSelectionViewModel.displayError(.footerMessage(ElementL10n.unknownError))
|
serverSelectionViewModel.displayError(.footerMessage(ElementL10n.unknownError))
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct PlaceholderAvatarImage: View {
|
|||||||
.padding(4)
|
.padding(4)
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
// Make the text resizable (i.e. Make it large and then allow it to scale down)
|
// Make the text resizable (i.e. Make it large and then allow it to scale down)
|
||||||
.font(.system(size: 200))
|
.font(.system(size: 200).weight(.semibold))
|
||||||
.minimumScaleFactor(0.001)
|
.minimumScaleFactor(0.001)
|
||||||
}
|
}
|
||||||
.aspectRatio(1, contentMode: .fill)
|
.aspectRatio(1, contentMode: .fill)
|
||||||
|
|||||||
+35
-16
@@ -9,42 +9,61 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import MatrixRustSDK
|
import MatrixRustSDK
|
||||||
|
|
||||||
class AuthenticationService: AuthenticationServiceProtocol {
|
class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
|
||||||
private(set) var homeserver = LoginHomeserver(address: BuildSettings.defaultHomeserverURLString)
|
private let authenticationService: AuthenticationService
|
||||||
private let userSessionStore: UserSessionStoreProtocol
|
private let userSessionStore: UserSessionStoreProtocol
|
||||||
|
|
||||||
|
// MARK: Public
|
||||||
|
|
||||||
|
private(set) var homeserver = LoginHomeserver(address: BuildSettings.defaultHomeserverAddress, loginMode: .unknown)
|
||||||
|
|
||||||
// MARK: - Setup
|
// MARK: - Setup
|
||||||
|
|
||||||
init(userSessionStore: UserSessionStoreProtocol) {
|
init(userSessionStore: UserSessionStoreProtocol) {
|
||||||
self.userSessionStore = userSessionStore
|
self.userSessionStore = userSessionStore
|
||||||
|
authenticationService = AuthenticationService(basePath: userSessionStore.baseDirectoryPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func startLogin(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError> {
|
func configure(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError> {
|
||||||
homeserver = LoginHomeserver(address: homeserverAddress)
|
let task = Task.detached { () -> LoginHomeserver in
|
||||||
|
var homeserver = LoginHomeserver(address: homeserverAddress, loginMode: .unknown)
|
||||||
|
|
||||||
|
try self.authenticationService.configureHomeserver(serverName: homeserverAddress)
|
||||||
|
|
||||||
|
guard let details = self.authenticationService.homeserverDetails() else { return homeserver }
|
||||||
|
|
||||||
|
if let issuer = details.authenticationIssuer(), let issuerURL = URL(string: issuer) {
|
||||||
|
homeserver.loginMode = .oidc(issuerURL)
|
||||||
|
} else if details.supportsPasswordLogin() {
|
||||||
|
homeserver.loginMode = .password
|
||||||
|
} else {
|
||||||
|
homeserver.loginMode = .unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
return homeserver
|
||||||
|
}
|
||||||
|
|
||||||
|
switch await task.result {
|
||||||
|
case .success(let homeserver):
|
||||||
|
self.homeserver = homeserver
|
||||||
return .success(())
|
return .success(())
|
||||||
|
case .failure(let error):
|
||||||
|
MXLog.error("Failed configuring a server: \(error)")
|
||||||
|
return .failure(.invalidHomeserverAddress)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func login(username: String, password: String) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
func login(username: String, password: String) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||||
Benchmark.startTrackingForIdentifier("Login", message: "Started new login")
|
Benchmark.startTrackingForIdentifier("Login", message: "Started new login")
|
||||||
|
|
||||||
// Workaround whilst the SDK requires a full MXID.
|
|
||||||
let username = username.isMatrixUserID ? username : "@\(username):\(homeserver.address)"
|
|
||||||
|
|
||||||
let basePath = userSessionStore.baseDirectoryPath(for: username)
|
|
||||||
let builder = ClientBuilder()
|
|
||||||
.basePath(path: basePath)
|
|
||||||
.username(username: username)
|
|
||||||
|
|
||||||
let loginTask: Task<Client, Error> = Task.detached {
|
let loginTask: Task<Client, Error> = Task.detached {
|
||||||
let client = try builder.build()
|
try self.authenticationService.login(username: username, password: password)
|
||||||
try client.login(username: username, password: password)
|
|
||||||
return client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch await loginTask.result {
|
switch await loginTask.result {
|
||||||
@@ -55,7 +74,7 @@ class AuthenticationService: AuthenticationServiceProtocol {
|
|||||||
Benchmark.endTrackingForIdentifier("Login", message: "Login failed")
|
Benchmark.endTrackingForIdentifier("Login", message: "Login failed")
|
||||||
|
|
||||||
MXLog.error("Failed logging in with error: \(error)")
|
MXLog.error("Failed logging in with error: \(error)")
|
||||||
guard let error = error as? ClientError else { return .failure(.failedLoggingIn) }
|
guard let error = error as? AuthenticationError else { return .failure(.failedLoggingIn) }
|
||||||
|
|
||||||
switch error.code {
|
switch error.code {
|
||||||
case .forbidden:
|
case .forbidden:
|
||||||
+4
-3
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// AuthenticationServiceProtocol.swift
|
// AuthenticationServiceProxyProtocol.swift
|
||||||
// ElementX
|
// ElementX
|
||||||
//
|
//
|
||||||
// Created by Doug on 29/06/2022.
|
// Created by Doug on 29/06/2022.
|
||||||
@@ -11,16 +11,17 @@ import Foundation
|
|||||||
enum AuthenticationServiceError: Error {
|
enum AuthenticationServiceError: Error {
|
||||||
case invalidServer
|
case invalidServer
|
||||||
case invalidCredentials
|
case invalidCredentials
|
||||||
|
case invalidHomeserverAddress
|
||||||
case accountDeactivated
|
case accountDeactivated
|
||||||
case failedLoggingIn
|
case failedLoggingIn
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
protocol AuthenticationServiceProtocol {
|
protocol AuthenticationServiceProxyProtocol {
|
||||||
var homeserver: LoginHomeserver { get }
|
var homeserver: LoginHomeserver { get }
|
||||||
|
|
||||||
/// Sets up the service for login on the specified homeserver address.
|
/// Sets up the service for login on the specified homeserver address.
|
||||||
func startLogin(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError>
|
func configure(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError>
|
||||||
/// Performs a password login using the current homeserver.
|
/// Performs a password login using the current homeserver.
|
||||||
func login(username: String, password: String) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
func login(username: String, password: String) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
||||||
}
|
}
|
||||||
+2
-2
@@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class MockAuthenticationService: AuthenticationServiceProtocol {
|
class MockAuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||||
let validCredentials = (username: "alice", password: "12345678")
|
let validCredentials = (username: "alice", password: "12345678")
|
||||||
private(set) var homeserver: LoginHomeserver = .mockMatrixDotOrg
|
private(set) var homeserver: LoginHomeserver = .mockMatrixDotOrg
|
||||||
|
|
||||||
func startLogin(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError> {
|
func configure(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError> {
|
||||||
// Map the address to the mock homeservers
|
// Map the address to the mock homeservers
|
||||||
if LoginHomeserver.mockMatrixDotOrg.address.contains(homeserverAddress) {
|
if LoginHomeserver.mockMatrixDotOrg.address.contains(homeserverAddress) {
|
||||||
homeserver = .mockMatrixDotOrg
|
homeserver = .mockMatrixDotOrg
|
||||||
@@ -15,7 +15,7 @@ enum MatrixErrorCode: String, CaseIterable {
|
|||||||
case forbidden = "M_FORBIDDEN"
|
case forbidden = "M_FORBIDDEN"
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ClientError {
|
extension AuthenticationError {
|
||||||
var code: MatrixErrorCode {
|
var code: MatrixErrorCode {
|
||||||
guard case let .Generic(message) = self else { return .unknown }
|
guard case let .Generic(message) = self else { return .unknown }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// FileManager.swift
|
||||||
|
// ElementX
|
||||||
|
//
|
||||||
|
// Created by Doug on 19/07/2022.
|
||||||
|
// Copyright © 2022 Element. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension FileManager {
|
||||||
|
/// The URL of the primary app group container.
|
||||||
|
var appGroupContainerURL: URL? {
|
||||||
|
containerURL(forSecurityApplicationGroupIdentifier: ElementInfoPlist.appGroupIdentifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,42 +16,42 @@ class KeychainController: KeychainControllerProtocol {
|
|||||||
keychain = Keychain(service: identifier)
|
keychain = Keychain(service: identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setAccessToken(_ accessToken: String, forUsername username: String) {
|
func setRestoreToken(_ restoreToken: String, forUsername username: String) {
|
||||||
do {
|
do {
|
||||||
try keychain.set(accessToken, key: username)
|
try keychain.set(restoreToken, key: username)
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed storing user access token with error: \(error)")
|
MXLog.error("Failed storing user restore token with error: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func accessTokenForUsername(_ username: String) -> String? {
|
func restoreTokenForUsername(_ username: String) -> String? {
|
||||||
do {
|
do {
|
||||||
return try keychain.get(username)
|
return try keychain.get(username)
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed retrieving user access token")
|
MXLog.error("Failed retrieving user restore token")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func accessTokens() -> [(username: String, accessToken: String)] {
|
func restoreTokens() -> [KeychainCredentials] {
|
||||||
keychain.allKeys().compactMap { username in
|
keychain.allKeys().compactMap { username in
|
||||||
guard let accessToken = accessTokenForUsername(username) else {
|
guard let restoreToken = restoreTokenForUsername(username) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return (username, accessToken)
|
return KeychainCredentials(userID: username, restoreToken: restoreToken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeAccessTokenForUsername(_ username: String) {
|
func removeRestoreTokenForUsername(_ username: String) {
|
||||||
do {
|
do {
|
||||||
try keychain.remove(username)
|
try keychain.remove(username)
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed removing access token with error: \(error)")
|
MXLog.error("Failed removing restore token with error: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeAllAccessTokens() {
|
func removeAllRestoreTokens() {
|
||||||
do {
|
do {
|
||||||
try keychain.removeAll()
|
try keychain.removeAll()
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -8,10 +8,15 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
protocol KeychainControllerProtocol {
|
struct KeychainCredentials {
|
||||||
func setAccessToken(_ accessToken: String, forUsername username: String)
|
let userID: String
|
||||||
func accessTokenForUsername(_ username: String) -> String?
|
let restoreToken: String
|
||||||
func accessTokens() -> [(username: String, accessToken: String)]
|
}
|
||||||
func removeAccessTokenForUsername(_ username: String)
|
|
||||||
func removeAllAccessTokens()
|
protocol KeychainControllerProtocol {
|
||||||
|
func setRestoreToken(_ accessToken: String, forUsername username: String)
|
||||||
|
func restoreTokenForUsername(_ username: String) -> String?
|
||||||
|
func restoreTokens() -> [KeychainCredentials]
|
||||||
|
func removeRestoreTokenForUsername(_ username: String)
|
||||||
|
func removeAllRestoreTokens()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
private let backgroundTaskService: BackgroundTaskServiceProtocol
|
private let backgroundTaskService: BackgroundTaskServiceProtocol
|
||||||
|
|
||||||
/// Whether or not there are sessions in the store.
|
/// Whether or not there are sessions in the store.
|
||||||
var hasSessions: Bool { !keychainController.accessTokens().isEmpty }
|
var hasSessions: Bool { !keychainController.restoreTokens().isEmpty }
|
||||||
|
|
||||||
|
/// The base directory where all session data is stored.
|
||||||
|
var baseDirectoryPath: String { baseDirectory().path }
|
||||||
|
|
||||||
init(bundleIdentifier: String, backgroundTaskService: BackgroundTaskServiceProtocol) {
|
init(bundleIdentifier: String, backgroundTaskService: BackgroundTaskServiceProtocol) {
|
||||||
keychainController = KeychainController(identifier: bundleIdentifier)
|
keychainController = KeychainController(identifier: bundleIdentifier)
|
||||||
@@ -31,13 +34,13 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func restoreUserSession() async -> Result<UserSession, UserSessionStoreError> {
|
func restoreUserSession() async -> Result<UserSession, UserSessionStoreError> {
|
||||||
let availableAccessTokens = keychainController.accessTokens()
|
let availableCredentials = keychainController.restoreTokens()
|
||||||
|
|
||||||
guard let usernameTokenTuple = availableAccessTokens.first else {
|
guard let credentials = availableCredentials.first else {
|
||||||
return .failure(.missingCredentials)
|
return .failure(.missingCredentials)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch await restorePreviousLogin(usernameTokenTuple) {
|
switch await restorePreviousLogin(credentials) {
|
||||||
case .success(let clientProxy):
|
case .success(let clientProxy):
|
||||||
return .success(UserSession(clientProxy: clientProxy,
|
return .success(UserSession(clientProxy: clientProxy,
|
||||||
mediaProvider: MediaProvider(clientProxy: clientProxy,
|
mediaProvider: MediaProvider(clientProxy: clientProxy,
|
||||||
@@ -47,8 +50,8 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
MXLog.error("Failed restoring login with error: \(error)")
|
MXLog.error("Failed restoring login with error: \(error)")
|
||||||
|
|
||||||
// On any restoration failure reset the token and restart
|
// On any restoration failure reset the token and restart
|
||||||
keychainController.removeAllAccessTokens()
|
keychainController.removeAllRestoreTokens()
|
||||||
deleteBaseDirectory(for: usernameTokenTuple.username)
|
deleteSessionDirectory(for: credentials.userID)
|
||||||
|
|
||||||
return .failure(error)
|
return .failure(error)
|
||||||
}
|
}
|
||||||
@@ -68,22 +71,21 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func logout(userSession: UserSessionProtocol) {
|
func logout(userSession: UserSessionProtocol) {
|
||||||
let username = userSession.clientProxy.userIdentifier
|
let userID = userSession.clientProxy.userIdentifier
|
||||||
keychainController.removeAccessTokenForUsername(username)
|
keychainController.removeRestoreTokenForUsername(userID)
|
||||||
deleteBaseDirectory(for: username)
|
deleteSessionDirectory(for: userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func restorePreviousLogin(_ usernameTokenTuple: (username: String, accessToken: String)) async -> Result<ClientProxyProtocol, UserSessionStoreError> {
|
private func restorePreviousLogin(_ credentials: KeychainCredentials) async -> Result<ClientProxyProtocol, UserSessionStoreError> {
|
||||||
Benchmark.startTrackingForIdentifier("Login", message: "Started restoring previous login")
|
Benchmark.startTrackingForIdentifier("Login", message: "Started restoring previous login")
|
||||||
|
|
||||||
let basePath = baseDirectoryPath(for: usernameTokenTuple.username)
|
|
||||||
let builder = ClientBuilder()
|
let builder = ClientBuilder()
|
||||||
.basePath(path: basePath)
|
.basePath(path: baseDirectoryPath)
|
||||||
.username(username: usernameTokenTuple.username)
|
.username(username: credentials.userID)
|
||||||
|
|
||||||
let loginTask: Task<Client, Error> = Task.detached {
|
let loginTask: Task<Client, Error> = Task.detached {
|
||||||
let client = try builder.build()
|
let client = try builder.build()
|
||||||
try client.restoreLogin(restoreToken: usernameTokenTuple.accessToken)
|
try client.restoreLogin(restoreToken: credentials.restoreToken)
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +103,7 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
let accessToken = try client.restoreToken()
|
let accessToken = try client.restoreToken()
|
||||||
let userId = try client.userId()
|
let userId = try client.userId()
|
||||||
|
|
||||||
keychainController.setAccessToken(accessToken, forUsername: userId)
|
keychainController.setRestoreToken(accessToken, forUsername: userId)
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed setting up user session with error: \(error)")
|
MXLog.error("Failed setting up user session with error: \(error)")
|
||||||
return .failure(.failedSettingUpSession)
|
return .failure(.failedSettingUpSession)
|
||||||
@@ -112,25 +114,30 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
return .success(clientProxy)
|
return .success(clientProxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
func baseDirectoryPath(for username: String) -> String {
|
private func deleteSessionDirectory(for userID: String) {
|
||||||
guard var url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
|
// Rust sanitises the user ID replacing invalid characters with an _
|
||||||
fatalError("Should always be able to retrieve the caches directory")
|
let sanitisedUserID = userID.replacingOccurrences(of: ":", with: "_")
|
||||||
|
let url = baseDirectory().appendingPathComponent(sanitisedUserID)
|
||||||
|
|
||||||
|
do {
|
||||||
|
try FileManager.default.removeItem(at: url)
|
||||||
|
} catch {
|
||||||
|
MXLog.failure("Failed deleting the session data: \(error)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url = url.appendingPathComponent(username)
|
func baseDirectory() -> URL {
|
||||||
|
guard let appGroupContainerURL = FileManager.default.appGroupContainerURL else {
|
||||||
|
fatalError("Should always be able to retrieve the container directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = appGroupContainerURL
|
||||||
|
.appendingPathComponent("Library", isDirectory: true)
|
||||||
|
.appendingPathComponent("Caches", isDirectory: true)
|
||||||
|
.appendingPathComponent("Sessions", isDirectory: true)
|
||||||
|
|
||||||
try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil)
|
try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil)
|
||||||
|
|
||||||
return url.path
|
return url
|
||||||
}
|
|
||||||
|
|
||||||
private func deleteBaseDirectory(for username: String) {
|
|
||||||
guard var url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
|
|
||||||
fatalError("Should always be able to retrieve the caches directory")
|
|
||||||
}
|
|
||||||
|
|
||||||
url = url.appendingPathComponent(username)
|
|
||||||
|
|
||||||
try? FileManager.default.removeItem(at: url)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ protocol UserSessionStoreProtocol {
|
|||||||
/// Whether or not there are sessions in the store.
|
/// Whether or not there are sessions in the store.
|
||||||
var hasSessions: Bool { get }
|
var hasSessions: Bool { get }
|
||||||
|
|
||||||
|
/// Returns the location to store user data for a particular username.
|
||||||
|
var baseDirectoryPath: String { get }
|
||||||
|
|
||||||
/// Restores an existing user session.
|
/// Restores an existing user session.
|
||||||
func restoreUserSession() async -> Result<UserSession, UserSessionStoreError>
|
func restoreUserSession() async -> Result<UserSession, UserSessionStoreError>
|
||||||
|
|
||||||
@@ -36,7 +39,4 @@ protocol UserSessionStoreProtocol {
|
|||||||
|
|
||||||
/// Logs out of the specified session.
|
/// Logs out of the specified session.
|
||||||
func logout(userSession: UserSessionProtocol)
|
func logout(userSession: UserSessionProtocol)
|
||||||
|
|
||||||
/// Returns the location to store user data for a particular username.
|
|
||||||
func baseDirectoryPath(for username: String) -> String
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,16 +60,16 @@ class MockScreen: Identifiable {
|
|||||||
lazy var coordinator: Coordinator & Presentable = {
|
lazy var coordinator: Coordinator & Presentable = {
|
||||||
switch id {
|
switch id {
|
||||||
case .login:
|
case .login:
|
||||||
return LoginCoordinator(parameters: .init(authenticationService: MockAuthenticationService(),
|
return LoginCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
|
||||||
navigationRouter: navigationRouter))
|
navigationRouter: navigationRouter))
|
||||||
case .serverSelection:
|
case .serverSelection:
|
||||||
return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationService(),
|
return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
|
||||||
hasModalPresentation: true))
|
hasModalPresentation: true))
|
||||||
case .serverSelectionNonModal:
|
case .serverSelectionNonModal:
|
||||||
return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationService(),
|
return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
|
||||||
hasModalPresentation: false))
|
hasModalPresentation: false))
|
||||||
case .authenticationFlow:
|
case .authenticationFlow:
|
||||||
return AuthenticationCoordinator(authenticationService: MockAuthenticationService(),
|
return AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(),
|
||||||
navigationRouter: navigationRouter)
|
navigationRouter: navigationRouter)
|
||||||
case .simpleRegular:
|
case .simpleRegular:
|
||||||
return TemplateCoordinator(parameters: .init(promptType: .regular))
|
return TemplateCoordinator(parameters: .init(promptType: .regular))
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
<key>com.apple.security.app-sandbox</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||||
|
</array>
|
||||||
<key>com.apple.security.network.client</key>
|
<key>com.apple.security.network.client</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>keychain-access-groups</key>
|
<key>keychain-access-groups</key>
|
||||||
|
|||||||
@@ -27,5 +27,7 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>appGroupIdentifier</key>
|
||||||
|
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -46,11 +46,13 @@ targets:
|
|||||||
UIInterfaceOrientationLandscapeLeft,
|
UIInterfaceOrientationLandscapeLeft,
|
||||||
UIInterfaceOrientationLandscapeRight
|
UIInterfaceOrientationLandscapeRight
|
||||||
]
|
]
|
||||||
|
appGroupIdentifier: $(APP_GROUP_IDENTIFIER)
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
base:
|
base:
|
||||||
PRODUCT_NAME: ElementX
|
PRODUCT_NAME: ElementX
|
||||||
PRODUCT_BUNDLE_IDENTIFIER: io.element.elementx
|
PRODUCT_BUNDLE_IDENTIFIER: io.element.elementx
|
||||||
|
APP_GROUP_IDENTIFIER: group.io.element
|
||||||
MARKETING_VERSION: 1.0.2
|
MARKETING_VERSION: 1.0.2
|
||||||
CURRENT_PROJECT_VERSION: 1
|
CURRENT_PROJECT_VERSION: 1
|
||||||
DEVELOPMENT_TEAM: 7J4U792NQT
|
DEVELOPMENT_TEAM: 7J4U792NQT
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ class LoginScreenUITests: XCTestCase {
|
|||||||
app.goToScreenWithIdentifier(.login)
|
app.goToScreenWithIdentifier(.login)
|
||||||
|
|
||||||
let state = "matrix.org"
|
let state = "matrix.org"
|
||||||
validateServerDescriptionIsVisible(for: state)
|
|
||||||
validateLoginFormIsVisible(for: state)
|
validateLoginFormIsVisible(for: state)
|
||||||
validateOIDCButtonIsHidden(for: state)
|
validateOIDCButtonIsHidden(for: state)
|
||||||
validateNextButtonIsDisabled(for: state)
|
validateNextButtonIsDisabled(for: state)
|
||||||
@@ -61,7 +60,6 @@ class LoginScreenUITests: XCTestCase {
|
|||||||
// Then the screen should be configured for OIDC.
|
// Then the screen should be configured for OIDC.
|
||||||
let state = "an OIDC only server"
|
let state = "an OIDC only server"
|
||||||
validateOIDCButtonIsShown(for: state)
|
validateOIDCButtonIsShown(for: state)
|
||||||
validateServerDescriptionIsHidden(for: state)
|
|
||||||
validateLoginFormIsHidden(for: state)
|
validateLoginFormIsHidden(for: state)
|
||||||
validateUnsupportedServerTextIsHidden(for: state)
|
validateUnsupportedServerTextIsHidden(for: state)
|
||||||
}
|
}
|
||||||
@@ -78,24 +76,10 @@ class LoginScreenUITests: XCTestCase {
|
|||||||
// Then the screen should not allow login to continue.
|
// Then the screen should not allow login to continue.
|
||||||
let state = "an unsupported server"
|
let state = "an unsupported server"
|
||||||
validateUnsupportedServerTextIsShown(for: state)
|
validateUnsupportedServerTextIsShown(for: state)
|
||||||
validateServerDescriptionIsHidden(for: state)
|
|
||||||
validateLoginFormIsHidden(for: state)
|
validateLoginFormIsHidden(for: state)
|
||||||
validateOIDCButtonIsHidden(for: state)
|
validateOIDCButtonIsHidden(for: state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that the server description label is shown.
|
|
||||||
func validateServerDescriptionIsVisible(for state: String) {
|
|
||||||
let descriptionLabel = app.staticTexts["serverDescriptionText"]
|
|
||||||
XCTAssertTrue(descriptionLabel.exists, "The server description should be shown for \(state).")
|
|
||||||
XCTAssertEqual(descriptionLabel.label, ElementL10n.authenticationServerInfoMatrixDescription)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks that the server description label is hidden.
|
|
||||||
func validateServerDescriptionIsHidden(for state: String) {
|
|
||||||
let descriptionLabel = app.staticTexts["serverDescriptionText"]
|
|
||||||
XCTAssertFalse(descriptionLabel.exists, "The server description should be hidden for \(state).")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks that the username and password text fields are shown along with the next button.
|
/// Checks that the username and password text fields are shown along with the next button.
|
||||||
func validateLoginFormIsVisible(for state: String) {
|
func validateLoginFormIsVisible(for state: String) {
|
||||||
let usernameTextField = app.textFields.element
|
let usernameTextField = app.textFields.element
|
||||||
|
|||||||
@@ -22,68 +22,68 @@ class KeychainControllerTests: XCTestCase {
|
|||||||
|
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
keychain = KeychainController(identifier: "\(ElementInfoPlist.cfBundleIdentifier).tests")
|
keychain = KeychainController(identifier: "\(ElementInfoPlist.cfBundleIdentifier).tests")
|
||||||
keychain.removeAllAccessTokens()
|
keychain.removeAllRestoreTokens()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAddAccessToken() {
|
func testAddRestoreToken() {
|
||||||
// Given an empty keychain.
|
// Given an empty keychain.
|
||||||
XCTAssertTrue(keychain.accessTokens().isEmpty, "The keychain should be empty to begin with.")
|
XCTAssertTrue(keychain.restoreTokens().isEmpty, "The keychain should be empty to begin with.")
|
||||||
|
|
||||||
// When adding an access token.
|
// When adding an restore token.
|
||||||
let username = "@test:example.com"
|
let username = "@test:example.com"
|
||||||
let accessToken = UUID().uuidString
|
let restoreToken = UUID().uuidString
|
||||||
keychain.setAccessToken(accessToken, forUsername: username)
|
keychain.setRestoreToken(restoreToken, forUsername: username)
|
||||||
|
|
||||||
// Then the access token should be stored in the keychain.
|
// Then the restore token should be stored in the keychain.
|
||||||
XCTAssertEqual(keychain.accessTokenForUsername(username), accessToken, "The retrieved access token should match the value that was stored.")
|
XCTAssertEqual(keychain.restoreTokenForUsername(username), restoreToken, "The retrieved restore token should match the value that was stored.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRemovingAccessToken() {
|
func testRemovingRestoreToken() {
|
||||||
// Given a keychain with a stored access token.
|
// Given a keychain with a stored restore token.
|
||||||
let username = "@test:example.com"
|
let username = "@test:example.com"
|
||||||
let accessToken = UUID().uuidString
|
let restoreToken = UUID().uuidString
|
||||||
keychain.setAccessToken(accessToken, forUsername: username)
|
keychain.setRestoreToken(restoreToken, forUsername: username)
|
||||||
XCTAssertEqual(keychain.accessTokens().count, 1, "The keychain should have 1 access token.")
|
XCTAssertEqual(keychain.restoreTokens().count, 1, "The keychain should have 1 restore token.")
|
||||||
XCTAssertEqual(keychain.accessTokenForUsername(username), accessToken, "The initial access token should match the value that was stored.")
|
XCTAssertEqual(keychain.restoreTokenForUsername(username), restoreToken, "The initial restore token should match the value that was stored.")
|
||||||
|
|
||||||
// When deleting the access token.
|
// When deleting the restore token.
|
||||||
keychain.removeAccessTokenForUsername(username)
|
keychain.removeRestoreTokenForUsername(username)
|
||||||
|
|
||||||
// Then the keychain should be empty.
|
// Then the keychain should be empty.
|
||||||
XCTAssertTrue(keychain.accessTokens().isEmpty, "The keychain should be empty after deleting the token.")
|
XCTAssertTrue(keychain.restoreTokens().isEmpty, "The keychain should be empty after deleting the token.")
|
||||||
XCTAssertNil(keychain.accessTokenForUsername(username), "There access token should not be returned after removal.")
|
XCTAssertNil(keychain.restoreTokenForUsername(username), "There restore token should not be returned after removal.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRemovingAllAccessTokens() {
|
func testRemovingAllRestoreTokens() {
|
||||||
// Given a keychain with 5 stored access tokens.
|
// Given a keychain with 5 stored restore tokens.
|
||||||
for index in 0..<5 {
|
for index in 0..<5 {
|
||||||
keychain.setAccessToken(UUID().uuidString, forUsername: "@test\(index):example.com")
|
keychain.setRestoreToken(UUID().uuidString, forUsername: "@test\(index):example.com")
|
||||||
}
|
}
|
||||||
XCTAssertEqual(keychain.accessTokens().count, 5, "The keychain should have 5 access tokens.")
|
XCTAssertEqual(keychain.restoreTokens().count, 5, "The keychain should have 5 restore tokens.")
|
||||||
|
|
||||||
// When deleting all of the access tokens.
|
// When deleting all of the restore tokens.
|
||||||
keychain.removeAllAccessTokens()
|
keychain.removeAllRestoreTokens()
|
||||||
|
|
||||||
// Then the keychain should be empty.
|
// Then the keychain should be empty.
|
||||||
XCTAssertTrue(keychain.accessTokens().isEmpty, "The keychain should be empty after deleting the token.")
|
XCTAssertTrue(keychain.restoreTokens().isEmpty, "The keychain should be empty after deleting the token.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRemovingSingleAccessTokens() {
|
func testRemovingSingleRestoreTokens() {
|
||||||
// Given a keychain with 5 stored access tokens.
|
// Given a keychain with 5 stored restore tokens.
|
||||||
for index in 0..<5 {
|
for index in 0..<5 {
|
||||||
keychain.setAccessToken(UUID().uuidString, forUsername: "@test\(index):example.com")
|
keychain.setRestoreToken(UUID().uuidString, forUsername: "@test\(index):example.com")
|
||||||
}
|
}
|
||||||
XCTAssertEqual(keychain.accessTokens().count, 5, "The keychain should have 5 access tokens.")
|
XCTAssertEqual(keychain.restoreTokens().count, 5, "The keychain should have 5 restore tokens.")
|
||||||
|
|
||||||
// When deleting one of the access tokens.
|
// When deleting one of the restore tokens.
|
||||||
keychain.removeAccessTokenForUsername("@test2:example.com")
|
keychain.removeRestoreTokenForUsername("@test2:example.com")
|
||||||
|
|
||||||
// Then the other 4 items should remain untouched.
|
// Then the other 4 items should remain untouched.
|
||||||
XCTAssertEqual(keychain.accessTokens().count, 4, "The keychain have 4 remaining access tokens.")
|
XCTAssertEqual(keychain.restoreTokens().count, 4, "The keychain have 4 remaining restore tokens.")
|
||||||
XCTAssertNotNil(keychain.accessTokenForUsername("@test0:example.com"), "The access token should not have been deleted.")
|
XCTAssertNotNil(keychain.restoreTokenForUsername("@test0:example.com"), "The restore token should not have been deleted.")
|
||||||
XCTAssertNotNil(keychain.accessTokenForUsername("@test1:example.com"), "The access token should not have been deleted.")
|
XCTAssertNotNil(keychain.restoreTokenForUsername("@test1:example.com"), "The restore token should not have been deleted.")
|
||||||
XCTAssertNil(keychain.accessTokenForUsername("@test2:example.com"), "The access token should have been deleted.")
|
XCTAssertNil(keychain.restoreTokenForUsername("@test2:example.com"), "The restore token should have been deleted.")
|
||||||
XCTAssertNotNil(keychain.accessTokenForUsername("@test3:example.com"), "The access token should not have been deleted.")
|
XCTAssertNotNil(keychain.restoreTokenForUsername("@test3:example.com"), "The restore token should not have been deleted.")
|
||||||
XCTAssertNotNil(keychain.accessTokenForUsername("@test4:example.com"), "The access token should not have been deleted.")
|
XCTAssertNotNil(keychain.restoreTokenForUsername("@test4:example.com"), "The restore token should not have been deleted.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
Perform password login using the Rust authentication service.
|
||||||
+1
-1
@@ -31,7 +31,7 @@ include:
|
|||||||
packages:
|
packages:
|
||||||
MatrixRustSDK:
|
MatrixRustSDK:
|
||||||
url: https://github.com/matrix-org/matrix-rust-components-swift
|
url: https://github.com/matrix-org/matrix-rust-components-swift
|
||||||
exactVersion: 1.0.11-alpha
|
exactVersion: 1.0.12-alpha
|
||||||
# path: ../matrix-rust-components-swift
|
# path: ../matrix-rust-components-swift
|
||||||
DesignKit:
|
DesignKit:
|
||||||
path: ./
|
path: ./
|
||||||
|
|||||||
Reference in New Issue
Block a user