Migration Screen (#1224)

- Hide bottom bar when in skeletons.
- Use the new design for the Waitlist screen too.
This commit is contained in:
Doug
2023-06-30 13:27:49 +01:00
committed by GitHub
parent c5d47378a4
commit 2025dd9517
38 changed files with 528 additions and 52 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ public struct ElementColors {
public var system: Color { colors.system }
@available(swift, obsoleted: 5.0, message: "Use bgCanvasDefault from Compound for backgrounds. For text or icons use textOnSolidPrimary/iconOnSolidPrimary.")
public var background: Color { colors.background }
@available(swift, obsoleted: 5.0, message: "Use textActionAccent/iconAccentTertiary from Compound.")
@available(swift, deprecated: 5.0, message: "Use textActionAccent/iconAccentTertiary from Compound.")
public var brand: Color { colors.accent }
public var contentAndAvatars: [Color] { colors.contentAndAvatars }
+50 -2
View File
@@ -211,6 +211,7 @@
5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */; };
516534FC5C893D57F169D5A8 /* MapTilerGeocoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33720F7AD25E85E4A84669E8 /* MapTilerGeocoding.swift */; };
518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; };
51C240F4660F7269203A9B3A /* MigrationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */; };
520EEDAFBC778AB0B41F2F53 /* ClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */; };
5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; };
53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */; };
@@ -253,6 +254,7 @@
6298AB0906DDD3525CD78C6B /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = 81DB3AB6CE996AB3954F4F03 /* KZFileWatchers */; };
63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */; };
6448F8D1D3CA4CD27BB4CADD /* RoomMemberProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */; };
644AA5001BCC58D7732EB772 /* MigrationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12EDAFB64FA5F6812D54F39A /* MigrationScreenViewModel.swift */; };
64C373ACCFA26D42BA45CFAD /* HomeScreenInvitesButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24227FF9A2797F6EA7F69CDD /* HomeScreenInvitesButton.swift */; };
64D05250CEDE8B604119F6E6 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 981663D961C94270FA035FD0 /* Alert.swift */; };
64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1941C8817E6B6971BA4415F5 /* VideoRoomTimelineView.swift */; };
@@ -287,6 +289,7 @@
6E47D126DD7585E8F8237CE7 /* LoadableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */; };
6EC7A40A537CFB3D526A111C /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; };
6F2AB43A1EFAD8A97AF41A15 /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */; };
6F2D5D4F2590310DFAE973E4 /* WaitingDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6D698BFD68B061350553930 /* WaitingDialog.swift */; };
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFF7BF82A950B91BC5469E91 /* ViewFrameReader.swift */; };
6FF51EB400DBA0668FC38B97 /* TimelineStartRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9ED8E731E21055F728E5FED /* TimelineStartRoomTimelineView.swift */; };
702694459B649B9D3A3C34F8 /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9212AE02CBDD692C56A879F /* TimelineTableViewController.swift */; };
@@ -402,6 +405,7 @@
9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */; };
962A4F8AD6312804E2C6BB6E /* PhotoLibraryPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A232D9156D225BD9FD1D0C43 /* PhotoLibraryPicker.swift */; };
964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; };
968823C9DBF3062729413EBF /* MigrationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3DF0BFE5637EA42F5651FE8 /* MigrationScreenCoordinator.swift */; };
968A5B890004526AB58A217C /* AvatarSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */; };
97189E495F0E47805D1868DB /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 527578916BD388A09F5A8036 /* DTCoreText */; };
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
@@ -429,6 +433,7 @@
9DC5FB22B8F86C3B51E907C1 /* HomeScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6E4C37E9F0E53D3DF951AC /* HomeScreenUITests.swift */; };
9DD5AA10E85137140FEA86A3 /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */; };
9DD84E014ADFB2DD813022D5 /* RoomDetailsEditScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */; };
9DE98D3EC47742A0F9F9EC3C /* MigrationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5685139D0B72BED3503EFCC /* MigrationScreen.swift */; };
9DF3F6318A4402305F5EB869 /* AnalyticsPromptScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F8002D0392A476D2758B291 /* AnalyticsPromptScreen.swift */; };
9E838A62918E47BC72D6640D /* UserIndicatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AB54B4F94686CCF0289B72F /* UserIndicatorPresenter.swift */; };
9EBDC79CAC9B63A0D626E333 /* LegalInformationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */; };
@@ -497,6 +502,7 @@
B402708F8728DD0DB7C324E2 /* StartChatScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */; };
B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; };
B45F20A1C3F1CE19D5B8BA74 /* InvitesScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F61A0DD8243B395499C99A2 /* InvitesScreenUITests.swift */; };
B46EBC7B96CCB64FF8E110DC /* MigrationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CD0FAE9EA761DA175D31CC7 /* MigrationScreenModels.swift */; };
B4A0C69370E6008A971463E7 /* BugReportScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */; };
B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; };
B5479997ECC516C121E6625E /* LocationMarkerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFECCE59967018204876D0A5 /* LocationMarkerView.swift */; };
@@ -553,6 +559,7 @@
C4FE0E11A907C8999F92D5A8 /* TimelineStartRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F5F9E02B1AB5350B1815E7 /* TimelineStartRoomTimelineItem.swift */; };
C55A44C99F64A479ABA85B46 /* RoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */; };
C58E305C380D3ADDF7912180 /* StickerRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 818695BED971753243FEF897 /* StickerRoomTimelineItem.swift */; };
C5946E4A3D4295F002F0B3DC /* MigrationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46B59EC4B0C93254089EAACB /* MigrationScreenViewModelTests.swift */; };
C5A07E2D88BE7D51DCECD166 /* LoginScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */; };
C6136E848E55D2C86BF760F5 /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C789E7BFC066CF39B8AE0974 /* NetworkMonitor.swift */; };
C67FCC854F3A6FC7A2EC04D0 /* MediaUploadPreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */; };
@@ -683,6 +690,7 @@
F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */; };
F5D2270B5021D521C0D22E11 /* FlowCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */; };
F656F92A63D3DC1978D79427 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 07FEEEDB11543A7DED420F04 /* Compound */; };
F692D4AF571333C0D785725A /* MigrationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBBC5E7C0F8337D2A46EB2DD /* MigrationScreenViewModelProtocol.swift */; };
F697284B9B5F2C00CFEA3B12 /* EmojiDetectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E93D91DE3288010390DEE /* EmojiDetectionTests.swift */; };
F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */; };
F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */; };
@@ -814,6 +822,7 @@
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>"; };
127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = "<group>"; };
12EDAFB64FA5F6812D54F39A /* MigrationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenViewModel.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>"; };
130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = "<group>"; };
@@ -945,6 +954,7 @@
45CDF9A107BFE6C79B58D6B5 /* RoomMembersListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModelProtocol.swift; sourceTree = "<group>"; };
45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationCenterProtocol.swift; sourceTree = "<group>"; };
466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenModels.swift; sourceTree = "<group>"; };
46B59EC4B0C93254089EAACB /* MigrationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenViewModelTests.swift; sourceTree = "<group>"; };
46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsAppCoordinator.swift; sourceTree = "<group>"; };
47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = "<group>"; };
471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineView.swift; sourceTree = "<group>"; };
@@ -1001,6 +1011,7 @@
5AEA0B743847CFA5B3C38EE4 /* RoomMembersListScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenCoordinator.swift; sourceTree = "<group>"; };
5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenCoordinator.swift; sourceTree = "<group>"; };
5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenCoordinator.swift; sourceTree = "<group>"; };
5CD0FAE9EA761DA175D31CC7 /* MigrationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenModels.swift; 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>"; };
5D99730313BEBF08CDE81EE3 /* EmojiDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiDetection.swift; sourceTree = "<group>"; };
@@ -1069,6 +1080,7 @@
7475C5AE20BA896930907EA8 /* AudioRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRoomTimelineItemContent.swift; sourceTree = "<group>"; };
748AE77AC3B0A01223033B87 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenCoordinator.swift; sourceTree = "<group>"; };
75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenUITests.swift; sourceTree = "<group>"; };
772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = "<group>"; };
78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenViewModelProtocol.swift; sourceTree = "<group>"; };
78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitCoordinatorTests.swift; sourceTree = "<group>"; };
@@ -1167,6 +1179,7 @@
A232D9156D225BD9FD1D0C43 /* PhotoLibraryPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryPicker.swift; sourceTree = "<group>"; };
A2AC3C656E960E15B5905E05 /* UnsupportedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineView.swift; sourceTree = "<group>"; };
A34A814CBD56230BC74FFCF4 /* MXLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXLogger.swift; sourceTree = "<group>"; };
A3DF0BFE5637EA42F5651FE8 /* MigrationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenCoordinator.swift; sourceTree = "<group>"; };
A3FBD9C2B9A5479526920399 /* BugReportScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenCoordinator.swift; sourceTree = "<group>"; };
A40C19719687984FD9478FBE /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; };
A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreen.swift; sourceTree = "<group>"; };
@@ -1310,6 +1323,7 @@
D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceProxy.swift; sourceTree = "<group>"; };
D4DA544B2520BFA65D6DB4BB /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelProtocol.swift; sourceTree = "<group>"; };
D5685139D0B72BED3503EFCC /* MigrationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreen.swift; sourceTree = "<group>"; };
D5AC06FC11B6638F7BF1670E /* TimelineDeliveryStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineDeliveryStatusView.swift; sourceTree = "<group>"; };
D5E26C54362206BBDD096D83 /* test_audio.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = test_audio.mp3; sourceTree = "<group>"; };
D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenCoordinator.swift; sourceTree = "<group>"; };
@@ -1358,6 +1372,7 @@
E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; 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>"; };
EBBC5E7C0F8337D2A46EB2DD /* MigrationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenViewModelProtocol.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>"; };
@@ -1386,6 +1401,7 @@
F506C6ADB1E1DA6638078E11 /* UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F5311C989EC15B4C2D699025 /* StaticLocationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreenViewModel.swift; sourceTree = "<group>"; };
F57C8022B8A871A1DCD1750A /* UserIndicatorToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorToastView.swift; sourceTree = "<group>"; };
F6D698BFD68B061350553930 /* WaitingDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitingDialog.swift; sourceTree = "<group>"; };
F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = "<group>"; };
F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedBodyText.swift; sourceTree = "<group>"; };
F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreen.swift; sourceTree = "<group>"; };
@@ -2372,6 +2388,7 @@
AE203026B9AD3DB412439866 /* MediaUploadingPreprocessorTests.swift */,
03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */,
6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */,
46B59EC4B0C93254089EAACB /* MigrationScreenViewModelTests.swift */,
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */,
78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */,
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */,
@@ -2495,6 +2512,14 @@
path = View;
sourceTree = "<group>";
};
79A3F9F48E7D5B189A63BACB /* View */ = {
isa = PBXGroup;
children = (
D5685139D0B72BED3503EFCC /* MigrationScreen.swift */,
);
path = View;
sourceTree = "<group>";
};
79E560F5113ED25D172E550C /* Media */ = {
isa = PBXGroup;
children = (
@@ -2606,6 +2631,18 @@
path = MediaPickerScreen;
sourceTree = "<group>";
};
888C38D172A591977316DB1E /* MigrationScreen */ = {
isa = PBXGroup;
children = (
A3DF0BFE5637EA42F5651FE8 /* MigrationScreenCoordinator.swift */,
5CD0FAE9EA761DA175D31CC7 /* MigrationScreenModels.swift */,
12EDAFB64FA5F6812D54F39A /* MigrationScreenViewModel.swift */,
EBBC5E7C0F8337D2A46EB2DD /* MigrationScreenViewModelProtocol.swift */,
79A3F9F48E7D5B189A63BACB /* View */,
);
path = MigrationScreen;
sourceTree = "<group>";
};
8A9C09B6A392465E03B8D1B1 /* IntegrationTests */ = {
isa = PBXGroup;
children = (
@@ -2712,6 +2749,7 @@
1DB34B0C74CD242FED9DD069 /* LoginScreenUITests.swift */,
39B6C8690AEA1E49FF1BAF95 /* MediaUploadPreviewScreenUITests.swift */,
59846FA04E1DBBFDD8829C2A /* MessageForwardingScreenUITests.swift */,
75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */,
0C88046D6A070D9827181C4D /* OnboardingUITests.swift */,
4132F882A984ED971338EE9D /* ReportContentScreenUITests.swift */,
122186B7CD1BC46A9C629DD9 /* RoomDetailsEditScreenUITests.swift */,
@@ -2768,6 +2806,7 @@
9F4A1E90C924DE7954BA5005 /* View */ = {
isa = PBXGroup;
children = (
F6D698BFD68B061350553930 /* WaitingDialog.swift */,
80C4927D09099497233E9980 /* WaitlistScreen.swift */,
);
path = View;
@@ -3258,6 +3297,7 @@
87E2774157D9C4894BCFF3F8 /* MediaPickerScreen */,
23605DD08620BE6558242469 /* MediaUploadPreviewScreen */,
3348D14DBDB54E72FC67E2F3 /* MessageForwardingScreen */,
888C38D172A591977316DB1E /* MigrationScreen */,
3F38EAC92E2281990E65DAF2 /* OnboardingScreen */,
A448A3A8F764174C60CD0CA1 /* Other */,
5970F275D6014548DCED6106 /* ReportContentScreen */,
@@ -3915,6 +3955,7 @@
B9A8C34A00D03094C0CF56F3 /* MediaUploadPreviewScreenViewModelTests.swift in Sources */,
23701DE32ACD6FD40AA992C3 /* MediaUploadingPreprocessorTests.swift in Sources */,
F777C6FEE7D106136E2ED2B2 /* MessageForwardingScreenViewModelTests.swift in Sources */,
C5946E4A3D4295F002F0B3DC /* MigrationScreenViewModelTests.swift in Sources */,
4E8F17EBA24FBBA6ABB62ECB /* MockBackgroundTaskService.swift in Sources */,
1146E9EDCF8344F7D6E0D553 /* MockCoder.swift in Sources */,
DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */,
@@ -4196,6 +4237,11 @@
695825D20A761C678809345D /* MessageForwardingScreenModels.swift in Sources */,
F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */,
C13128AAA787A4C2CBE4EE82 /* MessageForwardingScreenViewModelProtocol.swift in Sources */,
9DE98D3EC47742A0F9F9EC3C /* MigrationScreen.swift in Sources */,
968823C9DBF3062729413EBF /* MigrationScreenCoordinator.swift in Sources */,
B46EBC7B96CCB64FF8E110DC /* MigrationScreenModels.swift in Sources */,
644AA5001BCC58D7732EB772 /* MigrationScreenViewModel.swift in Sources */,
F692D4AF571333C0D785725A /* MigrationScreenViewModelProtocol.swift in Sources */,
152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */,
EE4F5601356228FF72FC56B6 /* MockClientProxy.swift in Sources */,
B659E3A49889E749E3239EA7 /* MockMediaProvider.swift in Sources */,
@@ -4439,6 +4485,7 @@
1A83DD22F3E6F76B13B6E2F9 /* VideoRoomTimelineItemContent.swift in Sources */,
64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */,
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */,
6F2D5D4F2590310DFAE973E4 /* WaitingDialog.swift in Sources */,
9AFEE46B03B7E995B3E1A53D /* WaitlistScreen.swift in Sources */,
7C384A8E54A4B60A14CDE8E5 /* WaitlistScreenCoordinator.swift in Sources */,
2F66701B15657A87B4AC3A0A /* WaitlistScreenModels.swift in Sources */,
@@ -4467,6 +4514,7 @@
5C8AFBF168A41E20835F3B86 /* LoginScreenUITests.swift in Sources */,
7FB0BDE26838F1A92782D5E1 /* MediaUploadPreviewScreenUITests.swift in Sources */,
6713835120D94BAA8ED7E3E5 /* MessageForwardingScreenUITests.swift in Sources */,
51C240F4660F7269203A9B3A /* MigrationScreenUITests.swift in Sources */,
6B15FF984906AAFCF9DC4F58 /* OnboardingUITests.swift in Sources */,
BA0D3DDCEDD97502DAC4B6E9 /* ReportContentScreenUITests.swift in Sources */,
F16109A6F6DF03DA26D59233 /* RoomDetailsEditScreenUITests.swift in Sources */,
@@ -4750,7 +4798,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)";
MACOSX_DEPLOYMENT_TARGET = 13.3;
MARKETING_VERSION = 1.1.6;
MARKETING_VERSION = 1.1.7;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -4825,7 +4873,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)";
MACOSX_DEPLOYMENT_TARGET = 13.3;
MARKETING_VERSION = 1.1.6;
MARKETING_VERSION = 1.1.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -97,6 +97,11 @@
value = ""
isEnabled = "NO">
</EnvironmentVariable>
<EnvironmentVariable
key = "RESET_APP_SETTINGS"
value = "true"
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "medium-light-dark.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

@@ -253,6 +253,8 @@
"screen_media_picker_error_failed_selection" = "Failed selecting media, please try again.";
"screen_media_upload_preview_error_failed_processing" = "Failed processing media to upload, please try again.";
"screen_media_upload_preview_error_failed_sending" = "Failed uploading media, please try again.";
"screen_migration_message" = "This is a one time process, thanks for waiting.";
"screen_migration_title" = "Setting up your account.";
"screen_onboarding_sign_in_manually" = "Sign in manually";
"screen_onboarding_sign_in_with_qr_code" = "Sign in with QR code";
"screen_onboarding_sign_up" = "Create account";
@@ -329,9 +331,9 @@
"screen_start_chat_error_starting_chat" = "An error occurred when trying to start a chat";
"screen_view_location_title" = "Location";
"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$@";
"screen_waitlist_title" = "You're on the waitlist!";
"screen_waitlist_title_success" = "You're in!";
"screen_waitlist_message_success" = "Welcome to %1$@!";
"screen_waitlist_title" = "You’re almost there.";
"screen_waitlist_title_success" = "You're in.";
"session_verification_banner_message" = "Looks like you’re using a new device. Verify it’s you to access your encrypted messages.";
"session_verification_banner_title" = "Access your message history";
"settings_rageshake" = "Rageshake";
@@ -194,6 +194,10 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
// MARK: - Private
private static func setupServiceLocator(navigationRootCoordinator: NavigationRootCoordinator) {
if ProcessInfo.processInfo.environment["RESET_APP_SETTINGS"].map(Bool.init) == true {
AppSettings.reset()
}
ServiceLocator.shared.register(userIndicatorController: UserIndicatorController(rootCoordinator: navigationRootCoordinator))
ServiceLocator.shared.register(appSettings: AppSettings())
ServiceLocator.shared.register(networkMonitor: NetworkMonitor())
@@ -211,10 +215,18 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
guard oldVersion != newVersion else { return }
if oldVersion < Version(1, 1, 0) {
MXLog.info("Migrating to v1.1.0, signing out the user.")
// Version 1.1.0 switched the Rust crypto store to SQLite
// There are no migrations in place so we need to reset everything
wipeUserData()
}
if oldVersion < Version(1, 1, 7) {
MXLog.info("Migrating to v1.1.0, marking accounts as migrated.")
for userID in userSessionStore.userIDs {
ServiceLocator.shared.settings.migratedAccounts[userID] = true
}
}
}
/// Clears the keychain, app support directory etc ready for a fresh use.
@@ -338,7 +350,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
let userSessionFlowCoordinator = UserSessionFlowCoordinator(userSession: userSession,
navigationSplitCoordinator: navigationSplitCoordinator,
bugReportService: ServiceLocator.shared.bugReportService,
roomTimelineControllerFactory: RoomTimelineControllerFactory())
roomTimelineControllerFactory: RoomTimelineControllerFactory(),
appSettings: ServiceLocator.shared.settings)
userSessionFlowCoordinator.callback = { [weak self] action in
switch action {
@@ -22,6 +22,7 @@ final class AppSettings {
private enum UserDefaultsKeys: String {
case lastVersionLaunched
case seenInvites
case migratedAccounts
case timelineStyle
case analyticsConsentState
case enableInAppNotifications
@@ -104,6 +105,13 @@ final class AppSettings {
/// Any pre-defined static client registrations for OIDC issuers.
let oidcStaticRegistrations: [URL: String] = ["https://id.thirdroom.io/realms/thirdroom": "elementx"]
/// A dictionary of accounts that have performed an initial sync through their proxy.
///
/// This is a temporary workaround. In the future we should be able to receive a signal from the
/// proxy that it is the first sync (or that an upgrade on the backend will involve a slower sync).
@UserPreference(key: UserDefaultsKeys.migratedAccounts, defaultValue: [:], storageType: .userDefaults(store))
var migratedAccounts: [String: Bool]
// MARK: - Notifications
var pusherAppId: String {
@@ -27,11 +27,13 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
private let navigationSplitCoordinator: NavigationSplitCoordinator
private let bugReportService: BugReportServiceProtocol
private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol
private let appSettings: AppSettings
private let stateMachine: UserSessionFlowCoordinatorStateMachine
private let roomFlowCoordinator: RoomFlowCoordinator
private var cancellables: Set<AnyCancellable> = .init()
private var migrationCancellable: AnyCancellable?
private let sidebarNavigationStackCoordinator: NavigationStackCoordinator
private let detailNavigationStackCoordinator: NavigationStackCoordinator
@@ -43,12 +45,14 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
init(userSession: UserSessionProtocol,
navigationSplitCoordinator: NavigationSplitCoordinator,
bugReportService: BugReportServiceProtocol,
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol) {
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol,
appSettings: AppSettings) {
stateMachine = UserSessionFlowCoordinatorStateMachine()
self.userSession = userSession
self.navigationSplitCoordinator = navigationSplitCoordinator
self.bugReportService = bugReportService
self.roomTimelineControllerFactory = roomTimelineControllerFactory
self.appSettings = appSettings
sidebarNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator)
detailNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator)
@@ -78,7 +82,13 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
}
func start() {
stateMachine.processEvent(.start)
if appSettings.migratedAccounts[userSession.userID] != true {
// Show the migration screen for a new account.
stateMachine.processEvent(.startWithMigration)
} else {
// Otherwise go straight to the home screen.
stateMachine.processEvent(.start)
}
}
func stop() { }
@@ -90,13 +100,17 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
// MARK: - FlowCoordinatorProtocol
func handleAppRoute(_ appRoute: AppRoute, animated: Bool) {
// Tidy up any state before applying the new route.
switch stateMachine.state {
case .initial, .migration:
return // Not ready to handle a route.
case .roomList:
break // Nothing to tidy up on the home screen.
case .feedbackScreen, .sessionVerificationScreen, .settingsScreen, .startChatScreen, .invitesScreen:
navigationSplitCoordinator.setSheetCoordinator(nil, animated: animated)
case .roomList, .initial:
break
}
// Apply the route.
switch appRoute {
case .room, .roomDetails, .roomList:
roomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
@@ -122,6 +136,12 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
switch (context.fromState, context.event, context.toState) {
case (.initial, .start, .roomList):
self.presentHomeScreen()
case (.initial, .startWithMigration, .migration):
self.presentMigrationScreen() // Full screen cover
self.presentHomeScreen() // Have the home screen ready to show underneath
case (.migration, .completeMigration, .roomList):
self.dismissMigrationScreen()
case(.roomList, .selectRoom, .roomList):
break
@@ -179,6 +199,25 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
}
}
private func presentMigrationScreen() {
// Listen for the first sync to finish.
migrationCancellable = userSession.clientProxy.callbacks
.receive(on: DispatchQueue.main)
.sink { [weak self] callback in
guard let self, stateMachine.state == .migration, case .receivedSyncUpdate = callback else { return }
migrationCancellable = nil
appSettings.migratedAccounts[userSession.userID] = true
stateMachine.processEvent(.completeMigration)
}
let coordinator = MigrationScreenCoordinator()
navigationSplitCoordinator.setFullScreenCoverCoordinator(coordinator)
}
private func dismissMigrationScreen() {
navigationSplitCoordinator.setFullScreenCoverCoordinator(nil)
}
// swiftlint:disable:next cyclomatic_complexity
private func presentHomeScreen() {
let parameters = HomeScreenCoordinatorParameters(userSession: userSession,
@@ -23,6 +23,9 @@ class UserSessionFlowCoordinatorStateMachine {
/// The initial state, used before the coordinator starts
case initial
/// Showing the migration screen whilst the proxy performs an initial sync.
case migration
/// Showing the home screen. The `selectedRoomId` represents the timeline shown on the detail panel (if any)
case roomList(selectedRoomId: String?)
@@ -51,6 +54,11 @@ class UserSessionFlowCoordinatorStateMachine {
/// Start the user session flows
case start
/// Start the user session flows with a migration screen.
case startWithMigration
/// Request to transition from the migration state to the home screen.
case completeMigration
/// Request presentation for a particular room
/// - Parameter roomId:the room identifier
case selectRoom(roomId: String)
@@ -97,7 +105,9 @@ class UserSessionFlowCoordinatorStateMachine {
// swiftlint:disable:next cyclomatic_complexity
private func configure() {
stateMachine.addRoutes(event: .start, transitions: [.initial => .roomList(selectedRoomId: nil)])
stateMachine.addRoutes(event: .startWithMigration, transitions: [.initial => .migration])
stateMachine.addRoutes(event: .completeMigration, transitions: [.migration => .roomList(selectedRoomId: nil)])
stateMachine.addRouteMapping { event, fromState, _ in
switch (event, fromState) {
case (.selectRoom(let roomId), .roomList):
+1
View File
@@ -40,6 +40,7 @@ internal enum Asset {
internal static let locationMarker = ImageAsset(name: "images/location-marker")
internal static let locationPin = ImageAsset(name: "images/location-pin")
internal static let timelineComposerSendMessage = ImageAsset(name: "images/timeline-composer-send-message")
internal static let waitingGradient = ImageAsset(name: "images/waiting-gradient")
}
}
// swiftlint:enable identifier_name line_length nesting type_body_length type_name
+7 -3
View File
@@ -644,6 +644,10 @@ public enum L10n {
public static var screenMediaUploadPreviewErrorFailedProcessing: String { return L10n.tr("Localizable", "screen_media_upload_preview_error_failed_processing") }
/// Failed uploading media, please try again.
public static var screenMediaUploadPreviewErrorFailedSending: String { return L10n.tr("Localizable", "screen_media_upload_preview_error_failed_sending") }
/// This is a one time process, thanks for waiting.
public static var screenMigrationMessage: String { return L10n.tr("Localizable", "screen_migration_message") }
/// Setting up your account.
public static var screenMigrationTitle: String { return L10n.tr("Localizable", "screen_migration_title") }
/// Sign in manually
public static var screenOnboardingSignInManually: String { return L10n.tr("Localizable", "screen_onboarding_sign_in_manually") }
/// Sign in with QR code
@@ -832,13 +836,13 @@ public enum L10n {
public static func screenWaitlistMessage(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "screen_waitlist_message", String(describing: p1), String(describing: p2))
}
/// Welcome to %1$@
/// Welcome to %1$@!
public static func screenWaitlistMessageSuccess(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_waitlist_message_success", String(describing: p1))
}
/// You're on the waitlist!
/// You’re almost there.
public static var screenWaitlistTitle: String { return L10n.tr("Localizable", "screen_waitlist_title") }
/// You're in!
/// You're in.
public static var screenWaitlistTitleSuccess: String { return L10n.tr("Localizable", "screen_waitlist_title_success") }
/// Looks like you’re using a new device. Verify it’s you to access your encrypted messages.
public static var sessionVerificationBannerMessage: String { return L10n.tr("Localizable", "session_verification_banner_message") }
@@ -84,9 +84,9 @@ class ScrollViewAdapter: NSObject, UIScrollViewDelegate {
let velocity = scrollView.panGestureRecognizer.velocity(in: nil)
if velocity.y > Constant.scrollDirectionThreshold {
scrollDirectionSubject.send(.down)
} else if velocity.y < -Constant.scrollDirectionThreshold {
scrollDirectionSubject.send(.up)
} else if velocity.y < -Constant.scrollDirectionThreshold {
scrollDirectionSubject.send(.down)
}
}
@@ -0,0 +1,93 @@
//
// Copyright 2023 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import SwiftUI
/// A standardised layout for waiting dialogs shown during the onboarding flow.
struct WaitingDialog<Content: View, BottomContent: View>: View {
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
@Environment(\.verticalSizeClass) private var verticalSizeClass
/// Not using the default to allow the gradient to fill edge to edge.
private let horizontalPadding = 16.0
/// The top padding of the content, used to keep the text below the image.
private var contentTopPadding: CGFloat {
if verticalSizeClass == .compact {
// Reduced value for iPhones in landscape.
return UIConstants.onboardingBreakerScreenTopPadding
} else if horizontalSizeClass == .compact {
// The default value for portrait iPhones.
return 2 * UIConstants.onboardingBreakerScreenTopPadding
} else {
// Larger on iPad specifically for 11" in Landscape.
return 2.7 * UIConstants.onboardingBreakerScreenTopPadding
}
}
/// The main content shown at the top of the layout.
@ViewBuilder var content: () -> Content
/// The content shown at the bottom of the layout.
@ViewBuilder var bottomContent: () -> BottomContent
var body: some View {
FullscreenDialog(topPadding: UIConstants.onboardingBreakerScreenTopPadding, horizontalPadding: 0) {
content()
.padding(.top, contentTopPadding)
.padding(.horizontal, horizontalPadding)
} bottomContent: {
bottomContent()
.padding(.horizontal, horizontalPadding)
}
.background {
background
.ignoresSafeArea(edges: [.horizontal, .bottom])
}
.ignoresSafeArea(edges: [.horizontal, .bottom])
.environment(\.backgroundStyle, AnyShapeStyle(Color.compound.bgCanvasDefault))
.environment(\.colorScheme, .dark)
.toolbar(.visible, for: .navigationBar) // Layout consistency in all states.
.toolbarBackground(.hidden, for: .navigationBar)
.preferredColorScheme(.light) // Has no effect on Previews, works fine in-app.
}
var background: some View {
// Negative spacing to hide a rendering bug that shows the white background.
GeometryReader { geometry in
VStack(spacing: -5) {
Color.white
.frame(maxHeight: UIConstants.onboardingBreakerScreenTopPadding)
Image(asset: Asset.Images.waitingGradient)
.resizable()
.frame(width: horizontalSizeClass == .compact ? nil : geometry.size.width) // Forced for landscape iPhone and nicer iPad.
.scaledToFit()
.layoutPriority(1) // Force for all landscape layouts.
Color.compound.bgCanvasDefault
}
}
}
}
struct WaitingDialog_Previews: PreviewProvider {
static let viewModel = WaitlistScreenViewModel(homeserver: .mockMatrixDotOrg)
static var previews: some View {
NavigationStack {
WaitlistScreen(context: viewModel.context)
}
}
}
@@ -20,42 +20,29 @@ struct WaitlistScreen: View {
@ObservedObject var context: WaitlistScreenViewModel.Context
var body: some View {
FullscreenDialog(topPadding: UIConstants.iconTopPaddingToNavigationBar) {
header
WaitingDialog {
content
} 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)
var content: some View {
VStack(spacing: 16) {
Text(context.viewState.title.tinting(".", color: .element.brand))
.font(.compound.headingXLBold)
.multilineTextAlignment(.center)
.foregroundColor(.compound.textPrimary)
.fixedSize(horizontal: false, vertical: true)
Text(context.viewState.message)
.font(.compound.bodyMD)
.font(.compound.bodyLG)
.multilineTextAlignment(.center)
.foregroundColor(.compound.textSecondary)
.foregroundColor(.compound.textPrimary)
}
.padding(.horizontal, 16)
}
/// The action buttons shown at the bottom of the view.
@@ -26,9 +26,17 @@ struct HomeScreen: View {
@ObservedObject var context: HomeScreenViewModel.Context
@State private var scrollViewAdapter = ScrollViewAdapter()
@State private var showingBottomToolbar = true
@State private var lastScrollDirection: ScrollViewAdapter.ScrollDirection = .up
@State private var isSearching = false
var bottomBarVisibility: Visibility {
if lastScrollDirection == .up, context.viewState.roomListMode == .rooms {
return .automatic
} else {
return .hidden
}
}
var body: some View {
ScrollView {
if context.viewState.showSessionVerificationBanner {
@@ -81,7 +89,7 @@ struct HomeScreen: View {
}
.onReceive(scrollViewAdapter.scrollDirection) { direction in
withAnimation(.elementDefault) {
showingBottomToolbar = (direction == .down)
lastScrollDirection = direction
}
}
.onChange(of: context.viewState.visibleRooms) { _ in
@@ -100,7 +108,7 @@ struct HomeScreen: View {
actions: leaveRoomAlertActions,
message: leaveRoomAlertMessage)
.navigationTitle(L10n.screenRoomlistMainSpaceTitle)
.toolbar(showingBottomToolbar ? .automatic : .hidden, for: .bottomBar)
.toolbar(bottomBarVisibility, for: .bottomBar)
.toolbar { toolbar }
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
.track(screen: .home)
@@ -117,6 +125,8 @@ struct HomeScreen: View {
ToolbarItemGroup(placement: .bottomBar) {
Spacer()
newRoomButton
// Fix position animating on loop by getting caught up in the shimmer effect somehow.
.animation(.noAnimation, value: context.viewState.roomListMode)
}
}
@@ -0,0 +1,33 @@
//
// 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
final class MigrationScreenCoordinator: CoordinatorProtocol {
private var viewModel: MigrationScreenViewModelProtocol
private var cancellables: Set<AnyCancellable> = .init()
init() {
viewModel = MigrationScreenViewModel()
}
func start() { }
func toPresentable() -> AnyView {
AnyView(MigrationScreen(context: viewModel.context))
}
}
@@ -0,0 +1,23 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
enum MigrationScreenViewModelAction { }
struct MigrationScreenViewState: BindableState { }
enum MigrationScreenViewAction { }
@@ -0,0 +1,32 @@
//
// 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 MigrationScreenViewModelType = StateStoreViewModel<MigrationScreenViewState, MigrationScreenViewAction>
class MigrationScreenViewModel: MigrationScreenViewModelType, MigrationScreenViewModelProtocol {
private var actionsSubject: PassthroughSubject<MigrationScreenViewModelAction, Never> = .init()
var actions: AnyPublisher<MigrationScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init() {
super.init(initialViewState: MigrationScreenViewState())
}
}
@@ -0,0 +1,23 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Combine
@MainActor
protocol MigrationScreenViewModelProtocol {
var actions: AnyPublisher<MigrationScreenViewModelAction, Never> { get }
var context: MigrationScreenViewModelType.Context { get }
}
@@ -0,0 +1,57 @@
//
// 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 MigrationScreen: View {
@ObservedObject var context: MigrationScreenViewModel.Context
var body: some View {
WaitingDialog {
content
} bottomContent: {
EmptyView()
}
.navigationBarBackButtonHidden()
}
var content: some View {
VStack(spacing: 16) {
ProgressView()
.tint(.compound.iconPrimary)
.padding(.bottom, 4)
Text(L10n.screenMigrationTitle.tinting(".", color: .element.brand))
.font(.compound.headingXLBold)
.multilineTextAlignment(.center)
.foregroundColor(.compound.textPrimary)
Text(L10n.screenMigrationMessage)
.font(.compound.bodyLG)
.multilineTextAlignment(.center)
.foregroundColor(.compound.textPrimary)
}
}
}
// MARK: - Previews
struct MigrationScreen_Previews: PreviewProvider {
static let viewModel = MigrationScreenViewModel()
static var previews: some View {
MigrationScreen(context: viewModel.context)
}
}
@@ -25,6 +25,8 @@ class UserSessionStore: UserSessionStoreProtocol {
/// Whether or not there are sessions in the store.
var hasSessions: Bool { !keychainController.restorationTokens().isEmpty }
/// All the user IDs managed by the store.
var userIDs: [String] { keychainController.restorationTokens().map(\.userID) }
/// The base directory where all session data is stored.
let baseDirectory: URL
@@ -31,6 +31,9 @@ protocol UserSessionStoreProtocol {
/// Whether or not there are sessions in the store.
var hasSessions: Bool { get }
/// All the user IDs managed by the store.
var userIDs: [String] { get }
/// Returns the location to store user data for a particular username.
var baseDirectory: URL { get }
@@ -113,6 +113,9 @@ class MockScreen: Identifiable {
analytics: ServiceLocator.shared.analytics))
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .migration:
let coordinator = MigrationScreenCoordinator()
return coordinator
case .authenticationFlow:
let navigationStackCoordinator = NavigationStackCoordinator()
let coordinator = AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(),
@@ -326,7 +329,8 @@ class MockScreen: Identifiable {
let coordinator = UserSessionFlowCoordinator(userSession: MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider()),
navigationSplitCoordinator: navigationSplitCoordinator,
bugReportService: BugReportServiceMock(),
roomTimelineControllerFactory: MockRoomTimelineControllerFactory())
roomTimelineControllerFactory: MockRoomTimelineControllerFactory(),
appSettings: ServiceLocator.shared.settings)
coordinator.start()
@@ -27,6 +27,7 @@ enum UITestsScreenIdentifier: String {
case waitlist
case analyticsPrompt
case analyticsSettingsScreen
case migration
case simpleRegular
case simpleUpgrade
case home
+3
View File
@@ -28,6 +28,9 @@ schemes:
- variable: UI_TESTS_SCREEN
value: ""
isEnabled: false
- variable: RESET_APP_SETTINGS
value: "true"
isEnabled: false
test:
config: Debug
gatherCoverageData: true
@@ -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 MigrationScreenUITests: XCTestCase {
func testRegularScreen() async throws {
let app = Application.launch(.migration)
try await app.assertScreenshot(.migration)
}
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:be0caf4575522004856575896db9e521b132b64ed60e7973be9af121acbbc6eb
size 705140
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:04a9042d779769d3d5f7d9c405ee98c09d10e7b29503784822a9eb5d65fe1335
size 86825
oid sha256:99710fb79e6a3ec46116249dfa10fa7f76e4d260f55ad918706bde3f78e44abb
size 718895
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cb11ec64209cf5ff6ba8c89883179a2b19b1bffc5f4123e475a8854e1a9a35d0
size 445100
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:06364eaf85691663137f97860abd42306c83fa134160de1f9274ab427d1a7db9
size 99246
oid sha256:fc6669feaa5c72bc5eafa0219895c6d7c8ff3d54e77ef41d5b4947016b206a65
size 465131
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:816e426325a232a5d61d062a2e66b949276ade47fd997553f5ed9d97a9113e4a
size 718647
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9b20644e2113d4ccc24d03a3d5818cb36086c83abf00b7a8f64e35d1002bae6d
size 108622
oid sha256:e6e2632eb4a30d943acc2859b517854b2c20aa59289d660c91973670b163e584
size 746877
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:51acefe26737409fe6a0f420eb3482e9614cf95dfd5b5beb62b27e69c1caf0e4
size 470957
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:136e986982afb54c76d94b4e413947f2db0ef194b8c9f02508ac397b5dca2b6c
size 138604
oid sha256:86605b7eb5f4d9fcd48a9ee0cf4e9e6e66a5b07673369392bc8304411d16078b
size 511376
@@ -0,0 +1,24 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import XCTest
@testable import ElementX
@MainActor
class MigrationScreenViewModelTests: XCTestCase {
// Nothing to test, the view model has no mutable state.
}
+1
View File
@@ -0,0 +1 @@
Show a migration screen on the first use of the app whilst the proxy does an initial sync.
+1 -1
View File
@@ -29,7 +29,7 @@ settings:
APP_NAME: ElementX
APP_DISPLAY_NAME: Element X
KEYCHAIN_ACCESS_GROUP_IDENTIFIER: $(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)
MARKETING_VERSION: 1.1.6
MARKETING_VERSION: 1.1.7
CURRENT_PROJECT_VERSION: 1
DEVELOPMENT_TEAM: 7J4U792NQT