Add encryption history banner and update session verification banner strings. (#1250)

* Add a hard wall on back-pagination in encrypted rooms.
Until the app supports key backup, the history will never be decryptable.

* Fix initial display of the timeline table view.

* Update session verification banner strings.
This commit is contained in:
Doug
2023-07-05 14:08:31 +01:00
committed by GitHub
parent 29d90dd29e
commit 6b8b5a75b3
16 changed files with 172 additions and 36 deletions
+19 -11
View File
@@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 54; objectVersion = 51;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@@ -415,6 +415,7 @@
988BA75A182738150894A23F /* UserIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */; }; 988BA75A182738150894A23F /* UserIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */; };
992477AB8E3F3C36D627D32E /* OnboardingViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BC4437C107D52ED19357DFC /* OnboardingViewModelProtocol.swift */; }; 992477AB8E3F3C36D627D32E /* OnboardingViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BC4437C107D52ED19357DFC /* OnboardingViewModelProtocol.swift */; };
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; }; 992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
9965CB800CE6BC74ACA969FC /* EncryptedHistoryRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75697AB5E64A12F1F069F511 /* EncryptedHistoryRoomTimelineView.swift */; };
99ED42B8F8D6BFB1DBCF4C45 /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = D661CAB418C075A94306A792 /* AnalyticsEvents */; }; 99ED42B8F8D6BFB1DBCF4C45 /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = D661CAB418C075A94306A792 /* AnalyticsEvents */; };
99F8DA4CCC6772EE5FE68E24 /* ViewModelContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 818CBE6249ED6E8FC30E8366 /* ViewModelContext.swift */; }; 99F8DA4CCC6772EE5FE68E24 /* ViewModelContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 818CBE6249ED6E8FC30E8366 /* ViewModelContext.swift */; };
9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; 9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; };
@@ -440,7 +441,6 @@
9EBDC79CAC9B63A0D626E333 /* LegalInformationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */; }; 9EBDC79CAC9B63A0D626E333 /* LegalInformationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EB2CAA266B921D128C35710 /* LegalInformationScreenCoordinator.swift */; };
9F19096BFA629C0AC282B1E4 /* CreateRoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CEB4634C0DD7779C4AB504 /* CreateRoomScreenUITests.swift */; }; 9F19096BFA629C0AC282B1E4 /* CreateRoomScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CEB4634C0DD7779C4AB504 /* CreateRoomScreenUITests.swift */; };
9FAF6DA7E8E85C9699757764 /* CollapsibleRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */; }; 9FAF6DA7E8E85C9699757764 /* CollapsibleRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */; };
A002DDF12A557DFF00228A9F /* AnalyticsLocationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A002DDF02A557DFF00228A9F /* AnalyticsLocationType.swift */; };
A009BDFB0A6816D4C392ADCB /* SettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */; }; A009BDFB0A6816D4C392ADCB /* SettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */; };
A021827B528F1EDC9101CA58 /* AppCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBC776F301D374A3298C69DA /* AppCoordinatorProtocol.swift */; }; A021827B528F1EDC9101CA58 /* AppCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBC776F301D374A3298C69DA /* AppCoordinatorProtocol.swift */; };
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */; }; A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */; };
@@ -493,6 +493,7 @@
AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */; }; AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */; };
B037C365CF8A58A0D149A2DB /* AuthenticationIconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97755C01C3971474EFAD5367 /* AuthenticationIconImage.swift */; }; B037C365CF8A58A0D149A2DB /* AuthenticationIconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97755C01C3971474EFAD5367 /* AuthenticationIconImage.swift */; };
B064D42BA087649ACAE462E8 /* SoftLogoutUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */; }; B064D42BA087649ACAE462E8 /* SoftLogoutUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */; };
B09DC6E3D0EE87C4D4ABFAB3 /* EncryptedHistoryRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0140615D2232612C813FD6C /* EncryptedHistoryRoomTimelineItem.swift */; };
B0CB16349B96262AA65A04AF /* URLRouting in Frameworks */ = {isa = PBXBuildFile; productRef = E9BAB8A793FE3B54CDD47102 /* URLRouting */; }; B0CB16349B96262AA65A04AF /* URLRouting in Frameworks */ = {isa = PBXBuildFile; productRef = E9BAB8A793FE3B54CDD47102 /* URLRouting */; };
B1069F361E604D5436AE9FFD /* StaticLocationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B06663F7858E45882E63471 /* StaticLocationScreen.swift */; }; B1069F361E604D5436AE9FFD /* StaticLocationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B06663F7858E45882E63471 /* StaticLocationScreen.swift */; };
B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; }; B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; };
@@ -665,6 +666,7 @@
EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; }; EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; };
EC280623A42904341363EAAF /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; }; EC280623A42904341363EAAF /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; };
ECA636DAF071C611FDC2BB57 /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; ECA636DAF071C611FDC2BB57 /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; };
EDC1031A7CFB3406A9DA3175 /* AnalyticsLocationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD6299F4516797E9BBE14C3 /* AnalyticsLocationType.swift */; };
EDF8919F15DE0FF00EF99E70 /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */; }; EDF8919F15DE0FF00EF99E70 /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */; };
EE4F5601356228FF72FC56B6 /* MockClientProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F40F48279322E504153AB0D /* MockClientProxy.swift */; }; EE4F5601356228FF72FC56B6 /* MockClientProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F40F48279322E504153AB0D /* MockClientProxy.swift */; };
EE6933C935080B4E0348A58B /* EmojiMartCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5C3AACCAA82392D08924496 /* EmojiMartCategory.swift */; }; EE6933C935080B4E0348A58B /* EmojiMartCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5C3AACCAA82392D08924496 /* EmojiMartCategory.swift */; };
@@ -826,7 +828,7 @@
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>"; };
12EDAFB64FA5F6812D54F39A /* MigrationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenViewModel.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>"; }; 12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenCoordinator.swift; sourceTree = "<group>"; };
1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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>"; };
1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; }; 1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
@@ -961,7 +963,7 @@
47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.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>"; }; 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineView.swift; sourceTree = "<group>"; };
47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenModels.swift; sourceTree = "<group>"; }; 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenModels.swift; sourceTree = "<group>"; };
478BE8591BD13E908EF70C0C /* DesignKit */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DesignKit; sourceTree = SOURCE_ROOT; }; 478BE8591BD13E908EF70C0C /* DesignKit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = DesignKit; path = DesignKit; sourceTree = SOURCE_ROOT; };
4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FramePreferenceKey.swift; sourceTree = "<group>"; }; 4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FramePreferenceKey.swift; sourceTree = "<group>"; };
47EBB5D698CE9A25BB553A2D /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; }; 47EBB5D698CE9A25BB553A2D /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModel.swift; sourceTree = "<group>"; }; 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModel.swift; sourceTree = "<group>"; };
@@ -970,6 +972,7 @@
49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNNotificationRequest.swift; sourceTree = "<group>"; }; 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNNotificationRequest.swift; sourceTree = "<group>"; };
4A542BC40D6EC2E66BC5659B /* TextBasedRoomTimelineViewMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewMock.swift; sourceTree = "<group>"; }; 4A542BC40D6EC2E66BC5659B /* TextBasedRoomTimelineViewMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineViewMock.swift; sourceTree = "<group>"; };
4AB7D7DAAAF662DED9D02379 /* MockMediaLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaLoader.swift; sourceTree = "<group>"; }; 4AB7D7DAAAF662DED9D02379 /* MockMediaLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaLoader.swift; sourceTree = "<group>"; };
4AD6299F4516797E9BBE14C3 /* AnalyticsLocationType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsLocationType.swift; sourceTree = "<group>"; };
4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = "<group>"; }; 4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = "<group>"; };
4B5046BB295AEAFA6FB81655 /* SessionVerificationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenModels.swift; sourceTree = "<group>"; }; 4B5046BB295AEAFA6FB81655 /* SessionVerificationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenModels.swift; sourceTree = "<group>"; };
4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = "<group>"; }; 4BD371B60E07A5324B9507EF /* AnalyticsSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenCoordinator.swift; sourceTree = "<group>"; };
@@ -1082,6 +1085,7 @@
7475C5AE20BA896930907EA8 /* AudioRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRoomTimelineItemContent.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenCoordinator.swift; sourceTree = "<group>"; };
75697AB5E64A12F1F069F511 /* EncryptedHistoryRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedHistoryRoomTimelineView.swift; sourceTree = "<group>"; };
75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenUITests.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>"; }; 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>"; }; 78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenViewModelProtocol.swift; sourceTree = "<group>"; };
@@ -1128,7 +1132,7 @@
8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineProvider.swift; sourceTree = "<group>"; }; 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineProvider.swift; sourceTree = "<group>"; };
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = "<group>"; }; 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = "<group>"; };
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = "<group>"; }; 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = "<group>"; };
8E1BBA73B611EDEEA6E20E05 /* InvitesScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenModels.swift; sourceTree = "<group>"; }; 8E1BBA73B611EDEEA6E20E05 /* InvitesScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenModels.swift; sourceTree = "<group>"; };
8EC57A32ABC80D774CC663DB /* SettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenUITests.swift; sourceTree = "<group>"; }; 8EC57A32ABC80D774CC663DB /* SettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenUITests.swift; sourceTree = "<group>"; };
8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = "<group>"; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = "<group>"; };
@@ -1172,7 +1176,6 @@
9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = "<group>"; }; 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = "<group>"; };
9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = "<group>"; }; 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = "<group>"; };
9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = "<group>"; }; 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = "<group>"; };
A002DDF02A557DFF00228A9F /* AnalyticsLocationType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsLocationType.swift; sourceTree = "<group>"; };
A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; }; A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; };
A05707BF550D770168A406DB /* LoginViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModelTests.swift; sourceTree = "<group>"; }; A05707BF550D770168A406DB /* LoginViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModelTests.swift; sourceTree = "<group>"; };
A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; }; A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; };
@@ -1235,7 +1238,7 @@
B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Analytics+SwiftUI.swift"; sourceTree = "<group>"; }; B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Analytics+SwiftUI.swift"; sourceTree = "<group>"; };
B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = "<group>"; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = "<group>"; };
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; lastKnownFileType = file.bplist; 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>"; }; 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>"; };
@@ -1312,8 +1315,9 @@
CD6B0C4639E066915B5E6463 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; }; CD6B0C4639E066915B5E6463 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = "<group>"; }; CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = "<group>"; };
CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = "<group>"; }; CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = "<group>"; };
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = "<group>"; }; CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = "<group>"; };
CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxy.swift; sourceTree = "<group>"; }; CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxy.swift; sourceTree = "<group>"; };
D0140615D2232612C813FD6C /* EncryptedHistoryRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedHistoryRoomTimelineItem.swift; sourceTree = "<group>"; };
D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = "<group>"; }; D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = "<group>"; };
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; }; D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; }; D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
@@ -1382,7 +1386,7 @@
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>"; };
ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = "<group>"; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = "<group>"; };
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = "<group>"; }; ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = "<group>"; };
ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = "<group>"; }; ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = "<group>"; };
EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = "<group>"; }; EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = "<group>"; };
EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = "<group>"; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = "<group>"; };
@@ -2071,7 +2075,7 @@
E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */, E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */,
D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */, D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */,
57B6B383F1FD04CC0E7B60C6 /* AnalyticsConsentState.swift */, 57B6B383F1FD04CC0E7B60C6 /* AnalyticsConsentState.swift */,
A002DDF02A557DFF00228A9F /* AnalyticsLocationType.swift */, 4AD6299F4516797E9BBE14C3 /* AnalyticsLocationType.swift */,
FEFEEE93B82937B2E86F92EB /* AnalyticsScreen.swift */, FEFEEE93B82937B2E86F92EB /* AnalyticsScreen.swift */,
5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */, 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */,
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */, A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */,
@@ -3028,6 +3032,7 @@
FC2D505742FDA21FCDC4C18A /* AudioRoomTimelineView.swift */, FC2D505742FDA21FCDC4C18A /* AudioRoomTimelineView.swift */,
6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */, 6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */,
471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */, 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */,
75697AB5E64A12F1F069F511 /* EncryptedHistoryRoomTimelineView.swift */,
56C1BCB9E83B09A45387FCA2 /* EncryptedRoomTimelineView.swift */, 56C1BCB9E83B09A45387FCA2 /* EncryptedRoomTimelineView.swift */,
E51E3D86A84341C3A0CB8A40 /* FileRoomTimelineView.swift */, E51E3D86A84341C3A0CB8A40 /* FileRoomTimelineView.swift */,
F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */, F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */,
@@ -3223,6 +3228,7 @@
D977D4E565C06D3F41C8F8FC /* Virtual */ = { D977D4E565C06D3F41C8F8FC /* Virtual */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D0140615D2232612C813FD6C /* EncryptedHistoryRoomTimelineItem.swift */,
0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */, 0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */,
DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */, DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */,
C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */, C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */,
@@ -4029,6 +4035,7 @@
F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */, F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */,
54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */, 54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */,
8DDC6F28C797D8685F2F8E32 /* AnalyticsConsentState.swift in Sources */, 8DDC6F28C797D8685F2F8E32 /* AnalyticsConsentState.swift in Sources */,
EDC1031A7CFB3406A9DA3175 /* AnalyticsLocationType.swift in Sources */,
9DF3F6318A4402305F5EB869 /* AnalyticsPromptScreen.swift in Sources */, 9DF3F6318A4402305F5EB869 /* AnalyticsPromptScreen.swift in Sources */,
10516CF20E8B5852F4C444FD /* AnalyticsPromptScreenCheckmarkItem.swift in Sources */, 10516CF20E8B5852F4C444FD /* AnalyticsPromptScreenCheckmarkItem.swift in Sources */,
5F28C9146694B381BB82E18C /* AnalyticsPromptScreenCoordinator.swift in Sources */, 5F28C9146694B381BB82E18C /* AnalyticsPromptScreenCoordinator.swift in Sources */,
@@ -4133,6 +4140,8 @@
8B41D0357B91CD3B6F6A3BCA /* EmoteRoomTimelineItemContent.swift in Sources */, 8B41D0357B91CD3B6F6A3BCA /* EmoteRoomTimelineItemContent.swift in Sources */,
68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */, 68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */,
8B1D5CE017EEC734CF5FE130 /* Encodable.swift in Sources */, 8B1D5CE017EEC734CF5FE130 /* Encodable.swift in Sources */,
B09DC6E3D0EE87C4D4ABFAB3 /* EncryptedHistoryRoomTimelineItem.swift in Sources */,
9965CB800CE6BC74ACA969FC /* EncryptedHistoryRoomTimelineView.swift in Sources */,
4C5A638DAA8AF64565BA4866 /* EncryptedRoomTimelineItem.swift in Sources */, 4C5A638DAA8AF64565BA4866 /* EncryptedRoomTimelineItem.swift in Sources */,
B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */, B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */,
69ABFBAF05D7EF11E7C88CEA /* EncryptionSyncListenerProxy.swift in Sources */, 69ABFBAF05D7EF11E7C88CEA /* EncryptionSyncListenerProxy.swift in Sources */,
@@ -4300,7 +4309,6 @@
46A261AA898344A1F3C406B1 /* ReportContentScreenModels.swift in Sources */, 46A261AA898344A1F3C406B1 /* ReportContentScreenModels.swift in Sources */,
42A5A42ACF063EEE6B1980D2 /* ReportContentScreenViewModel.swift in Sources */, 42A5A42ACF063EEE6B1980D2 /* ReportContentScreenViewModel.swift in Sources */,
8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */, 8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */,
A002DDF12A557DFF00228A9F /* AnalyticsLocationType.swift in Sources */,
A494741843F087881299ACF0 /* RestorationToken.swift in Sources */, A494741843F087881299ACF0 /* RestorationToken.swift in Sources */,
755EE5B0998C6A4D764D86E5 /* RoomAttachmentPicker.swift in Sources */, 755EE5B0998C6A4D764D86E5 /* RoomAttachmentPicker.swift in Sources */,
0BDA19079FD6E17C5AC62E22 /* RoomDetailsEditScreen.swift in Sources */, 0BDA19079FD6E17C5AC62E22 /* RoomDetailsEditScreen.swift in Sources */,
@@ -283,6 +283,7 @@
"screen_room_details_room_name_label" = "Room name"; "screen_room_details_room_name_label" = "Room name";
"screen_room_details_share_room_title" = "Share room"; "screen_room_details_share_room_title" = "Share room";
"screen_room_details_updating_room" = "Updating room…"; "screen_room_details_updating_room" = "Updating room…";
"screen_room_encrypted_history_banner" = "Message history is currently unavailable in this room";
"screen_room_error_failed_retrieving_user_details" = "Could not retrieve user details"; "screen_room_error_failed_retrieving_user_details" = "Could not retrieve user details";
"screen_room_invite_again_alert_message" = "Would you like to invite them back?"; "screen_room_invite_again_alert_message" = "Would you like to invite them back?";
"screen_room_invite_again_alert_title" = "You are alone in this chat"; "screen_room_invite_again_alert_title" = "You are alone in this chat";
@@ -335,8 +336,8 @@
"screen_waitlist_message_success" = "Welcome to %1$@!"; "screen_waitlist_message_success" = "Welcome to %1$@!";
"screen_waitlist_title" = "You’re almost there."; "screen_waitlist_title" = "You’re almost there.";
"screen_waitlist_title_success" = "You're in."; "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_message" = "Looks like you’re using a new device. Verify with another device to access your encrypted messages moving forwards.";
"session_verification_banner_title" = "Access your message history"; "session_verification_banner_title" = "Verify it’s you";
"settings_rageshake" = "Rageshake"; "settings_rageshake" = "Rageshake";
"settings_rageshake_detection_threshold" = "Detection threshold"; "settings_rageshake_detection_threshold" = "Detection threshold";
"settings_title_general" = "General"; "settings_title_general" = "General";
@@ -22,6 +22,7 @@ final class AppSettings {
private enum UserDefaultsKeys: String { private enum UserDefaultsKeys: String {
case lastVersionLaunched case lastVersionLaunched
case seenInvites case seenInvites
case lastLoginDate
case migratedAccounts case migratedAccounts
case timelineStyle case timelineStyle
case analyticsConsentState case analyticsConsentState
@@ -105,6 +106,13 @@ final class AppSettings {
/// Any pre-defined static client registrations for OIDC issuers. /// Any pre-defined static client registrations for OIDC issuers.
let oidcStaticRegistrations: [URL: String] = ["https://id.thirdroom.io/realms/thirdroom": "elementx"] let oidcStaticRegistrations: [URL: String] = ["https://id.thirdroom.io/realms/thirdroom": "elementx"]
/// The date that the call to `/login` completed successfully. This is used to put
/// a hard wall on the history of encrypted messages until we have key backup.
///
/// Not a multi-account aware setting as key backup will come before multi-account.
@UserPreference(key: UserDefaultsKeys.lastLoginDate, defaultValue: nil, storageType: .userDefaults(store))
var lastLoginDate: Date?
/// A dictionary of accounts that have performed an initial sync through their proxy. /// 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 /// This is a temporary workaround. In the future we should be able to receive a signal from the
@@ -271,15 +271,14 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
self.roomProxy = roomProxy self.roomProxy = roomProxy
let userId = userSession.clientProxy.userID let userID = userSession.clientProxy.userID
let timelineItemFactory = RoomTimelineItemFactory(userID: userId, let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
mediaProvider: userSession.mediaProvider, mediaProvider: userSession.mediaProvider,
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: appSettings.permalinkBaseURL), attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: appSettings.permalinkBaseURL),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userId)) stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(userId: userId, let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy,
roomProxy: roomProxy,
timelineItemFactory: timelineItemFactory, timelineItemFactory: timelineItemFactory,
mediaProvider: userSession.mediaProvider) mediaProvider: userSession.mediaProvider)
self.timelineController = timelineController self.timelineController = timelineController
+4 -2
View File
@@ -718,6 +718,8 @@ public enum L10n {
public static var screenRoomDetailsTopicTitle: String { return L10n.tr("Localizable", "screen_room_details_topic_title") } public static var screenRoomDetailsTopicTitle: String { return L10n.tr("Localizable", "screen_room_details_topic_title") }
/// Updating room… /// Updating room…
public static var screenRoomDetailsUpdatingRoom: String { return L10n.tr("Localizable", "screen_room_details_updating_room") } public static var screenRoomDetailsUpdatingRoom: String { return L10n.tr("Localizable", "screen_room_details_updating_room") }
/// Message history is currently unavailable in this room
public static var screenRoomEncryptedHistoryBanner: String { return L10n.tr("Localizable", "screen_room_encrypted_history_banner") }
/// Failed processing media to upload, please try again. /// Failed processing media to upload, please try again.
public static var screenRoomErrorFailedProcessingMedia: String { return L10n.tr("Localizable", "screen_room_error_failed_processing_media") } public static var screenRoomErrorFailedProcessingMedia: String { return L10n.tr("Localizable", "screen_room_error_failed_processing_media") }
/// Could not retrieve user details /// Could not retrieve user details
@@ -848,9 +850,9 @@ public enum L10n {
public static var screenWaitlistTitle: String { return L10n.tr("Localizable", "screen_waitlist_title") } 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") } 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. /// Looks like you’re using a new device. Verify with another device to access your encrypted messages moving forwards.
public static var sessionVerificationBannerMessage: String { return L10n.tr("Localizable", "session_verification_banner_message") } public static var sessionVerificationBannerMessage: String { return L10n.tr("Localizable", "session_verification_banner_message") }
/// Access your message history /// Verify it’s you
public static var sessionVerificationBannerTitle: String { return L10n.tr("Localizable", "session_verification_banner_title") } public static var sessionVerificationBannerTitle: String { return L10n.tr("Localizable", "session_verification_banner_title") }
/// Rageshake /// Rageshake
public static var settingsRageshake: String { return L10n.tr("Localizable", "settings_rageshake") } public static var settingsRageshake: String { return L10n.tr("Localizable", "settings_rageshake") }
@@ -205,6 +205,8 @@ class AuthenticationCoordinator: CoordinatorProtocol {
} }
private func userHasSignedIn(userSession: UserSessionProtocol) { private func userHasSignedIn(userSession: UserSessionProtocol) {
appSettings.lastLoginDate = .now
showAnalyticsPromptIfNeeded { [weak self] in showAnalyticsPromptIfNeeded { [weak self] in
guard let self else { return } guard let self else { return }
self.delegate?.authenticationCoordinator(self, didLoginWithSession: userSession) self.delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
@@ -0,0 +1,61 @@
//
// 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
/// The item shown when all previous items are un-decryptable due to
/// key backup not yet being supported in the app.
struct EncryptedHistoryRoomTimelineView: View {
let timelineItem: EncryptedHistoryRoomTimelineItem
var body: some View {
Label {
Text(L10n.screenRoomEncryptedHistoryBanner)
.font(.compound.bodyMDSemibold)
.foregroundColor(.compound.textInfoPrimary)
} icon: {
Image(systemName: "info.circle.fill")
.foregroundColor(.compound.iconInfoPrimary)
}
.labelStyle(EncryptedHistoryLabelStyle())
.padding(16)
.background {
RoundedRectangle(cornerRadius: 8)
.fill(Color.compound.bgInfoSubtle)
RoundedRectangle(cornerRadius: 8)
.stroke(Color.compound.borderInfoSubtle)
}
.frame(maxWidth: .infinity)
.padding(.horizontal, 8)
.padding(.vertical, 16)
}
}
private struct EncryptedHistoryLabelStyle: LabelStyle {
func makeBody(configuration: Configuration) -> some View {
HStack(alignment: .firstTextBaseline, spacing: 16) {
configuration.icon
configuration.title
}
}
}
struct EncryptedHistoryRoomTimelineView_Previews: PreviewProvider {
static var previews: some View {
let item = EncryptedHistoryRoomTimelineItem(id: UUID().uuidString)
EncryptedHistoryRoomTimelineView(timelineItem: item)
}
}
@@ -119,6 +119,13 @@ class TimelineTableViewController: UIViewController {
// for each possible cell, causing layout issues // for each possible cell, causing layout issues
tableView.accessibilityElementsHidden = Tests.shouldDisableTimelineAccessibility tableView.accessibilityElementsHidden = Tests.shouldDisableTimelineAccessibility
tableView.publisher(for: \.contentSize)
.removeDuplicates()
.sink { [weak self] _ in
self?.updateTopPadding()
}
.store(in: &cancellables)
scrollToBottomPublisher scrollToBottomPublisher
.sink { [weak self] _ in .sink { [weak self] _ in
self?.scrollToBottom(animated: true) self?.scrollToBottom(animated: true)
@@ -242,9 +249,11 @@ class TimelineTableViewController: UIViewController {
snapshot.appendSections([.main]) snapshot.appendSections([.main])
snapshot.appendItems(timelineItemsIDs) snapshot.appendItems(timelineItemsIDs)
dataSource.apply(snapshot, animatingDifferences: false) dataSource.apply(snapshot, animatingDifferences: false)
// Probably redundant now we observe content size changes…
// Leaving in place for the release and will reassess after.
updateTopPadding() updateTopPadding()
if previousLayout.isBottomVisible { if previousLayout.isBottomVisible {
scrollToBottom(animated: false) scrollToBottom(animated: false)
} else if let pinnedItem = previousLayout.pinnedItem { } else if let pinnedItem = previousLayout.pinnedItem {
@@ -283,7 +292,8 @@ class TimelineTableViewController: UIViewController {
let contentHeight = tableView.contentSize.height - headerHeight let contentHeight = tableView.contentSize.height - headerHeight
let newHeight = max(0, tableView.visibleSize.height - contentHeight) let newHeight = max(0, tableView.visibleSize.height - contentHeight)
guard newHeight != headerHeight else { return } // Round the check to account floating point accuracy during keyboard appearance.
guard newHeight.rounded() != headerHeight.rounded() else { return }
if newHeight > 0 { if newHeight > 0 {
let frame = CGRect(origin: .zero, size: CGSize(width: tableView.contentSize.width, height: newHeight)) let frame = CGRect(origin: .zero, size: CGSize(width: tableView.contentSize.width, height: newHeight))
@@ -17,8 +17,7 @@
import Foundation import Foundation
struct MockRoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { struct MockRoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol {
func buildRoomTimelineController(userId: String, func buildRoomTimelineController(roomProxy: RoomProxyProtocol,
roomProxy: RoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol { mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol {
let timelineController = MockRoomTimelineController() let timelineController = MockRoomTimelineController()
@@ -19,7 +19,6 @@ import Foundation
import UIKit import UIKit
class RoomTimelineController: RoomTimelineControllerProtocol { class RoomTimelineController: RoomTimelineControllerProtocol {
private let userId: String
private let roomProxy: RoomProxyProtocol private let roomProxy: RoomProxyProtocol
private let timelineProvider: RoomTimelineProviderProtocol private let timelineProvider: RoomTimelineProviderProtocol
private let timelineItemFactory: RoomTimelineItemFactoryProtocol private let timelineItemFactory: RoomTimelineItemFactoryProtocol
@@ -42,12 +41,10 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
roomProxy.id roomProxy.id
} }
init(userId: String, init(roomProxy: RoomProxyProtocol,
roomProxy: RoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol, mediaProvider: MediaProviderProtocol,
appSettings: AppSettings) { appSettings: AppSettings) {
self.userId = userId
self.roomProxy = roomProxy self.roomProxy = roomProxy
timelineProvider = roomProxy.timelineProvider timelineProvider = roomProxy.timelineProvider
self.timelineItemFactory = timelineItemFactory self.timelineItemFactory = timelineItemFactory
@@ -246,6 +243,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
var newTimelineItems = [RoomTimelineItemProtocol]() var newTimelineItems = [RoomTimelineItemProtocol]()
var canBackPaginate = true var canBackPaginate = true
var isBackPaginating = false var isBackPaginating = false
var lastEncryptedHistoryItemIndex: Int?
let collapsibleChunks = timelineProvider.itemsPublisher.value.groupBy { isItemCollapsible($0) } let collapsibleChunks = timelineProvider.itemsPublisher.value.groupBy { isItemCollapsible($0) }
@@ -264,6 +262,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
isBackPaginating = true isBackPaginating = true
} else if timelineItem is TimelineStartRoomTimelineItem { } else if timelineItem is TimelineStartRoomTimelineItem {
canBackPaginate = false canBackPaginate = false
} else if timelineItem is EncryptedHistoryRoomTimelineItem {
canBackPaginate = false
} }
return timelineItem return timelineItem
@@ -280,11 +280,21 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
continue continue
} }
if timelineItem is EncryptedHistoryRoomTimelineItem {
lastEncryptedHistoryItemIndex = newTimelineItems.endIndex
}
newTimelineItems.append(timelineItem) newTimelineItems.append(timelineItem)
} else { } else {
newTimelineItems.append(CollapsibleTimelineItem(items: items)) newTimelineItems.append(CollapsibleTimelineItem(items: items))
} }
} }
if let lastEncryptedHistoryItemIndex {
// Remove everything up to the last encrypted history item.
// It only contains encrypted messages, state changes and date separators.
newTimelineItems.removeFirst(lastEncryptedHistoryItemIndex)
}
timelineItems = newTimelineItems timelineItems = newTimelineItems
@@ -298,6 +308,10 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
case .event(let eventTimelineItem): case .event(let eventTimelineItem):
let timelineItem = timelineItemFactory.buildTimelineItem(for: eventTimelineItem) let timelineItem = timelineItemFactory.buildTimelineItem(for: eventTimelineItem)
if timelineItem is EncryptedRoomTimelineItem, isItemInEncryptionHistory(eventTimelineItem) {
return EncryptedHistoryRoomTimelineItem(id: eventTimelineItem.id)
}
if let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol { if let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol {
// Avoid fetching this over and over again as it changes states if it keeps failing to load // Avoid fetching this over and over again as it changes states if it keeps failing to load
// Errors will be handled again on appearance // Errors will be handled again on appearance
@@ -326,6 +340,13 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
} }
} }
/// Whether or not a specific item is part of the room's history that can't be decrypted due
/// to the lack of key-backup. This is handled differently so we only show a single item.
private func isItemInEncryptionHistory(_ itemProxy: EventTimelineItemProxy) -> Bool {
guard roomProxy.isEncrypted, let lastLoginDate = appSettings.lastLoginDate else { return false }
return itemProxy.timestamp < lastLoginDate
}
private func isItemCollapsible(_ item: TimelineItemProxy) -> Bool { private func isItemCollapsible(_ item: TimelineItemProxy) -> Bool {
if !appSettings.shouldCollapseRoomStateEvents { if !appSettings.shouldCollapseRoomStateEvents {
return false return false
@@ -17,12 +17,10 @@
import Foundation import Foundation
struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol { struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol {
func buildRoomTimelineController(userId: String, func buildRoomTimelineController(roomProxy: RoomProxyProtocol,
roomProxy: RoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol { mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol {
RoomTimelineController(userId: userId, RoomTimelineController(roomProxy: roomProxy,
roomProxy: roomProxy,
timelineItemFactory: timelineItemFactory, timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider, mediaProvider: mediaProvider,
appSettings: ServiceLocator.shared.settings) appSettings: ServiceLocator.shared.settings)
@@ -18,8 +18,7 @@ import Foundation
@MainActor @MainActor
protocol RoomTimelineControllerFactoryProtocol { protocol RoomTimelineControllerFactoryProtocol {
func buildRoomTimelineController(userId: String, func buildRoomTimelineController(roomProxy: RoomProxyProtocol,
roomProxy: RoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol
} }
@@ -0,0 +1,21 @@
//
// 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 Foundation
struct EncryptedHistoryRoomTimelineItem: DecorationTimelineItemProtocol, Identifiable, Hashable {
let id: String
}
@@ -55,6 +55,8 @@ struct RoomTimelineItemView: View {
UnsupportedRoomTimelineView(timelineItem: item) UnsupportedRoomTimelineView(timelineItem: item)
case .timelineStart(let item): case .timelineStart(let item):
TimelineStartRoomTimelineView(timelineItem: item) TimelineStartRoomTimelineView(timelineItem: item)
case .encryptedHistory(let item):
EncryptedHistoryRoomTimelineView(timelineItem: item)
case .state(let item): case .state(let item):
StateRoomTimelineView(timelineItem: item) StateRoomTimelineView(timelineItem: item)
case .group(let item): case .group(let item):
@@ -58,6 +58,7 @@ enum RoomTimelineItemType: Equatable {
case sticker(StickerRoomTimelineItem) case sticker(StickerRoomTimelineItem)
case unsupported(UnsupportedRoomTimelineItem) case unsupported(UnsupportedRoomTimelineItem)
case timelineStart(TimelineStartRoomTimelineItem) case timelineStart(TimelineStartRoomTimelineItem)
case encryptedHistory(EncryptedHistoryRoomTimelineItem)
case state(StateRoomTimelineItem) case state(StateRoomTimelineItem)
case group(CollapsibleTimelineItem) case group(CollapsibleTimelineItem)
case location(LocationRoomTimelineItem) case location(LocationRoomTimelineItem)
@@ -95,6 +96,8 @@ enum RoomTimelineItemType: Equatable {
self = .unsupported(item) self = .unsupported(item)
case let item as TimelineStartRoomTimelineItem: case let item as TimelineStartRoomTimelineItem:
self = .timelineStart(item) self = .timelineStart(item)
case let item as EncryptedHistoryRoomTimelineItem:
self = .encryptedHistory(item)
case let item as StateRoomTimelineItem: case let item as StateRoomTimelineItem:
self = .state(item) self = .state(item)
case let item as CollapsibleTimelineItem: case let item as CollapsibleTimelineItem:
@@ -123,6 +126,7 @@ enum RoomTimelineItemType: Equatable {
.sticker(let item as RoomTimelineItemProtocol), .sticker(let item as RoomTimelineItemProtocol),
.unsupported(let item as RoomTimelineItemProtocol), .unsupported(let item as RoomTimelineItemProtocol),
.timelineStart(let item as RoomTimelineItemProtocol), .timelineStart(let item as RoomTimelineItemProtocol),
.encryptedHistory(let item as RoomTimelineItemProtocol),
.state(let item as RoomTimelineItemProtocol), .state(let item as RoomTimelineItemProtocol),
.group(let item as RoomTimelineItemProtocol), .group(let item as RoomTimelineItemProtocol),
.location(let item as RoomTimelineItemProtocol): .location(let item as RoomTimelineItemProtocol):
@@ -137,7 +141,7 @@ enum RoomTimelineItemType: Equatable {
return true return true
case .redacted, .encrypted, .unsupported, .state: // Event based items that aren't reactable case .redacted, .encrypted, .unsupported, .state: // Event based items that aren't reactable
return false return false
case .timelineStart, .separator, .readMarker, .paginationIndicator: // Virtual items are never reactable case .timelineStart, .encryptedHistory, .separator, .readMarker, .paginationIndicator: // Virtual items are never reactable
return false return false
case .group: case .group:
return false return false
+1
View File
@@ -0,0 +1 @@
Add encryption history banner.