mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Handle waiting list error. (#1165)
This commit is contained in:
@@ -119,9 +119,11 @@
|
|||||||
2C5E832434EE94E21AB3B238 /* EmojiPickerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */; };
|
2C5E832434EE94E21AB3B238 /* EmojiPickerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */; };
|
||||||
2CA6ABBC9A88EB89EA52FCCB /* ConfettiScene.scn in Resources */ = {isa = PBXBuildFile; fileRef = B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */; };
|
2CA6ABBC9A88EB89EA52FCCB /* ConfettiScene.scn in Resources */ = {isa = PBXBuildFile; fileRef = B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */; };
|
||||||
2CB6787E25B11711518E9588 /* OnboardingCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6281B199D8A8F0892490C2E /* OnboardingCoordinator.swift */; };
|
2CB6787E25B11711518E9588 /* OnboardingCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6281B199D8A8F0892490C2E /* OnboardingCoordinator.swift */; };
|
||||||
|
2DA90E38FF4E696825810C1A /* WaitlistScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB08484CD5D77C9BF97AA78 /* WaitlistScreenUITests.swift */; };
|
||||||
2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */; };
|
2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */; };
|
||||||
2E8C6672D0EE7D5B1BEDB8E2 /* ServerConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */; };
|
2E8C6672D0EE7D5B1BEDB8E2 /* ServerConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */; };
|
||||||
2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086B997409328F091EBA43CE /* RoomScreenUITests.swift */; };
|
2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086B997409328F091EBA43CE /* RoomScreenUITests.swift */; };
|
||||||
|
2F66701B15657A87B4AC3A0A /* WaitlistScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CE2B7AD979BDEE09FEDB08 /* WaitlistScreenModels.swift */; };
|
||||||
2F94054F50E312AF30BE07F3 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B21E611DADDEF00307E7AC /* String.swift */; };
|
2F94054F50E312AF30BE07F3 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B21E611DADDEF00307E7AC /* String.swift */; };
|
||||||
308BD9343B95657FAA583FB7 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD5B074D7DD44AF4C58BB6 /* SwiftState */; };
|
308BD9343B95657FAA583FB7 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD5B074D7DD44AF4C58BB6 /* SwiftState */; };
|
||||||
3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; };
|
3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; };
|
||||||
@@ -317,6 +319,7 @@
|
|||||||
7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */; };
|
7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */; };
|
||||||
7BB31E67648CF32D2AB5E502 /* RoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */; };
|
7BB31E67648CF32D2AB5E502 /* RoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */; };
|
||||||
7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; };
|
7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; };
|
||||||
|
7C384A8E54A4B60A14CDE8E5 /* WaitlistScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */; };
|
||||||
7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */; };
|
7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */; };
|
||||||
7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */; };
|
7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */; };
|
||||||
7E3C34BC10936AD4F77975F4 /* EmojiMartJSONLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39001365B76B89983FDB7AD8 /* EmojiMartJSONLoader.swift */; };
|
7E3C34BC10936AD4F77975F4 /* EmojiMartJSONLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39001365B76B89983FDB7AD8 /* EmojiMartJSONLoader.swift */; };
|
||||||
@@ -407,6 +410,7 @@
|
|||||||
9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; };
|
9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; };
|
||||||
9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */; };
|
9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92390F9FA98255440A6BF5F8 /* OIDCAuthenticationPresenter.swift */; };
|
||||||
9AC5F8142413862A9E3A2D98 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; };
|
9AC5F8142413862A9E3A2D98 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; };
|
||||||
|
9AFEE46B03B7E995B3E1A53D /* WaitlistScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80C4927D09099497233E9980 /* WaitlistScreen.swift */; };
|
||||||
9B582B3EEFEA615D4A6FBF1A /* TimelineReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351E89CE2ED9B73C5CC47955 /* TimelineReactionsView.swift */; };
|
9B582B3EEFEA615D4A6FBF1A /* TimelineReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351E89CE2ED9B73C5CC47955 /* TimelineReactionsView.swift */; };
|
||||||
9B872FF37DBE6BE054903831 /* MediaUploadPreviewScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */; };
|
9B872FF37DBE6BE054903831 /* MediaUploadPreviewScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */; };
|
||||||
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
|
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
|
||||||
@@ -501,6 +505,7 @@
|
|||||||
B6DA66EFC13A90846B625836 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 91DE43B8815918E590912DDA /* InfoPlist.strings */; };
|
B6DA66EFC13A90846B625836 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 91DE43B8815918E590912DDA /* InfoPlist.strings */; };
|
||||||
B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */; };
|
B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */; };
|
||||||
B6EC2148FA5443C9289BEEBA /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */; };
|
B6EC2148FA5443C9289BEEBA /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */; };
|
||||||
|
B717A820BE02C6FE2CB53F6E /* WaitlistScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B697816AF93DA06EC58C5D70 /* WaitlistScreenViewModelProtocol.swift */; };
|
||||||
B721125D17A0BA86794F29FB /* MockServerSelectionScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E057FB1F07A5C201C89061 /* MockServerSelectionScreenState.swift */; };
|
B721125D17A0BA86794F29FB /* MockServerSelectionScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E057FB1F07A5C201C89061 /* MockServerSelectionScreenState.swift */; };
|
||||||
B796A25F282C0A340D1B9C12 /* ImageRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B5EDCD05D50BA9B815C66C /* ImageRoomTimelineItemContent.swift */; };
|
B796A25F282C0A340D1B9C12 /* ImageRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B5EDCD05D50BA9B815C66C /* ImageRoomTimelineItemContent.swift */; };
|
||||||
B80C4FABB5529DF12436FFDA /* AppIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 16DC8C5B2991724903F1FA6A /* AppIcon.pdf */; };
|
B80C4FABB5529DF12436FFDA /* AppIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 16DC8C5B2991724903F1FA6A /* AppIcon.pdf */; };
|
||||||
@@ -570,6 +575,7 @@
|
|||||||
CE7148E80F09B7305E026AC6 /* OnboardingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1198B925F4A88DA74083662 /* OnboardingViewModel.swift */; };
|
CE7148E80F09B7305E026AC6 /* OnboardingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1198B925F4A88DA74083662 /* OnboardingViewModel.swift */; };
|
||||||
CE9530A4CA661E090635C2F2 /* NotificationItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */; };
|
CE9530A4CA661E090635C2F2 /* NotificationItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */; };
|
||||||
CEB8FB1269DE20536608B957 /* LoginMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41FABA2B0AEF4389986495 /* LoginMode.swift */; };
|
CEB8FB1269DE20536608B957 /* LoginMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41FABA2B0AEF4389986495 /* LoginMode.swift */; };
|
||||||
|
CF3827071B0BC9638BD44F5D /* WaitlistScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB58EF0176D4CFB1040DA22 /* WaitlistScreenViewModel.swift */; };
|
||||||
CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D316BB02636AF2174F2580E6 /* SoftLogoutScreenViewModelProtocol.swift */; };
|
CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D316BB02636AF2174F2580E6 /* SoftLogoutScreenViewModelProtocol.swift */; };
|
||||||
CF82143AA4A4F7BD11D22946 /* RoomTimelineViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACB6C5E4950B6C9842F35A38 /* RoomTimelineViewProvider.swift */; };
|
CF82143AA4A4F7BD11D22946 /* RoomTimelineViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACB6C5E4950B6C9842F35A38 /* RoomTimelineViewProvider.swift */; };
|
||||||
D02AA6208C7ACB9BE6332394 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
|
D02AA6208C7ACB9BE6332394 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
|
||||||
@@ -689,6 +695,7 @@
|
|||||||
FA5A7E32B1920FCB4EEDC1BA /* RoomDetailsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */; };
|
FA5A7E32B1920FCB4EEDC1BA /* RoomDetailsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */; };
|
||||||
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; };
|
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; };
|
||||||
FB53CD9B74A15B3B94F9F788 /* CreateRoomModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B849D2FF2CC12BA411A1651 /* CreateRoomModels.swift */; };
|
FB53CD9B74A15B3B94F9F788 /* CreateRoomModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B849D2FF2CC12BA411A1651 /* CreateRoomModels.swift */; };
|
||||||
|
FB9A1DD83EF641A75ABBCE69 /* WaitlistScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C796FC1DFDBCDD5573D0360F /* WaitlistScreenViewModelTests.swift */; };
|
||||||
FBCCF1EA25A071324FCD8544 /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7023EB4F3B7C7D1FBA68638B /* TimelineItemDebugView.swift */; };
|
FBCCF1EA25A071324FCD8544 /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7023EB4F3B7C7D1FBA68638B /* TimelineItemDebugView.swift */; };
|
||||||
FBF09B6C900415800DDF2A21 /* EmojiProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */; };
|
FBF09B6C900415800DDF2A21 /* EmojiProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */; };
|
||||||
FC10228E73323BDC09526F97 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
|
FC10228E73323BDC09526F97 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
|
||||||
@@ -774,6 +781,7 @@
|
|||||||
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = "<group>"; };
|
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = "<group>"; };
|
||||||
0960A7F5C1B0B6679BDF26F9 /* ElementToggleStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementToggleStyle.swift; sourceTree = "<group>"; };
|
0960A7F5C1B0B6679BDF26F9 /* ElementToggleStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementToggleStyle.swift; sourceTree = "<group>"; };
|
||||||
099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = "<group>"; };
|
099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = "<group>"; };
|
||||||
|
09CE2B7AD979BDEE09FEDB08 /* WaitlistScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenModels.swift; sourceTree = "<group>"; };
|
||||||
0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
|
0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIndicatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIndicatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineSenderAvatarView.swift; sourceTree = "<group>"; };
|
0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineSenderAvatarView.swift; sourceTree = "<group>"; };
|
||||||
@@ -799,6 +807,7 @@
|
|||||||
1222DB76B917EB8A55365BA5 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
1222DB76B917EB8A55365BA5 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
||||||
127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = "<group>"; };
|
127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = "<group>"; };
|
||||||
127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = "<group>"; };
|
127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = "<group>"; };
|
||||||
|
12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = "<group>"; };
|
1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = "<group>"; };
|
||||||
130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = "<group>"; };
|
130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = "<group>"; };
|
||||||
13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
@@ -822,6 +831,7 @@
|
|||||||
1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+Untranslated.swift"; sourceTree = "<group>"; };
|
1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+Untranslated.swift"; sourceTree = "<group>"; };
|
||||||
1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStaticMap.swift; sourceTree = "<group>"; };
|
1A4D29F2683F5772AC72406F /* MapTilerStaticMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStaticMap.swift; sourceTree = "<group>"; };
|
||||||
1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURITests.swift; sourceTree = "<group>"; };
|
1A7ED2EF5BDBAD2A7DBC4636 /* GeoURITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURITests.swift; sourceTree = "<group>"; };
|
||||||
|
1AB58EF0176D4CFB1040DA22 /* WaitlistScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
1ABDE6F66532CBEB0E016F94 /* RoomProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyMock.swift; sourceTree = "<group>"; };
|
1ABDE6F66532CBEB0E016F94 /* RoomProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyMock.swift; sourceTree = "<group>"; };
|
||||||
1B1EE0908B2BF9212436AD3E /* SessionVerificationScreenStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenStateMachine.swift; sourceTree = "<group>"; };
|
1B1EE0908B2BF9212436AD3E /* SessionVerificationScreenStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenStateMachine.swift; sourceTree = "<group>"; };
|
||||||
1B2AC540DE619B36832A5DB5 /* LocationRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItem.swift; sourceTree = "<group>"; };
|
1B2AC540DE619B36832A5DB5 /* LocationRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
@@ -1062,6 +1072,7 @@
|
|||||||
7DDBF99755A9008CF8C8499E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
7DDBF99755A9008CF8C8499E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||||
7DDF49CEBC0DFC59C308335F /* RoomMemberDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
7DDF49CEBC0DFC59C308335F /* RoomMemberDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryServiceProtocol.swift; sourceTree = "<group>"; };
|
7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoveryServiceProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
80C4927D09099497233E9980 /* WaitlistScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreen.swift; sourceTree = "<group>"; };
|
||||||
818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickerRoomTimelineItem.swift; sourceTree = "<group>"; };
|
818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickerRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
818CBE6249ED6E8FC30E8366 /* ViewModelContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModelContext.swift; sourceTree = "<group>"; };
|
818CBE6249ED6E8FC30E8366 /* ViewModelContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModelContext.swift; sourceTree = "<group>"; };
|
||||||
8196D64EB9CF2AF1F43E4ED1 /* AnalyticsPromptScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
8196D64EB9CF2AF1F43E4ED1 /* AnalyticsPromptScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
@@ -1198,6 +1209,7 @@
|
|||||||
B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = "<group>"; };
|
B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = "<group>"; };
|
B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = "<group>"; };
|
||||||
B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = "<group>"; };
|
B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
|
B697816AF93DA06EC58C5D70 /* WaitlistScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
B6E89E530A8E92EC44301CA1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; };
|
B6E89E530A8E92EC44301CA1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; };
|
||||||
B7AE92E7BFF71797BDE1D261 /* MapTilerStyleBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilder.swift; sourceTree = "<group>"; };
|
B7AE92E7BFF71797BDE1D261 /* MapTilerStyleBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilder.swift; sourceTree = "<group>"; };
|
||||||
B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsSignalling.swift; sourceTree = "<group>"; };
|
B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsSignalling.swift; sourceTree = "<group>"; };
|
||||||
@@ -1249,6 +1261,7 @@
|
|||||||
C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomList.swift; sourceTree = "<group>"; };
|
C7661EFFCAA307A97D71132A /* HomeScreenRoomList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomList.swift; sourceTree = "<group>"; };
|
||||||
C789E7BFC066CF39B8AE0974 /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
|
C789E7BFC066CF39B8AE0974 /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
|
||||||
|
C796FC1DFDBCDD5573D0360F /* WaitlistScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
C830A64609CBD152F06E0457 /* NotificationConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationConstants.swift; sourceTree = "<group>"; };
|
C830A64609CBD152F06E0457 /* NotificationConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationConstants.swift; sourceTree = "<group>"; };
|
||||||
C843CF833BF6485B64AC87E1 /* AppRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouter.swift; sourceTree = "<group>"; };
|
C843CF833BF6485B64AC87E1 /* AppRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouter.swift; sourceTree = "<group>"; };
|
||||||
C8F2A7A4E3F5060F52ACFFB0 /* RedactedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineView.swift; sourceTree = "<group>"; };
|
C8F2A7A4E3F5060F52ACFFB0 /* RedactedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
@@ -1335,6 +1348,7 @@
|
|||||||
E9DFC0FBA0FC6FC4DC0FC9FC /* NSESettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESettings.swift; sourceTree = "<group>"; };
|
E9DFC0FBA0FC6FC4DC0FC9FC /* NSESettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESettings.swift; sourceTree = "<group>"; };
|
||||||
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = "<group>"; };
|
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = "<group>"; };
|
||||||
EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsViewModelTests.swift; sourceTree = "<group>"; };
|
EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
|
ECB08484CD5D77C9BF97AA78 /* WaitlistScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
ECD5FCBA169B6A82F501CA1B /* AnalyticsSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
ECD5FCBA169B6A82F501CA1B /* AnalyticsSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModel.swift; sourceTree = "<group>"; };
|
ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = "<group>"; };
|
ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = "<group>"; };
|
||||||
@@ -2382,6 +2396,7 @@
|
|||||||
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */,
|
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */,
|
||||||
2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */,
|
2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */,
|
||||||
BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */,
|
BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */,
|
||||||
|
C796FC1DFDBCDD5573D0360F /* WaitlistScreenViewModelTests.swift */,
|
||||||
53280D2292E6C9C7821773FD /* UserSession */,
|
53280D2292E6C9C7821773FD /* UserSession */,
|
||||||
70C5B842301AC281DF374E41 /* Extensions */,
|
70C5B842301AC281DF374E41 /* Extensions */,
|
||||||
7583EAC171059A86B767209F /* MediaProvider */,
|
7583EAC171059A86B767209F /* MediaProvider */,
|
||||||
@@ -2706,6 +2721,7 @@
|
|||||||
55F30E764BED111C81739844 /* SoftLogoutUITests.swift */,
|
55F30E764BED111C81739844 /* SoftLogoutUITests.swift */,
|
||||||
DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */,
|
DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */,
|
||||||
F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */,
|
F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */,
|
||||||
|
ECB08484CD5D77C9BF97AA78 /* WaitlistScreenUITests.swift */,
|
||||||
);
|
);
|
||||||
path = Sources;
|
path = Sources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -2744,6 +2760,14 @@
|
|||||||
path = Templates;
|
path = Templates;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
9F4A1E90C924DE7954BA5005 /* View */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
80C4927D09099497233E9980 /* WaitlistScreen.swift */,
|
||||||
|
);
|
||||||
|
path = View;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9FD8D798D879069243A7E7F7 /* View */ = {
|
9FD8D798D879069243A7E7F7 /* View */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -2804,6 +2828,18 @@
|
|||||||
path = UnitTests;
|
path = UnitTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
A67C1933D33AAC64642E9A82 /* WaitlistScreen */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */,
|
||||||
|
09CE2B7AD979BDEE09FEDB08 /* WaitlistScreenModels.swift */,
|
||||||
|
1AB58EF0176D4CFB1040DA22 /* WaitlistScreenViewModel.swift */,
|
||||||
|
B697816AF93DA06EC58C5D70 /* WaitlistScreenViewModelProtocol.swift */,
|
||||||
|
9F4A1E90C924DE7954BA5005 /* View */,
|
||||||
|
);
|
||||||
|
path = WaitlistScreen;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
A78C2592419CA4C76FBA8FD2 /* Application */ = {
|
A78C2592419CA4C76FBA8FD2 /* Application */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -3296,6 +3332,7 @@
|
|||||||
BA1938A75D8C780F694CEB62 /* ServerConfirmationScreen */,
|
BA1938A75D8C780F694CEB62 /* ServerConfirmationScreen */,
|
||||||
2D0D49B0533C4C2EB889BF3A /* ServerSelectionScreen */,
|
2D0D49B0533C4C2EB889BF3A /* ServerSelectionScreen */,
|
||||||
5B2C520AB9863B8CBC8EB3CA /* SoftLogoutScreen */,
|
5B2C520AB9863B8CBC8EB3CA /* SoftLogoutScreen */,
|
||||||
|
A67C1933D33AAC64642E9A82 /* WaitlistScreen */,
|
||||||
);
|
);
|
||||||
path = Authentication;
|
path = Authentication;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -3905,6 +3942,7 @@
|
|||||||
04F17DE71A50206336749BAC /* UserPreferenceTests.swift in Sources */,
|
04F17DE71A50206336749BAC /* UserPreferenceTests.swift in Sources */,
|
||||||
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */,
|
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */,
|
||||||
99F8DA4CCC6772EE5FE68E24 /* ViewModelContext.swift in Sources */,
|
99F8DA4CCC6772EE5FE68E24 /* ViewModelContext.swift in Sources */,
|
||||||
|
FB9A1DD83EF641A75ABBCE69 /* WaitlistScreenViewModelTests.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -4385,6 +4423,11 @@
|
|||||||
1A83DD22F3E6F76B13B6E2F9 /* VideoRoomTimelineItemContent.swift in Sources */,
|
1A83DD22F3E6F76B13B6E2F9 /* VideoRoomTimelineItemContent.swift in Sources */,
|
||||||
64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */,
|
64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */,
|
||||||
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */,
|
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */,
|
||||||
|
9AFEE46B03B7E995B3E1A53D /* WaitlistScreen.swift in Sources */,
|
||||||
|
7C384A8E54A4B60A14CDE8E5 /* WaitlistScreenCoordinator.swift in Sources */,
|
||||||
|
2F66701B15657A87B4AC3A0A /* WaitlistScreenModels.swift in Sources */,
|
||||||
|
CF3827071B0BC9638BD44F5D /* WaitlistScreenViewModel.swift in Sources */,
|
||||||
|
B717A820BE02C6FE2CB53F6E /* WaitlistScreenViewModelProtocol.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -4425,6 +4468,7 @@
|
|||||||
54AE8860D668AFD96E7E177B /* UITestsScreenIdentifier.swift in Sources */,
|
54AE8860D668AFD96E7E177B /* UITestsScreenIdentifier.swift in Sources */,
|
||||||
84EFCB95F9DA2979C8042B26 /* UITestsSignalling.swift in Sources */,
|
84EFCB95F9DA2979C8042B26 /* UITestsSignalling.swift in Sources */,
|
||||||
B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */,
|
B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */,
|
||||||
|
2DA90E38FF4E696825810C1A /* WaitlistScreenUITests.swift in Sources */,
|
||||||
588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */,
|
588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
@@ -14,3 +14,9 @@
|
|||||||
"soft_logout_clear_data_submit" = "Clear all data";
|
"soft_logout_clear_data_submit" = "Clear all data";
|
||||||
"soft_logout_clear_data_dialog_title" = "Clear data";
|
"soft_logout_clear_data_dialog_title" = "Clear data";
|
||||||
"soft_logout_clear_data_dialog_content" = "Clear all data currently stored on this device?\nSign in again to access your account data and messages.";
|
"soft_logout_clear_data_dialog_content" = "Clear all data currently stored on this device?\nSign in again to access your account data and messages.";
|
||||||
|
|
||||||
|
"common_refreshing" = "Refreshing…";
|
||||||
|
"screen_waitlist_title" = "You're on the waitlist!";
|
||||||
|
"screen_waitlist_title_success" = "You're in!";
|
||||||
|
"screen_waitlist_message" = "There's a high demand for %1$@ on %2$@ at the moment. Come back to the app in a few days and try again.\n\nThanks for your patience!";
|
||||||
|
"screen_waitlist_message_success" = "Welcome to %1$@";
|
||||||
|
|||||||
@@ -291,10 +291,10 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
|||||||
displayName = name
|
displayName = name
|
||||||
}
|
}
|
||||||
|
|
||||||
let credentials = SoftLogoutScreenCredentials(userId: userSession.userID,
|
let credentials = SoftLogoutScreenCredentials(userID: userSession.userID,
|
||||||
homeserverName: userSession.homeserver,
|
homeserverName: userSession.homeserver,
|
||||||
userDisplayName: displayName,
|
userDisplayName: displayName,
|
||||||
deviceId: userSession.deviceID)
|
deviceID: userSession.deviceID)
|
||||||
|
|
||||||
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore)
|
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore)
|
||||||
_ = await authenticationService.configure(for: userSession.homeserver)
|
_ = await authenticationService.configure(for: userSession.homeserver)
|
||||||
|
|||||||
@@ -10,6 +10,22 @@ import Foundation
|
|||||||
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
|
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
|
||||||
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
|
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||||
public enum UntranslatedL10n {
|
public enum UntranslatedL10n {
|
||||||
|
/// Refreshing…
|
||||||
|
public static var commonRefreshing: String { return UntranslatedL10n.tr("Untranslated", "common_refreshing") }
|
||||||
|
/// There's a high demand for %1$@ on %2$@ at the moment. Come back to the app in a few days and try again.
|
||||||
|
///
|
||||||
|
/// Thanks for your patience!
|
||||||
|
public static func screenWaitlistMessage(_ p1: Any, _ p2: Any) -> String {
|
||||||
|
return UntranslatedL10n.tr("Untranslated", "screen_waitlist_message", String(describing: p1), String(describing: p2))
|
||||||
|
}
|
||||||
|
/// Welcome to %1$@
|
||||||
|
public static func screenWaitlistMessageSuccess(_ p1: Any) -> String {
|
||||||
|
return UntranslatedL10n.tr("Untranslated", "screen_waitlist_message_success", String(describing: p1))
|
||||||
|
}
|
||||||
|
/// You're on the waitlist!
|
||||||
|
public static var screenWaitlistTitle: String { return UntranslatedL10n.tr("Untranslated", "screen_waitlist_title") }
|
||||||
|
/// You're in!
|
||||||
|
public static var screenWaitlistTitleSuccess: String { return UntranslatedL10n.tr("Untranslated", "screen_waitlist_title_success") }
|
||||||
/// Clear all data currently stored on this device?
|
/// Clear all data currently stored on this device?
|
||||||
/// Sign in again to access your account data and messages.
|
/// Sign in again to access your account data and messages.
|
||||||
public static var softLogoutClearDataDialogContent: String { return UntranslatedL10n.tr("Untranslated", "soft_logout_clear_data_dialog_content") }
|
public static var softLogoutClearDataDialogContent: String { return UntranslatedL10n.tr("Untranslated", "soft_logout_clear_data_dialog_content") }
|
||||||
|
|||||||
@@ -168,12 +168,33 @@ class AuthenticationCoordinator: CoordinatorProtocol {
|
|||||||
case .configuredForOIDC:
|
case .configuredForOIDC:
|
||||||
// Pop back to the confirmation screen for OIDC login to continue.
|
// Pop back to the confirmation screen for OIDC login to continue.
|
||||||
navigationStackCoordinator.pop(animated: false)
|
navigationStackCoordinator.pop(animated: false)
|
||||||
|
case .isOnWaitlist(let credentials):
|
||||||
|
showWaitlistScreen(for: credentials)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationStackCoordinator.push(coordinator)
|
navigationStackCoordinator.push(coordinator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func showWaitlistScreen(for credentials: WaitlistScreenCredentials) {
|
||||||
|
let parameters = WaitlistScreenCoordinatorParameters(credentials: credentials,
|
||||||
|
authenticationService: authenticationService)
|
||||||
|
let coordinator = WaitlistScreenCoordinator(parameters: parameters)
|
||||||
|
|
||||||
|
coordinator.actions.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
|
switch action {
|
||||||
|
case .signedIn(let userSession):
|
||||||
|
userHasSignedIn(userSession: userSession)
|
||||||
|
case .cancel:
|
||||||
|
navigationStackCoordinator.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
navigationStackCoordinator.push(coordinator)
|
||||||
|
}
|
||||||
|
|
||||||
private func userHasSignedIn(userSession: UserSessionProtocol) {
|
private func userHasSignedIn(userSession: UserSessionProtocol) {
|
||||||
showAnalyticsPromptIfNeeded { [weak self] in
|
showAnalyticsPromptIfNeeded { [weak self] in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ enum LoginScreenCoordinatorAction {
|
|||||||
case configuredForOIDC
|
case configuredForOIDC
|
||||||
/// Login was successful.
|
/// Login was successful.
|
||||||
case signedIn(UserSessionProtocol)
|
case signedIn(UserSessionProtocol)
|
||||||
|
/// The user's request to login failed due to being on the proxy waitlist.
|
||||||
|
case isOnWaitlist(WaitlistScreenCredentials)
|
||||||
}
|
}
|
||||||
|
|
||||||
final class LoginScreenCoordinator: CoordinatorProtocol {
|
final class LoginScreenCoordinator: CoordinatorProtocol {
|
||||||
@@ -117,13 +119,22 @@ final class LoginScreenCoordinator: CoordinatorProtocol {
|
|||||||
switch await authenticationService.login(username: username,
|
switch await authenticationService.login(username: username,
|
||||||
password: password,
|
password: password,
|
||||||
initialDeviceName: UIDevice.current.initialDeviceName,
|
initialDeviceName: UIDevice.current.initialDeviceName,
|
||||||
deviceId: nil) {
|
deviceID: nil) {
|
||||||
case .success(let userSession):
|
case .success(let userSession):
|
||||||
callback?(.signedIn(userSession))
|
callback?(.signedIn(userSession))
|
||||||
stopLoading()
|
stopLoading()
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
stopLoading()
|
stopLoading()
|
||||||
handleError(error)
|
switch error {
|
||||||
|
case .isOnWaitlist:
|
||||||
|
callback?(.isOnWaitlist(.init(username: username,
|
||||||
|
password: password,
|
||||||
|
initialDeviceName: UIDevice.current.initialDeviceName,
|
||||||
|
deviceID: nil,
|
||||||
|
homeserver: authenticationService.homeserver.value)))
|
||||||
|
default:
|
||||||
|
handleError(error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -31,10 +31,10 @@ enum MockSoftLogoutScreenState: String, CaseIterable {
|
|||||||
|
|
||||||
/// Generate the view struct for the screen state.
|
/// Generate the view struct for the screen state.
|
||||||
@MainActor var viewModel: SoftLogoutScreenViewModel {
|
@MainActor var viewModel: SoftLogoutScreenViewModel {
|
||||||
let credentials = SoftLogoutScreenCredentials(userId: "@mock:matrix.org",
|
let credentials = SoftLogoutScreenCredentials(userID: "@mock:matrix.org",
|
||||||
homeserverName: "matrix.org",
|
homeserverName: "matrix.org",
|
||||||
userDisplayName: "mock",
|
userDisplayName: "mock",
|
||||||
deviceId: nil)
|
deviceID: nil)
|
||||||
switch self {
|
switch self {
|
||||||
case .emptyPassword:
|
case .emptyPassword:
|
||||||
return SoftLogoutScreenViewModel(credentials: credentials,
|
return SoftLogoutScreenViewModel(credentials: credentials,
|
||||||
|
|||||||
+2
-2
@@ -108,7 +108,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
|
|||||||
|
|
||||||
/// Login with the supplied username and password.
|
/// Login with the supplied username and password.
|
||||||
@MainActor private func login(withPassword password: String) {
|
@MainActor private func login(withPassword password: String) {
|
||||||
let username = parameters.credentials.userId
|
let username = parameters.credentials.userID
|
||||||
|
|
||||||
startLoading()
|
startLoading()
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
|
|||||||
switch await authenticationService.login(username: username,
|
switch await authenticationService.login(username: username,
|
||||||
password: password,
|
password: password,
|
||||||
initialDeviceName: UIDevice.current.initialDeviceName,
|
initialDeviceName: UIDevice.current.initialDeviceName,
|
||||||
deviceId: parameters.credentials.deviceId) {
|
deviceID: parameters.credentials.deviceID) {
|
||||||
case .success(let userSession):
|
case .success(let userSession):
|
||||||
callback?(.signedIn(userSession))
|
callback?(.signedIn(userSession))
|
||||||
stopLoading()
|
stopLoading()
|
||||||
|
|||||||
+2
-2
@@ -17,10 +17,10 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct SoftLogoutScreenCredentials {
|
struct SoftLogoutScreenCredentials {
|
||||||
let userId: String
|
let userID: String
|
||||||
let homeserverName: String
|
let homeserverName: String
|
||||||
let userDisplayName: String
|
let userDisplayName: String
|
||||||
let deviceId: String?
|
let deviceID: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SoftLogoutScreenViewModelAction: CustomStringConvertible {
|
enum SoftLogoutScreenViewModelAction: CustomStringConvertible {
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ struct SoftLogoutScreen: View {
|
|||||||
.foregroundColor(.compound.textPrimary)
|
.foregroundColor(.compound.textPrimary)
|
||||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.title)
|
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.title)
|
||||||
|
|
||||||
Text(UntranslatedL10n.softLogoutSigninNotice(context.viewState.credentials.homeserverName, context.viewState.credentials.userDisplayName, context.viewState.credentials.userId))
|
Text(UntranslatedL10n.softLogoutSigninNotice(context.viewState.credentials.homeserverName, context.viewState.credentials.userDisplayName, context.viewState.credentials.userID))
|
||||||
.font(.compound.bodyLG)
|
.font(.compound.bodyLG)
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.leading)
|
||||||
.foregroundColor(.compound.textPrimary)
|
.foregroundColor(.compound.textPrimary)
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct WaitlistScreen: View {
|
||||||
|
@ObservedObject var context: WaitlistScreenViewModel.Context
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
FullscreenDialog(topPadding: UIConstants.iconTopPaddingToNavigationBar) {
|
||||||
|
header
|
||||||
|
} bottomContent: {
|
||||||
|
buttons
|
||||||
|
}
|
||||||
|
.background()
|
||||||
|
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
|
||||||
|
.navigationBarBackButtonHidden()
|
||||||
|
.toolbar { toolbar }
|
||||||
|
.toolbar(.visible, for: .navigationBar) // Layout consistency in all states.
|
||||||
|
.overlay {
|
||||||
|
EffectsView(effect: context.viewState.isWaiting ? .none : .confetti)
|
||||||
|
.ignoresSafeArea()
|
||||||
|
.allowsHitTesting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main content of the view to be shown in a scroll view.
|
||||||
|
var header: some View {
|
||||||
|
VStack(spacing: 8) {
|
||||||
|
AuthenticationIconImage(image: Image(systemName: context.viewState.iconSymbolName))
|
||||||
|
.fontWeight(.semibold)
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
|
||||||
|
Text(context.viewState.title)
|
||||||
|
.font(.compound.headingMDBold)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.foregroundColor(.compound.textPrimary)
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
|
||||||
|
Text(context.viewState.message)
|
||||||
|
.font(.compound.bodyMD)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.foregroundColor(.compound.textSecondary)
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The action buttons shown at the bottom of the view.
|
||||||
|
@ViewBuilder
|
||||||
|
var buttons: some View {
|
||||||
|
if let userSession = context.viewState.userSession {
|
||||||
|
Button { context.send(viewAction: .continue(userSession)) } label: {
|
||||||
|
Text(L10n.actionContinue)
|
||||||
|
}
|
||||||
|
.buttonStyle(.elementAction(.xLarge))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ToolbarContentBuilder
|
||||||
|
var toolbar: some ToolbarContent {
|
||||||
|
if context.viewState.isWaiting {
|
||||||
|
ToolbarItem(placement: .cancellationAction) {
|
||||||
|
Button(L10n.actionCancel) {
|
||||||
|
context.send(viewAction: .cancel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Previews
|
||||||
|
|
||||||
|
struct WaitlistScreen_Previews: PreviewProvider {
|
||||||
|
static let viewModel = WaitlistScreenViewModel(homeserver: .mockMatrixDotOrg)
|
||||||
|
static let successViewModel = {
|
||||||
|
let viewModel = WaitlistScreenViewModel(homeserver: .mockMatrixDotOrg)
|
||||||
|
viewModel.update(userSession: MockUserSession(clientProxy: MockClientProxy(userID: "@alice:matrix.org"),
|
||||||
|
mediaProvider: MockMediaProvider()))
|
||||||
|
return viewModel
|
||||||
|
}()
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
NavigationStack {
|
||||||
|
WaitlistScreen(context: viewModel.context)
|
||||||
|
}
|
||||||
|
.previewDisplayName("Waiting")
|
||||||
|
|
||||||
|
NavigationStack {
|
||||||
|
WaitlistScreen(context: successViewModel.context)
|
||||||
|
}
|
||||||
|
.previewDisplayName("Success")
|
||||||
|
}
|
||||||
|
}
|
||||||
+128
@@ -0,0 +1,128 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct WaitlistScreenCoordinatorParameters {
|
||||||
|
/// The credentials for the login.
|
||||||
|
let credentials: WaitlistScreenCredentials
|
||||||
|
/// The service used to authenticate the user.
|
||||||
|
let authenticationService: AuthenticationServiceProxyProtocol
|
||||||
|
/// The service locator for the screen.
|
||||||
|
var userIndicatorController: UserIndicatorControllerProtocol = ServiceLocator.shared.userIndicatorController
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WaitlistScreenCoordinatorAction {
|
||||||
|
/// Login was successful after a retry attempt.
|
||||||
|
case signedIn(UserSessionProtocol)
|
||||||
|
/// The user would like to try sign in another way.
|
||||||
|
case cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
final class WaitlistScreenCoordinator: CoordinatorProtocol {
|
||||||
|
private let parameters: WaitlistScreenCoordinatorParameters
|
||||||
|
private var viewModel: WaitlistScreenViewModelProtocol
|
||||||
|
private let actionsSubject: PassthroughSubject<WaitlistScreenCoordinatorAction, Never> = .init()
|
||||||
|
private var cancellables: Set<AnyCancellable> = .init()
|
||||||
|
private var refreshCancellable: AnyCancellable?
|
||||||
|
|
||||||
|
var actions: AnyPublisher<WaitlistScreenCoordinatorAction, Never> {
|
||||||
|
actionsSubject.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(parameters: WaitlistScreenCoordinatorParameters) {
|
||||||
|
self.parameters = parameters
|
||||||
|
|
||||||
|
viewModel = WaitlistScreenViewModel(homeserver: parameters.credentials.homeserver)
|
||||||
|
|
||||||
|
refreshCancellable = NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)
|
||||||
|
.sink { [weak self] _ in
|
||||||
|
self?.refresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func start() {
|
||||||
|
viewModel.actions.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
|
switch action {
|
||||||
|
case .cancel:
|
||||||
|
actionsSubject.send(.cancel)
|
||||||
|
case .continue(let userSession):
|
||||||
|
actionsSubject.send(.signedIn(userSession))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toPresentable() -> AnyView {
|
||||||
|
AnyView(WaitlistScreen(context: viewModel.context))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Private
|
||||||
|
|
||||||
|
/// Refresh the screen by retrying login to see if the waitlist has opened up.
|
||||||
|
private func refresh() {
|
||||||
|
guard parameters.credentials.homeserver == parameters.authenticationService.homeserver.value else {
|
||||||
|
MXLog.warning("Homeserver configuration changed.")
|
||||||
|
actionsSubject.send(.cancel)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
showRefreshIndicator()
|
||||||
|
|
||||||
|
Task {
|
||||||
|
switch await parameters.authenticationService.login(username: parameters.credentials.username,
|
||||||
|
password: parameters.credentials.password,
|
||||||
|
initialDeviceName: parameters.credentials.initialDeviceName,
|
||||||
|
deviceID: parameters.credentials.deviceID) {
|
||||||
|
case .success(let userSession):
|
||||||
|
hideRefreshIndicator()
|
||||||
|
refreshCancellable = nil
|
||||||
|
viewModel.update(userSession: userSession)
|
||||||
|
case .failure(.isOnWaitlist):
|
||||||
|
hideRefreshIndicator() // Nothing to do, still waiting for availability.
|
||||||
|
case .failure(.invalidCredentials):
|
||||||
|
hideRefreshIndicator()
|
||||||
|
actionsSubject.send(.cancel)
|
||||||
|
case .failure:
|
||||||
|
hideRefreshIndicator()
|
||||||
|
showFailureIndicator()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static let refreshIndicatorID = "WaitlistCoordinatorRefresh"
|
||||||
|
private static let failureIndicatorID = "WaitlistCoordinatorFailure"
|
||||||
|
|
||||||
|
private func showRefreshIndicator() {
|
||||||
|
parameters.userIndicatorController.submitIndicator(UserIndicator(id: Self.refreshIndicatorID,
|
||||||
|
type: .modal,
|
||||||
|
title: UntranslatedL10n.commonRefreshing,
|
||||||
|
persistent: true))
|
||||||
|
}
|
||||||
|
|
||||||
|
private func hideRefreshIndicator() {
|
||||||
|
parameters.userIndicatorController.retractIndicatorWithId(Self.refreshIndicatorID)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showFailureIndicator() {
|
||||||
|
parameters.userIndicatorController.submitIndicator(UserIndicator(id: Self.failureIndicatorID,
|
||||||
|
type: .toast,
|
||||||
|
title: L10n.errorUnknown,
|
||||||
|
iconName: "xmark"))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum WaitlistScreenViewModelAction {
|
||||||
|
case cancel
|
||||||
|
case `continue`(UserSessionProtocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The user's credentials used to retry login and refresh the waiting list.
|
||||||
|
struct WaitlistScreenCredentials: CustomStringConvertible, CustomDebugStringConvertible {
|
||||||
|
let username: String
|
||||||
|
let password: String
|
||||||
|
let initialDeviceName: String?
|
||||||
|
let deviceID: String?
|
||||||
|
|
||||||
|
let homeserver: LoginHomeserver
|
||||||
|
|
||||||
|
var description: String { "Redacted" }
|
||||||
|
var debugDescription: String { "Redacted" }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WaitlistScreenViewState: BindableState {
|
||||||
|
/// The homeserver the user is waiting for.
|
||||||
|
let homeserver: LoginHomeserver
|
||||||
|
/// When refresh was successful, the user session that was returned by the login.
|
||||||
|
var userSession: UserSessionProtocol?
|
||||||
|
|
||||||
|
/// Whether or not the user is still waiting in the queue.
|
||||||
|
var isWaiting: Bool { userSession == nil }
|
||||||
|
|
||||||
|
var iconSymbolName: String {
|
||||||
|
if isWaiting {
|
||||||
|
return "stopwatch"
|
||||||
|
} else {
|
||||||
|
return "sparkles"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var title: String {
|
||||||
|
if isWaiting {
|
||||||
|
return UntranslatedL10n.screenWaitlistTitle
|
||||||
|
} else {
|
||||||
|
return UntranslatedL10n.screenWaitlistTitleSuccess
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var message: String {
|
||||||
|
if isWaiting {
|
||||||
|
return UntranslatedL10n.screenWaitlistMessage(InfoPlistReader.main.bundleDisplayName, homeserver.address)
|
||||||
|
} else {
|
||||||
|
return UntranslatedL10n.screenWaitlistMessageSuccess(InfoPlistReader.main.bundleDisplayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WaitlistScreenViewAction {
|
||||||
|
case cancel
|
||||||
|
case `continue`(UserSessionProtocol)
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
typealias WaitlistScreenViewModelType = StateStoreViewModel<WaitlistScreenViewState, WaitlistScreenViewAction>
|
||||||
|
|
||||||
|
class WaitlistScreenViewModel: WaitlistScreenViewModelType, WaitlistScreenViewModelProtocol {
|
||||||
|
private var actionsSubject: PassthroughSubject<WaitlistScreenViewModelAction, Never> = .init()
|
||||||
|
|
||||||
|
var actions: AnyPublisher<WaitlistScreenViewModelAction, Never> {
|
||||||
|
actionsSubject.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(homeserver: LoginHomeserver) {
|
||||||
|
super.init(initialViewState: WaitlistScreenViewState(homeserver: homeserver))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Public
|
||||||
|
|
||||||
|
override func process(viewAction: WaitlistScreenViewAction) {
|
||||||
|
switch viewAction {
|
||||||
|
case .cancel:
|
||||||
|
actionsSubject.send(.cancel)
|
||||||
|
case .continue(let userSession):
|
||||||
|
actionsSubject.send(.continue(userSession))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(userSession: UserSessionProtocol) {
|
||||||
|
state.userSession = userSession
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
protocol WaitlistScreenViewModelProtocol {
|
||||||
|
var actions: AnyPublisher<WaitlistScreenViewModelAction, Never> { get }
|
||||||
|
var context: WaitlistScreenViewModelType.Context { get }
|
||||||
|
|
||||||
|
/// Set a user session on the screen to transition to the success state.
|
||||||
|
func update(userSession: UserSessionProtocol)
|
||||||
|
}
|
||||||
@@ -102,13 +102,13 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
func login(username: String, password: String, initialDeviceName: String?, deviceId: String?) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||||
do {
|
do {
|
||||||
let client = try await Task.dispatch(on: .global()) {
|
let client = try await Task.dispatch(on: .global()) {
|
||||||
try self.authenticationService.login(username: username,
|
try self.authenticationService.login(username: username,
|
||||||
password: password,
|
password: password,
|
||||||
initialDeviceName: initialDeviceName,
|
initialDeviceName: initialDeviceName,
|
||||||
deviceId: deviceId)
|
deviceId: deviceID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await userSession(for: client)
|
return await userSession(for: client)
|
||||||
@@ -116,6 +116,10 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
|||||||
MXLog.error("Failed logging in with error: \(error)")
|
MXLog.error("Failed logging in with error: \(error)")
|
||||||
guard let error = error as? AuthenticationError else { return .failure(.failedLoggingIn) }
|
guard let error = error as? AuthenticationError else { return .failure(.failedLoggingIn) }
|
||||||
|
|
||||||
|
if error.isElementWaitlist {
|
||||||
|
return .failure(.isOnWaitlist)
|
||||||
|
}
|
||||||
|
|
||||||
switch error.code {
|
switch error.code {
|
||||||
case .forbidden:
|
case .forbidden:
|
||||||
return .failure(.invalidCredentials)
|
return .failure(.invalidCredentials)
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ enum AuthenticationServiceError: Error {
|
|||||||
case slidingSyncNotAvailable
|
case slidingSyncNotAvailable
|
||||||
case accountDeactivated
|
case accountDeactivated
|
||||||
case failedLoggingIn
|
case failedLoggingIn
|
||||||
|
|
||||||
|
case isOnWaitlist
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol AuthenticationServiceProxyProtocol {
|
protocol AuthenticationServiceProxyProtocol {
|
||||||
@@ -47,7 +49,7 @@ protocol AuthenticationServiceProxyProtocol {
|
|||||||
/// Add docs.
|
/// Add docs.
|
||||||
func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthenticationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthenticationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
||||||
/// Performs a password login using the current homeserver.
|
/// Performs a password login using the current homeserver.
|
||||||
func login(username: String, password: String, initialDeviceName: String?, deviceId: String?) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - OIDC
|
// MARK: - OIDC
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class MockAuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
|||||||
.failure(.oidcError(.notSupported))
|
.failure(.oidcError(.notSupported))
|
||||||
}
|
}
|
||||||
|
|
||||||
func login(username: String, password: String, initialDeviceName: String?, deviceId: String?) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||||
// Login only succeeds if the username and password match the valid credentials property
|
// Login only succeeds if the username and password match the valid credentials property
|
||||||
guard username == validCredentials.username, password == validCredentials.password else {
|
guard username == validCredentials.username, password == validCredentials.password else {
|
||||||
return .failure(.invalidCredentials)
|
return .failure(.invalidCredentials)
|
||||||
|
|||||||
@@ -46,4 +46,12 @@ extension AuthenticationError {
|
|||||||
|
|
||||||
return first
|
return first
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether or not the error is related to the sliding sync proxy being full.
|
||||||
|
///
|
||||||
|
/// This is a temporary error whilst we scale the backend infrastructure.
|
||||||
|
var isElementWaitlist: Bool {
|
||||||
|
guard case let .Generic(message) = self else { return false }
|
||||||
|
return message.contains("IO_ELEMENT_X_WAIT_LIST")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,13 +116,22 @@ class MockScreen: Identifiable {
|
|||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
return navigationStackCoordinator
|
return navigationStackCoordinator
|
||||||
case .softLogout:
|
case .softLogout:
|
||||||
let credentials = SoftLogoutScreenCredentials(userId: "@mock:matrix.org",
|
let credentials = SoftLogoutScreenCredentials(userID: "@mock:matrix.org",
|
||||||
homeserverName: "matrix.org",
|
homeserverName: "matrix.org",
|
||||||
userDisplayName: "mock",
|
userDisplayName: "mock",
|
||||||
deviceId: "ABCDEFGH")
|
deviceID: "ABCDEFGH")
|
||||||
return SoftLogoutScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
|
return SoftLogoutScreenCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
|
||||||
credentials: credentials,
|
credentials: credentials,
|
||||||
keyBackupNeeded: false))
|
keyBackupNeeded: false))
|
||||||
|
case .waitlist:
|
||||||
|
let credentials = WaitlistScreenCredentials(username: "alice",
|
||||||
|
password: "password",
|
||||||
|
initialDeviceName: nil,
|
||||||
|
deviceID: nil,
|
||||||
|
homeserver: .mockMatrixDotOrg)
|
||||||
|
return WaitlistScreenCoordinator(parameters: .init(credentials: credentials,
|
||||||
|
authenticationService: MockAuthenticationServiceProxy(),
|
||||||
|
userIndicatorController: UserIndicatorControllerMock.default))
|
||||||
case .simpleRegular:
|
case .simpleRegular:
|
||||||
return TemplateScreenCoordinator(parameters: .init(promptType: .regular))
|
return TemplateScreenCoordinator(parameters: .init(promptType: .regular))
|
||||||
case .simpleUpgrade:
|
case .simpleUpgrade:
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ enum UITestsScreenIdentifier: String {
|
|||||||
case serverSelectionNonModal
|
case serverSelectionNonModal
|
||||||
case authenticationFlow
|
case authenticationFlow
|
||||||
case softLogout
|
case softLogout
|
||||||
|
case waitlist
|
||||||
case analyticsPrompt
|
case analyticsPrompt
|
||||||
case analyticsSettingsScreen
|
case analyticsSettingsScreen
|
||||||
case simpleRegular
|
case simpleRegular
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ElementX
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class WaitlistScreenUITests: XCTestCase {
|
||||||
|
func testWaitingState() async throws {
|
||||||
|
let app = Application.launch(.waitlist)
|
||||||
|
try await app.assertScreenshot(.waitlist)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,10 +19,10 @@ import XCTest
|
|||||||
@testable import ElementX
|
@testable import ElementX
|
||||||
|
|
||||||
class SoftLogoutViewModelTests: XCTestCase {
|
class SoftLogoutViewModelTests: XCTestCase {
|
||||||
let credentials = SoftLogoutScreenCredentials(userId: "mock_user_id",
|
let credentials = SoftLogoutScreenCredentials(userID: "mock_user_id",
|
||||||
homeserverName: "https://matrix.org",
|
homeserverName: "https://matrix.org",
|
||||||
userDisplayName: "mock_username",
|
userDisplayName: "mock_username",
|
||||||
deviceId: "ABCDEFGH")
|
deviceID: "ABCDEFGH")
|
||||||
|
|
||||||
@MainActor func testInitialStateForMatrixOrg() {
|
@MainActor func testInitialStateForMatrixOrg() {
|
||||||
let viewModel = SoftLogoutScreenViewModel(credentials: credentials,
|
let viewModel = SoftLogoutScreenViewModel(credentials: credentials,
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@testable import ElementX
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class WaitlistScreenViewModelTests: XCTestCase {
|
||||||
|
var viewModel: WaitlistScreenViewModelProtocol!
|
||||||
|
var context: WaitlistScreenViewModelType.Context { viewModel.context }
|
||||||
|
|
||||||
|
override func setUpWithError() throws {
|
||||||
|
viewModel = WaitlistScreenViewModel(homeserver: .mockMatrixDotOrg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSuccess() async throws {
|
||||||
|
XCTAssertNil(context.viewState.userSession, "No user session should be set on a new view model.")
|
||||||
|
XCTAssertTrue(context.viewState.isWaiting, "The view should start off in the waiting state.")
|
||||||
|
|
||||||
|
viewModel.update(userSession: MockUserSession(clientProxy: MockClientProxy(userID: "@alice:matrix.org"),
|
||||||
|
mediaProvider: MockMediaProvider()))
|
||||||
|
|
||||||
|
XCTAssertNotNil(context.viewState.userSession, "The user session should have been updated.")
|
||||||
|
XCTAssertFalse(context.viewState.isWaiting, "The view should not be in the waiting state after setting a user session.")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Add a screen to be shown when new users are on the waiting list.
|
||||||
Reference in New Issue
Block a user