mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
tombstoned and upgraded rooms implementation
added tests tombstoned room avatar
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objectVersion = 63;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
@@ -876,6 +876,7 @@
|
||||
A6FFC4C5154C446BAD6B40D8 /* TimelineItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8520AFD6680CBAD388F6D927 /* TimelineItemProvider.swift */; };
|
||||
A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; };
|
||||
A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; };
|
||||
A7CA45942DEF306400300A02 /* Highlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CA45932DEF306200300A02 /* Highlight.swift */; };
|
||||
A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; };
|
||||
A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCDA016D05107DED3B9495CB /* TimelineItemDebugView.swift */; };
|
||||
A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; };
|
||||
@@ -1396,7 +1397,7 @@
|
||||
044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = "<group>"; };
|
||||
045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
|
||||
046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = "<group>"; };
|
||||
048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = "<group>"; };
|
||||
04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = "<group>"; };
|
||||
0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
@@ -1470,7 +1471,7 @@
|
||||
128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAttachmentPicker.swift; sourceTree = "<group>"; };
|
||||
12B09A94C519227264A41208 /* RoomMembershipDetailsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembershipDetailsProxy.swift; sourceTree = "<group>"; };
|
||||
12FD5280AF55AB7F50F8E47D /* preview_avatar_room.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_avatar_room.jpg; sourceTree = "<group>"; };
|
||||
1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = "<group>"; };
|
||||
1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; sourceTree = "<group>"; };
|
||||
130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = "<group>"; };
|
||||
136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenModels.swift; sourceTree = "<group>"; };
|
||||
13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
@@ -1572,7 +1573,7 @@
|
||||
25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = "<group>"; };
|
||||
25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = "<group>"; };
|
||||
267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = "<group>"; };
|
||||
267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = "<group>"; };
|
||||
26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = "<group>"; };
|
||||
26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = "<group>"; };
|
||||
2711E5996016ABD6EAAEB58A /* LogLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogLevel.swift; sourceTree = "<group>"; };
|
||||
@@ -1648,7 +1649,7 @@
|
||||
3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = "<group>"; };
|
||||
35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = "<group>"; };
|
||||
36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = "<group>"; };
|
||||
37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringTests.swift; sourceTree = "<group>"; };
|
||||
@@ -2063,7 +2064,7 @@
|
||||
8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = "<group>"; };
|
||||
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = "<group>"; };
|
||||
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = "<group>"; };
|
||||
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = "<group>"; };
|
||||
8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreen.swift; sourceTree = "<group>"; };
|
||||
8EAF4A49F3ACD8BB8B0D2371 /* ClientSDKMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientSDKMock.swift; sourceTree = "<group>"; };
|
||||
8F062DD2CCD95DC33528A16F /* KnockRequestProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestProxy.swift; sourceTree = "<group>"; };
|
||||
@@ -2184,6 +2185,7 @@
|
||||
A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = "<group>"; };
|
||||
A7A1B80FE6E3BA72F9C748AD /* AdvancedSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = "<group>"; };
|
||||
A7CA45932DEF306200300A02 /* Highlight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Highlight.swift; sourceTree = "<group>"; };
|
||||
A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftServiceProtocol.swift; sourceTree = "<group>"; };
|
||||
A84D413BF49F0E980F010A6B /* LogViewerScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewerScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
@@ -2269,7 +2271,7 @@
|
||||
B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = "<group>"; };
|
||||
B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = "<group>"; };
|
||||
B5D829FD8958376614504B18 /* TargetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetConfiguration.swift; sourceTree = "<group>"; };
|
||||
B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = "<group>"; };
|
||||
B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = "<group>"; };
|
||||
B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = "<group>"; };
|
||||
B655A536341D2695158C6664 /* AuthenticationClientBuilderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilderFactory.swift; sourceTree = "<group>"; };
|
||||
B65DDCF8E41759890355ACBC /* AuthenticationStartScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@@ -2297,7 +2299,7 @@
|
||||
BA40B98B098B6F0371B750B3 /* TemplateScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenModels.swift; sourceTree = "<group>"; };
|
||||
BA919F521E9F0EE3638AFC85 /* BugReportScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreen.swift; sourceTree = "<group>"; };
|
||||
BB284643AF7AB131E307DCE0 /* AudioSessionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioSessionProtocol.swift; sourceTree = "<group>"; };
|
||||
BB576F4118C35E6B5124FA22 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = "<group>"; };
|
||||
BB576F4118C35E6B5124FA22 /* test_apple_image.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_apple_image.heic; sourceTree = "<group>"; };
|
||||
BB5B00A014307CE37B2812CD /* TimelineViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
BB6ED50FE104992419310EEB /* NotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandler.swift; sourceTree = "<group>"; };
|
||||
BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
@@ -2396,7 +2398,7 @@
|
||||
CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = "<group>"; };
|
||||
CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = "<group>"; };
|
||||
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = "<group>"; };
|
||||
D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.swift; sourceTree = "<group>"; };
|
||||
D03D7ECAC68C2FFB8CF01BCB /* DeactivateAccountScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreen.swift; sourceTree = "<group>"; };
|
||||
D046ABB22E680F7C5054441B /* SecurityAndPrivacyScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@@ -2459,7 +2461,7 @@
|
||||
DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNNotification+Creator.swift"; sourceTree = "<group>"; };
|
||||
DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollInteractionHandler.swift; sourceTree = "<group>"; };
|
||||
DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = "<group>"; };
|
||||
DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = "<group>"; };
|
||||
DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionModels.swift; sourceTree = "<group>"; };
|
||||
DCDAB580109C09A6AA97AF7E /* PollFormScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenTests.swift; sourceTree = "<group>"; };
|
||||
DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenModels.swift; sourceTree = "<group>"; };
|
||||
@@ -2500,7 +2502,7 @@
|
||||
E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashDecode.swift; sourceTree = "<group>"; };
|
||||
E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreen.swift; sourceTree = "<group>"; };
|
||||
E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = "<group>"; };
|
||||
E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = "<group>"; };
|
||||
E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = "<group>"; };
|
||||
E5F2B6443D1ED8602F328539 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
E5FDFAA04174CC99FB66391C /* EditRoomAddressScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditRoomAddressScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
@@ -2542,7 +2544,7 @@
|
||||
ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||
ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = "<group>"; };
|
||||
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = "<group>"; };
|
||||
ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = "<group>"; };
|
||||
EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = "<group>"; };
|
||||
@@ -3327,6 +3329,7 @@
|
||||
328DD5DA1281F758B72006C7 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A7CA45932DEF306200300A02 /* Highlight.swift */,
|
||||
8F21ED7205048668BEB44A38 /* AppActivityView.swift */,
|
||||
CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */,
|
||||
9A028783CFFF861C5E44FFB1 /* BadgeLabel.swift */,
|
||||
@@ -6471,7 +6474,6 @@
|
||||
EC6D0C817B1C21D9D096505A /* XCRemoteSwiftPackageReference "Version" */,
|
||||
EE40B0E16A55BD23ECBFFD22 /* XCRemoteSwiftPackageReference "matrix-rich-text-editor-swift" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 54;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
@@ -7635,6 +7637,7 @@
|
||||
FA71CD334F2D2289BEF0D749 /* SecureBackupRecoveryKeyScreen.swift in Sources */,
|
||||
B1387648C6F71F1B98244803 /* SecureBackupRecoveryKeyScreenCoordinator.swift in Sources */,
|
||||
8AA84EF202F2EFC8453A97BD /* SecureBackupRecoveryKeyScreenModels.swift in Sources */,
|
||||
A7CA45942DEF306400300A02 /* Highlight.swift in Sources */,
|
||||
27F015B0D5436633B5B3C8C3 /* SecureBackupRecoveryKeyScreenViewModel.swift in Sources */,
|
||||
F0570F1ECD70C4C851FB2052 /* SecureBackupRecoveryKeyScreenViewModelProtocol.swift in Sources */,
|
||||
E84ADFE9696936C18C2424B5 /* SecureBackupScreen.swift in Sources */,
|
||||
@@ -8128,9 +8131,7 @@
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = "$(MARKETING_VERSION)";
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DIS_NSE",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DIS_NSE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse";
|
||||
PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)";
|
||||
PRODUCT_NAME = NSE;
|
||||
@@ -8179,9 +8180,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = "$(MARKETING_VERSION)";
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DIS_MAIN_APP",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP";
|
||||
PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = "$(APP_NAME)";
|
||||
@@ -8207,9 +8206,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = "$(MARKETING_VERSION)";
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DIS_MAIN_APP",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP";
|
||||
PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)";
|
||||
PRODUCT_NAME = "$(APP_NAME)";
|
||||
@@ -8434,9 +8431,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DDEBUG",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DDEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.ui.tests";
|
||||
PRODUCT_NAME = UITests;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -8455,9 +8450,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DRELEASE",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DRELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.ui.tests";
|
||||
PRODUCT_NAME = UITests;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -8479,9 +8472,7 @@
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = "$(MARKETING_VERSION)";
|
||||
OTHER_SWIFT_FLAGS = (
|
||||
"-DIS_NSE",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "-DIS_NSE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse";
|
||||
PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)";
|
||||
PRODUCT_NAME = NSE;
|
||||
|
||||
@@ -515,6 +515,11 @@
|
||||
"screen_room_details_pinned_events_row_title" = "Pinned messages";
|
||||
"screen_room_details_profile_row_title" = "Profile";
|
||||
"screen_room_details_requests_to_join_title" = "Requests to join";
|
||||
"screen_room_timeline_tombstoned_room_action" = "Jump to new room";
|
||||
"screen_room_timeline_tombstoned_room_message" = "This room has been replaced and is no longer active";
|
||||
"screen_room_timeline_upgraded_room_action" = "See old messages";
|
||||
"screen_room_timeline_upgraded_room_message" = "This room is a continuation of another room";
|
||||
"screen_roomlist_tombstoned_room_description" = "This room has been upgraded";
|
||||
"screen_security_and_privacy_add_room_address_action" = "Add room address";
|
||||
"screen_security_and_privacy_ask_to_join_option_description" = "Anyone can ask to join the room but an administrator or moderator will have to accept the request.";
|
||||
"screen_security_and_privacy_enable_encryption_alert_confirm_button_title" = "Yes, enable encryption";
|
||||
|
||||
@@ -549,6 +549,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
stateMachine.tryEvent(.presentKnockRequestsListScreen)
|
||||
case .presentThread(let itemID):
|
||||
stateMachine.tryEvent(.presentThread(itemID: itemID))
|
||||
case .presentRoom(roomID: let roomID):
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -2312,6 +2312,14 @@ internal enum L10n {
|
||||
internal static func screenRoomTimelineStateChanges(_ p1: Int) -> String {
|
||||
return L10n.tr("Localizable", "screen_room_timeline_state_changes", p1)
|
||||
}
|
||||
/// Jump to new room
|
||||
internal static var screenRoomTimelineTombstonedRoomAction: String { return L10n.tr("Localizable", "screen_room_timeline_tombstoned_room_action") }
|
||||
/// This room has been replaced and is no longer active
|
||||
internal static var screenRoomTimelineTombstonedRoomMessage: String { return L10n.tr("Localizable", "screen_room_timeline_tombstoned_room_message") }
|
||||
/// See old messages
|
||||
internal static var screenRoomTimelineUpgradedRoomAction: String { return L10n.tr("Localizable", "screen_room_timeline_upgraded_room_action") }
|
||||
/// This room is a continuation of another room
|
||||
internal static var screenRoomTimelineUpgradedRoomMessage: String { return L10n.tr("Localizable", "screen_room_timeline_upgraded_room_message") }
|
||||
/// Chat
|
||||
internal static var screenRoomTitle: String { return L10n.tr("Localizable", "screen_room_title") }
|
||||
/// Plural format key: "%#@COUNT@"
|
||||
@@ -2380,6 +2388,8 @@ internal enum L10n {
|
||||
internal static var screenRoomlistMarkAsRead: String { return L10n.tr("Localizable", "screen_roomlist_mark_as_read") }
|
||||
/// Mark as unread
|
||||
internal static var screenRoomlistMarkAsUnread: String { return L10n.tr("Localizable", "screen_roomlist_mark_as_unread") }
|
||||
/// This room has been upgraded
|
||||
internal static var screenRoomlistTombstonedRoomDescription: String { return L10n.tr("Localizable", "screen_roomlist_tombstoned_room_description") }
|
||||
/// Add room address
|
||||
internal static var screenSecurityAndPrivacyAddRoomAddressAction: String { return L10n.tr("Localizable", "screen_security_and_privacy_add_room_address_action") }
|
||||
/// Anyone can ask to join the room but an administrator or moderator will have to accept the request.
|
||||
|
||||
@@ -6484,6 +6484,7 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
||||
set(value) { underlyingTimeline = value }
|
||||
}
|
||||
var underlyingTimeline: TimelineProxyProtocol!
|
||||
var predecessorRoom: PredecessorRoom?
|
||||
var id: String {
|
||||
get { return underlyingId }
|
||||
set(value) { underlyingId = value }
|
||||
|
||||
@@ -48,6 +48,8 @@ struct JoinedRoomProxyMockConfiguration {
|
||||
var membership: Membership = .joined
|
||||
|
||||
var isVisibleInPublicDirectory = false
|
||||
var predecessor: PredecessorRoom?
|
||||
var successor: SuccessorRoom?
|
||||
}
|
||||
|
||||
extension JoinedRoomProxyMock {
|
||||
@@ -137,6 +139,8 @@ extension JoinedRoomProxyMock {
|
||||
clearDraftReturnValue = .success(())
|
||||
sendTypingNotificationIsTypingReturnValue = .success(())
|
||||
isVisibleInRoomDirectoryReturnValue = .success(configuration.isVisibleInPublicDirectory)
|
||||
|
||||
predecessorRoom = configuration.predecessor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +156,7 @@ extension RoomInfo {
|
||||
isDirect: configuration.isDirect,
|
||||
isPublic: configuration.isPublic,
|
||||
isSpace: configuration.isSpace,
|
||||
successorRoom: nil,
|
||||
successorRoom: configuration.successor,
|
||||
isFavourite: false,
|
||||
canonicalAlias: configuration.canonicalAlias,
|
||||
alternativeAliases: configuration.alternativeAliases,
|
||||
|
||||
@@ -89,7 +89,8 @@ extension RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false)
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +114,8 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false),
|
||||
isFavourite: false,
|
||||
isTombstoned: false),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "2",
|
||||
joinRequestType: nil,
|
||||
@@ -132,7 +134,8 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false),
|
||||
isFavourite: false,
|
||||
isTombstoned: false),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "3",
|
||||
joinRequestType: nil,
|
||||
@@ -151,7 +154,8 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false),
|
||||
isFavourite: false,
|
||||
isTombstoned: false),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "4",
|
||||
joinRequestType: nil,
|
||||
@@ -170,7 +174,8 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false),
|
||||
isFavourite: false,
|
||||
isTombstoned: false),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "5",
|
||||
joinRequestType: nil,
|
||||
@@ -189,7 +194,8 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: true,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false),
|
||||
isFavourite: false,
|
||||
isTombstoned: false),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "6",
|
||||
joinRequestType: nil,
|
||||
@@ -208,7 +214,28 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: true,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false),
|
||||
isFavourite: false,
|
||||
isTombstoned: false),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "7",
|
||||
joinRequestType: nil,
|
||||
name: "Tombstoned",
|
||||
isDirect: false,
|
||||
avatarURL: nil,
|
||||
heroes: [],
|
||||
activeMembersCount: 0,
|
||||
lastMessage: nil,
|
||||
lastMessageDate: .mock,
|
||||
unreadMessagesCount: 1,
|
||||
unreadMentionsCount: 0,
|
||||
unreadNotificationsCount: 1,
|
||||
notificationMode: .allMessages,
|
||||
canonicalAlias: nil,
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false,
|
||||
isTombstoned: true),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "0",
|
||||
joinRequestType: nil,
|
||||
@@ -227,7 +254,8 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false)
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
]
|
||||
|
||||
static let mockRoomsWithNotificationsState: [Element] = {
|
||||
@@ -279,7 +307,8 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false),
|
||||
isFavourite: false,
|
||||
isTombstoned: false),
|
||||
RoomSummary(room: RoomSDKMock(),
|
||||
id: "someAwesomeRoomId2",
|
||||
joinRequestType: .invite(inviter: RoomMemberProxyMock.mockCharlie),
|
||||
@@ -298,6 +327,7 @@ extension Array where Element == RoomSummary {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false)
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright 2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct Highlight: ViewModifier {
|
||||
let borderColor: Color
|
||||
let primaryColor: Color
|
||||
let secondaryColor: Color
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
ZStack(alignment: .top) {
|
||||
VStack(spacing: 0) {
|
||||
borderColor
|
||||
.frame(height: 1)
|
||||
LinearGradient(colors: [primaryColor, secondaryColor],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom)
|
||||
}
|
||||
content
|
||||
.layoutPriority(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
func highlight(borderColor: Color, primaryColor: Color, secondaryColor: Color) -> some View {
|
||||
modifier(Highlight(borderColor: borderColor, primaryColor: primaryColor, secondaryColor: secondaryColor))
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ struct PlaceholderAvatarImage: View {
|
||||
@Environment(\.redactionReasons) private var redactionReasons
|
||||
|
||||
private let textForImage: String
|
||||
/// When `nil` the tombstoned colors will be used
|
||||
private let contentID: String?
|
||||
|
||||
var body: some View {
|
||||
@@ -22,7 +23,9 @@ struct PlaceholderAvatarImage: View {
|
||||
// This text's frame doesn't look right when redacted
|
||||
if redactionReasons != .placeholder {
|
||||
Text(textForImage)
|
||||
.foregroundColor(avatarColor?.text ?? .white)
|
||||
.foregroundColor(avatarColor?.text ??
|
||||
// tombstoned room foreground
|
||||
.compound.iconTertiary)
|
||||
.font(.system(size: geometry.size.width * 0.5625, weight: .semibold))
|
||||
.minimumScaleFactor(0.001)
|
||||
.frame(alignment: .center)
|
||||
@@ -43,7 +46,9 @@ struct PlaceholderAvatarImage: View {
|
||||
return Color(.systemGray4) // matches the default text redaction
|
||||
}
|
||||
|
||||
return avatarColor?.background ?? .compound.iconPrimary
|
||||
return avatarColor?.background ??
|
||||
// tombstoned room background
|
||||
.compound.bgSubtlePrimary
|
||||
}
|
||||
|
||||
private var avatarColor: DecorativeColor? {
|
||||
@@ -70,6 +75,10 @@ struct PlaceholderAvatarImage_Previews: PreviewProvider, TestablePreview {
|
||||
.clipShape(Circle())
|
||||
.frame(width: 150, height: 100)
|
||||
|
||||
PlaceholderAvatarImage(name: "!", contentID: nil)
|
||||
.clipShape(Circle())
|
||||
.frame(width: 100, height: 100)
|
||||
|
||||
PlaceholderAvatarImage(name: nil, contentID: "@fooserid:matrix.org")
|
||||
.clipShape(Circle())
|
||||
.frame(width: 30, height: 30)
|
||||
|
||||
@@ -13,13 +13,17 @@ enum RoomAvatar: Equatable {
|
||||
case room(id: String, name: String?, avatarURL: URL?)
|
||||
/// An avatar generated from the room's heroes.
|
||||
case heroes([UserProfileProxy])
|
||||
/// A static avatar for a tombstoned room.
|
||||
case tombstoned
|
||||
|
||||
var removingAvatar: RoomAvatar {
|
||||
switch self {
|
||||
case let .room(id, name, _):
|
||||
return .room(id: id, name: name, avatarURL: nil)
|
||||
.room(id: id, name: name, avatarURL: nil)
|
||||
case let .heroes(users):
|
||||
return .heroes(users.map { .init(userID: $0.userID, displayName: $0.displayName, avatarURL: nil) })
|
||||
.heroes(users.map { .init(userID: $0.userID, displayName: $0.displayName, avatarURL: nil) })
|
||||
case .tombstoned:
|
||||
.tombstoned
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,6 +95,12 @@ struct RoomAvatarImage: View {
|
||||
mediaProvider: mediaProvider,
|
||||
onTap: onAvatarTap)
|
||||
}
|
||||
case .tombstoned:
|
||||
LoadableAvatarImage(url: nil,
|
||||
name: "!",
|
||||
contentID: nil, avatarSize: avatarSize,
|
||||
mediaProvider: mediaProvider,
|
||||
onTap: onAvatarTap)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,6 +136,8 @@ struct RoomAvatarImage_Previews: PreviewProvider, TestablePreview {
|
||||
.init(userID: "@bob:server.net", displayName: "Bob", avatarURL: nil)]),
|
||||
avatarSize: .room(on: .home),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()))
|
||||
|
||||
RoomAvatarImage(avatar: .tombstoned, avatarSize: .room(on: .home), mediaProvider: MediaProviderMock(configuration: .init()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +197,8 @@ struct HomeScreenRoom: Identifiable, Equatable {
|
||||
|
||||
let canonicalAlias: String?
|
||||
|
||||
let isTombstoned: Bool
|
||||
|
||||
static func placeholder() -> HomeScreenRoom {
|
||||
HomeScreenRoom(id: UUID().uuidString,
|
||||
roomID: nil,
|
||||
@@ -209,7 +211,8 @@ struct HomeScreenRoom: Identifiable, Equatable {
|
||||
timestamp: "Now",
|
||||
lastMessage: placeholderLastMessage,
|
||||
avatar: .room(id: "", name: "", avatarURL: nil),
|
||||
canonicalAlias: nil)
|
||||
canonicalAlias: nil,
|
||||
isTombstoned: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,6 +249,7 @@ extension HomeScreenRoom {
|
||||
timestamp: summary.lastMessageDate?.formattedMinimal(),
|
||||
lastMessage: summary.lastMessage,
|
||||
avatar: summary.avatar,
|
||||
canonicalAlias: summary.canonicalAlias)
|
||||
canonicalAlias: summary.canonicalAlias,
|
||||
isTombstoned: summary.isTombstoned)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,8 @@ private extension HomeScreenRoom {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false)
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
|
||||
return .init(summary: summary, hideUnreadMessagesBadge: false)
|
||||
}
|
||||
@@ -246,7 +247,8 @@ private extension HomeScreenRoom {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false)
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
|
||||
return .init(summary: summary, hideUnreadMessagesBadge: false)
|
||||
}
|
||||
|
||||
@@ -162,7 +162,8 @@ private extension HomeScreenRoom {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false)
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
|
||||
return .init(summary: summary, hideUnreadMessagesBadge: false)
|
||||
}
|
||||
@@ -191,7 +192,8 @@ private extension HomeScreenRoom {
|
||||
alternativeAliases: [],
|
||||
hasOngoingCall: false,
|
||||
isMarkedUnread: false,
|
||||
isFavourite: false)
|
||||
isFavourite: false,
|
||||
isTombstoned: false)
|
||||
|
||||
return .init(summary: summary, hideUnreadMessagesBadge: false)
|
||||
}
|
||||
|
||||
@@ -135,7 +135,11 @@ struct HomeScreenRoomCell: View {
|
||||
|
||||
@ViewBuilder
|
||||
private var lastMessage: some View {
|
||||
if let lastMessage = room.lastMessage {
|
||||
// If the room is tombstoned, show a specific message, regardless of any last message.
|
||||
if room.isTombstoned {
|
||||
Text(L10n.screenRoomlistTombstonedRoomDescription)
|
||||
.lastMessageFormatting()
|
||||
} else if let lastMessage = room.lastMessage {
|
||||
Text(lastMessage)
|
||||
.lastMessageFormatting()
|
||||
}
|
||||
|
||||
+2
-2
@@ -81,7 +81,7 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
|
||||
case .displayEmojiPicker, .displayReportContent, .displayCameraPicker, .displayMediaPicker,
|
||||
.displayDocumentPicker, .displayLocationPicker, .displayPollForm, .displayMediaUploadPreviewScreen,
|
||||
.displaySenderDetails, .displayMessageForwarding, .displayLocation, .displayResolveSendFailure,
|
||||
.displayThread, .composer, .hasScrolled, .viewInRoomTimeline:
|
||||
.displayThread, .composer, .hasScrolled, .viewInRoomTimeline, .displayRoom:
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
|
||||
case .displayEmojiPicker, .displayReportContent, .displayCameraPicker, .displayMediaPicker,
|
||||
.displayDocumentPicker, .displayLocationPicker, .displayPollForm, .displayMediaUploadPreviewScreen,
|
||||
.displaySenderDetails, .displayMessageForwarding, .displayLocation, .displayResolveSendFailure,
|
||||
.displayThread, .composer, .hasScrolled, .viewInRoomTimeline:
|
||||
.displayThread, .composer, .hasScrolled, .viewInRoomTimeline, .displayRoom:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ final class PinnedEventsTimelineScreenCoordinator: CoordinatorProtocol {
|
||||
// These other actions will not be handled in this view
|
||||
case .displayEmojiPicker, .displayReportContent, .displayCameraPicker, .displayMediaPicker,
|
||||
.displayDocumentPicker, .displayLocationPicker, .displayPollForm, .displayMediaUploadPreviewScreen,
|
||||
.displayResolveSendFailure, .displayThread, .composer, .hasScrolled:
|
||||
.displayResolveSendFailure, .displayThread, .composer, .hasScrolled, .displayRoom:
|
||||
// These actions are not handled in this coordinator
|
||||
break
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ enum RoomScreenCoordinatorAction {
|
||||
case presentResolveSendFailure(failure: TimelineItemSendFailure.VerifiedUser, sendHandle: SendHandleProxy)
|
||||
case presentKnockRequestsList
|
||||
case presentThread(itemID: TimelineItemIdentifier)
|
||||
case presentRoom(roomID: String)
|
||||
}
|
||||
|
||||
final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
@@ -151,6 +152,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
composerViewModel.process(timelineAction: action)
|
||||
case .hasScrolled(direction: let direction):
|
||||
roomViewModel.timelineHasScrolled(direction: direction)
|
||||
case .displayRoom(let roomID):
|
||||
actionsSubject.send(.presentRoom(roomID: roomID))
|
||||
case .viewInRoomTimeline:
|
||||
fatalError("The action: \(action) should not be sent to this coordinator")
|
||||
}
|
||||
@@ -182,6 +185,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
composerViewModel.process(timelineAction: .removeFocus)
|
||||
case .displayKnockRequests:
|
||||
actionsSubject.send(.presentKnockRequestsList)
|
||||
case .displayRoom(let roomID):
|
||||
actionsSubject.send(.presentRoom(roomID: roomID))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -15,6 +15,7 @@ enum RoomScreenViewModelAction: Equatable {
|
||||
case displayCall
|
||||
case removeComposerFocus
|
||||
case displayKnockRequests
|
||||
case displayRoom(roomID: String)
|
||||
}
|
||||
|
||||
enum RoomScreenViewAction {
|
||||
@@ -26,6 +27,7 @@ enum RoomScreenViewAction {
|
||||
case acceptKnock(eventID: String)
|
||||
case dismissKnockRequests
|
||||
case viewKnockRequests
|
||||
case displaySuccessorRoom
|
||||
}
|
||||
|
||||
struct RoomScreenViewState: BindableState {
|
||||
@@ -53,6 +55,8 @@ struct RoomScreenViewState: BindableState {
|
||||
var unseenKnockRequests: [KnockRequestInfo] = []
|
||||
var handledEventIDs: Set<String> = []
|
||||
|
||||
var hasSuccessor: Bool
|
||||
|
||||
var displayedKnockRequests: [KnockRequestInfo] {
|
||||
unseenKnockRequests.filter { !handledEventIDs.contains($0.eventID) }
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
super.init(initialViewState: .init(roomTitle: roomProxy.infoPublisher.value.displayName ?? roomProxy.id,
|
||||
roomAvatar: roomProxy.infoPublisher.value.avatar,
|
||||
hasOngoingCall: roomProxy.infoPublisher.value.hasRoomCall,
|
||||
hasSuccessor: roomProxy.infoPublisher.value.successor != nil,
|
||||
bindings: .init()),
|
||||
mediaProvider: mediaProvider)
|
||||
|
||||
@@ -114,6 +115,9 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
Task { await markAllKnocksAsSeen() }
|
||||
case .viewKnockRequests:
|
||||
actionsSubject.send(.displayKnockRequests)
|
||||
case .displaySuccessorRoom:
|
||||
guard let successorID = roomProxy.infoPublisher.value.successor?.roomId else { return }
|
||||
actionsSubject.send(.displayRoom(roomID: successorID))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +330,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
}
|
||||
|
||||
private func handleRoomInfoUpdate(_ roomInfo: RoomInfoProxy) async {
|
||||
state.hasSuccessor = roomInfo.successor != nil
|
||||
let pinnedEventIDs = roomInfo.pinnedEventIDs
|
||||
// Only update the loading state of the banner
|
||||
if state.pinnedEventsBannerState.isLoading {
|
||||
|
||||
@@ -151,7 +151,9 @@ struct RoomScreen: View {
|
||||
|
||||
@ViewBuilder
|
||||
private var composer: some View {
|
||||
if roomContext.viewState.canSendMessage {
|
||||
if roomContext.viewState.hasSuccessor {
|
||||
tombstonedDialogue
|
||||
} else if roomContext.viewState.canSendMessage {
|
||||
composerToolbar
|
||||
} else {
|
||||
Text(L10n.screenRoomTimelineNoPermissionToPost)
|
||||
@@ -162,6 +164,28 @@ struct RoomScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var tombstonedDialogue: some View {
|
||||
VStack(spacing: 16) {
|
||||
Text(L10n.screenRoomTimelineTombstonedRoomMessage)
|
||||
.font(.compound.bodyMD)
|
||||
.foregroundStyle(.compound.textPrimary)
|
||||
|
||||
Button {
|
||||
roomContext.send(viewAction: .displaySuccessorRoom)
|
||||
} label: {
|
||||
Text(L10n.screenRoomTimelineTombstonedRoomAction)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.buttonStyle(.compound(.primary, size: .medium))
|
||||
}
|
||||
.padding(.top, 16)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.bottom, 8)
|
||||
.highlight(borderColor: .compound.borderInfoSubtle,
|
||||
primaryColor: .compound.bgInfoSubtle,
|
||||
secondaryColor: .compound.bgCanvasDefault)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var loadingIndicator: some View {
|
||||
if timelineContext.viewState.showLoading {
|
||||
@@ -233,6 +257,7 @@ struct RoomScreen: View {
|
||||
struct RoomScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModels = makeViewModels()
|
||||
static let readOnlyViewModels = makeViewModels(canSendMessage: false)
|
||||
static let tombstonedViewModels = makeViewModels(hasSuccessor: true)
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
@@ -249,13 +274,22 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
.previewDisplayName("Read-only")
|
||||
.snapshotPreferences(expect: readOnlyViewModels.room.context.$viewState.map { !$0.canSendMessage })
|
||||
|
||||
NavigationStack {
|
||||
RoomScreen(roomViewModel: tombstonedViewModels.room,
|
||||
timelineViewModel: tombstonedViewModels.timeline,
|
||||
composerToolbar: ComposerToolbar.mock())
|
||||
}
|
||||
.previewDisplayName("Tombstoned")
|
||||
.snapshotPreferences(expect: tombstonedViewModels.room.context.$viewState.map(\.hasSuccessor))
|
||||
}
|
||||
|
||||
static func makeViewModels(canSendMessage: Bool = true) -> ViewModels {
|
||||
static func makeViewModels(canSendMessage: Bool = true, hasSuccessor: Bool = false) -> ViewModels {
|
||||
let roomProxyMock = JoinedRoomProxyMock(.init(id: "stable_id",
|
||||
name: "Preview room",
|
||||
hasOngoingCall: true,
|
||||
canUserSendMessage: canSendMessage))
|
||||
canUserSendMessage: canSendMessage,
|
||||
successor: hasSuccessor ? .init(roomId: UUID().uuidString, reason: nil) : nil))
|
||||
let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock)
|
||||
let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock,
|
||||
timelineController: MockTimelineController(),
|
||||
|
||||
@@ -12,32 +12,44 @@ struct RoomScreenFooterView: View {
|
||||
let mediaProvider: MediaProviderProtocol?
|
||||
let callback: (RoomScreenFooterViewAction) -> Void
|
||||
|
||||
private var borderColor: Color {
|
||||
switch details {
|
||||
case .pinViolation:
|
||||
.compound.borderInfoSubtle
|
||||
case .verificationViolation:
|
||||
.compound.borderCriticalSubtle
|
||||
case .none:
|
||||
Color.compound.bgCanvasDefault
|
||||
}
|
||||
}
|
||||
|
||||
private var gradientColor: Color {
|
||||
switch details {
|
||||
case .pinViolation:
|
||||
.compound.bgInfoSubtle
|
||||
case .verificationViolation:
|
||||
.compound.bgCriticalSubtle
|
||||
case .none:
|
||||
Color.compound.bgCanvasDefault
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if let details {
|
||||
ZStack(alignment: .top) {
|
||||
switch details {
|
||||
case .pinViolation(let member, let learnMoreURL):
|
||||
VStack(spacing: 0) {
|
||||
Color.compound.borderInfoSubtle
|
||||
.frame(height: 1)
|
||||
LinearGradient(colors: [.compound.bgInfoSubtle, .compound.bgCanvasDefault],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom)
|
||||
}
|
||||
pinViolation(member: member, learnMoreURL: learnMoreURL)
|
||||
case .verificationViolation(member: let member, learnMoreURL: let learnMoreURL):
|
||||
VStack(spacing: 0) {
|
||||
Color.compound.borderCriticalSubtle
|
||||
.frame(height: 1)
|
||||
LinearGradient(colors: [.compound.bgCriticalSubtle, .compound.bgCanvasDefault],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom)
|
||||
}
|
||||
verificationViolation(member: member, learnMoreURL: learnMoreURL)
|
||||
}
|
||||
}
|
||||
.padding(.top, 8)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
detailsView(details)
|
||||
.highlight(borderColor: borderColor, primaryColor: gradientColor, secondaryColor: .compound.bgCanvasDefault)
|
||||
.padding(.top, 8)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func detailsView(_ details: RoomScreenFooterViewDetails) -> some View {
|
||||
switch details {
|
||||
case .pinViolation(let member, let learnMoreURL):
|
||||
pinViolation(member: member, learnMoreURL: learnMoreURL)
|
||||
case .verificationViolation(member: let member, learnMoreURL: let learnMoreURL):
|
||||
verificationViolation(member: member, learnMoreURL: learnMoreURL)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ final class ThreadTimelineScreenCoordinator: CoordinatorProtocol {
|
||||
actionsSubject.send(.presentLocationViewer(body: body, geoURI: geoURI, description: description))
|
||||
case .displayResolveSendFailure(let failure, let sendHandle):
|
||||
actionsSubject.send(.presentResolveSendFailure(failure: failure, sendHandle: sendHandle))
|
||||
case .displayThread, .composer, .hasScrolled:
|
||||
case .displayThread, .composer, .hasScrolled, .displayRoom:
|
||||
break
|
||||
case .viewInRoomTimeline:
|
||||
fatalError("The action: \(action) should not be sent to this coordinator")
|
||||
|
||||
@@ -28,6 +28,7 @@ enum TimelineViewModelAction {
|
||||
case composer(action: TimelineComposerAction)
|
||||
case hasScrolled(direction: ScrollDirection)
|
||||
case viewInRoomTimeline(eventID: String)
|
||||
case displayRoom(roomID: String)
|
||||
}
|
||||
|
||||
enum TimelineViewPollAction {
|
||||
@@ -77,6 +78,8 @@ enum TimelineViewAction {
|
||||
|
||||
case hasScrolled(direction: ScrollDirection)
|
||||
case setOpenURLAction(OpenURLAction)
|
||||
|
||||
case seePredecessorTapped
|
||||
}
|
||||
|
||||
enum TimelineComposerAction {
|
||||
@@ -107,6 +110,8 @@ struct TimelineViewState: BindableState {
|
||||
var areThreadsEnabled: Bool
|
||||
var hideTimelineMedia: Bool
|
||||
|
||||
let hasPredecessor: Bool
|
||||
|
||||
// The `pinnedEventIDs` are used only to determine if an item is already pinned or not.
|
||||
// It's updated from the room info, so it's faster than using the timeline
|
||||
var pinnedEventIDs: Set<String> = []
|
||||
|
||||
@@ -104,6 +104,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
||||
isViewSourceEnabled: appSettings.viewSourceEnabled,
|
||||
areThreadsEnabled: appSettings.threadsEnabled,
|
||||
hideTimelineMedia: hideTimelineMedia,
|
||||
hasPredecessor: roomProxy.predecessorRoom != nil,
|
||||
pinnedEventIDs: roomProxy.infoPublisher.value.pinnedEventIDs,
|
||||
emojiProvider: emojiProvider,
|
||||
mapTilerConfiguration: appSettings.mapTilerConfiguration,
|
||||
@@ -211,6 +212,9 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
||||
actionsSubject.send(.hasScrolled(direction: direction))
|
||||
case .setOpenURLAction(let action):
|
||||
state.openURL = action
|
||||
case .seePredecessorTapped:
|
||||
guard let predecessorID = roomProxy.predecessorRoom?.roomId else { return }
|
||||
actionsSubject.send(.displayRoom(roomID: predecessorID))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,11 +1022,12 @@ private extension RoomInfoProxy {
|
||||
extension TimelineViewModel {
|
||||
static let mock = mock(timelineKind: .live)
|
||||
|
||||
static func mock(timelineKind: TimelineKind = .live, timelineController: MockTimelineController? = nil) -> TimelineViewModel {
|
||||
static func mock(timelineKind: TimelineKind = .live, timelineController: MockTimelineController? = nil, hasPredecessor: Bool = false) -> TimelineViewModel {
|
||||
let clientProxyMock = ClientProxyMock(.init())
|
||||
clientProxyMock.roomSummaryForAliasReturnValue = .mock(id: "!room:matrix.org", name: "Room")
|
||||
clientProxyMock.roomSummaryForIdentifierReturnValue = .mock(id: "!room:matrix.org", name: "Room", canonicalAlias: "#room:matrix.org")
|
||||
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
|
||||
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview room", predecessor: hasPredecessor ? .init(roomId: UUID().uuidString, lastEventId: UUID().uuidString) : nil))
|
||||
return TimelineViewModel(roomProxy: roomProxy,
|
||||
focussedEventID: nil,
|
||||
timelineController: timelineController ?? MockTimelineController(timelineKind: timelineKind),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()),
|
||||
|
||||
+43
-6
@@ -5,20 +5,50 @@
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct TimelineStartRoomTimelineView: View {
|
||||
let timelineItem: TimelineStartRoomTimelineItem
|
||||
@Environment(\.timelineContext) private var context
|
||||
|
||||
var body: some View {
|
||||
Text(title)
|
||||
.font(.compound.bodySM)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.padding(.vertical, 24)
|
||||
.frame(maxWidth: .infinity)
|
||||
VStack(spacing: 14) {
|
||||
if context?.viewState.hasPredecessor == true {
|
||||
upgrade
|
||||
}
|
||||
if context?.viewState.isDirectOneToOneRoom != true {
|
||||
Text(title)
|
||||
.font(.compound.bodySM)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.padding(.bottom, 24)
|
||||
.padding(.top, context?.viewState.hasPredecessor == true ? 0 : 24)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var title: String {
|
||||
private var upgrade: some View {
|
||||
VStack(spacing: 16) {
|
||||
Text(L10n.screenRoomTimelineUpgradedRoomMessage)
|
||||
.font(.compound.bodyMD)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
Button {
|
||||
context?.send(viewAction: .seePredecessorTapped)
|
||||
} label: {
|
||||
Text(L10n.screenRoomTimelineUpgradedRoomAction)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.buttonStyle(.compound(.primary, size: .medium))
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.padding(.top, 16)
|
||||
.padding(.bottom, 8)
|
||||
.padding(.horizontal, 16)
|
||||
.highlight(borderColor: .compound.borderInfoSubtle, primaryColor: .compound.bgInfoSubtle, secondaryColor: Color.clear)
|
||||
}
|
||||
|
||||
private var title: String {
|
||||
var text = L10n.screenRoomTimelineBeginningOfRoomNoName
|
||||
if let name = timelineItem.name {
|
||||
text = L10n.screenRoomTimelineBeginningOfRoom(name)
|
||||
@@ -28,8 +58,15 @@ struct TimelineStartRoomTimelineView: View {
|
||||
}
|
||||
|
||||
struct TimelineStartRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = TimelineViewModel.mock(hasPredecessor: true)
|
||||
|
||||
static var previews: some View {
|
||||
let item = TimelineStartRoomTimelineItem(name: "Alice and Bob")
|
||||
TimelineStartRoomTimelineView(timelineItem: item)
|
||||
.previewLayout(.sizeThatFits)
|
||||
TimelineStartRoomTimelineView(timelineItem: item)
|
||||
.environment(\.timelineContext, viewModel.context)
|
||||
.previewLayout(.sizeThatFits)
|
||||
.previewDisplayName("with predecessor")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
|
||||
var ownUserID: String { room.ownUserId() }
|
||||
|
||||
lazy var predecessorRoom: PredecessorRoom? = room.predecessorRoom()
|
||||
|
||||
let timeline: TimelineProxyProtocol
|
||||
|
||||
private let infoSubject: CurrentValueSubject<RoomInfoProxy, Never>
|
||||
|
||||
@@ -33,6 +33,10 @@ struct RoomInfoProxy: BaseRoomInfoProxyProtocol {
|
||||
var avatarURL: URL? { roomInfo.avatarUrl.flatMap(URL.init) }
|
||||
/// The room's avatar info for use in a ``RoomAvatarImage``.
|
||||
var avatar: RoomAvatar {
|
||||
guard successor == nil else {
|
||||
return .tombstoned
|
||||
}
|
||||
|
||||
if isDirect, avatarURL == nil, heroes.count == 1 {
|
||||
return .heroes(heroes.map(UserProfileProxy.init))
|
||||
}
|
||||
@@ -61,7 +65,7 @@ struct RoomInfoProxy: BaseRoomInfoProxyProtocol {
|
||||
}
|
||||
|
||||
var isSpace: Bool { roomInfo.isSpace }
|
||||
var tombstoneInfo: SuccessorRoom? { roomInfo.successorRoom }
|
||||
var successor: SuccessorRoom? { roomInfo.successorRoom }
|
||||
var isFavourite: Bool { roomInfo.isFavourite }
|
||||
var canonicalAlias: String? { roomInfo.canonicalAlias }
|
||||
var alternativeAliases: [String] { roomInfo.alternativeAliases }
|
||||
|
||||
@@ -76,6 +76,8 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
||||
|
||||
var timeline: TimelineProxyProtocol { get }
|
||||
|
||||
var predecessorRoom: PredecessorRoom? { get }
|
||||
|
||||
func subscribeForUpdates() async
|
||||
|
||||
func subscribeToRoomInfoUpdates()
|
||||
|
||||
@@ -56,6 +56,8 @@ struct RoomSummary {
|
||||
let isMarkedUnread: Bool
|
||||
let isFavourite: Bool
|
||||
|
||||
let isTombstoned: Bool
|
||||
|
||||
var hasUnreadMessages: Bool { unreadMessagesCount > 0 }
|
||||
var hasUnreadMentions: Bool { unreadMentionsCount > 0 }
|
||||
var hasUnreadNotifications: Bool { unreadNotificationsCount > 0 }
|
||||
@@ -124,14 +126,19 @@ extension RoomSummary {
|
||||
joinRequestType = nil
|
||||
isMarkedUnread = false
|
||||
isFavourite = false
|
||||
isTombstoned = false
|
||||
}
|
||||
|
||||
// This doesn't have to work properly for DM invites, the heroes are always empty
|
||||
var avatar: RoomAvatar {
|
||||
guard !isTombstoned else {
|
||||
return .tombstoned
|
||||
}
|
||||
|
||||
if isDirect, avatarURL == nil, heroes.count == 1 {
|
||||
.heroes(heroes)
|
||||
return .heroes(heroes)
|
||||
} else {
|
||||
.room(id: id, name: name, avatarURL: avatarURL)
|
||||
return .room(id: id, name: name, avatarURL: avatarURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,8 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
|
||||
alternativeAliases: .init(roomInfo.alternativeAliases),
|
||||
hasOngoingCall: roomInfo.hasRoomCall,
|
||||
isMarkedUnread: roomInfo.isMarkedUnread,
|
||||
isFavourite: roomInfo.isFavourite)
|
||||
isFavourite: roomInfo.isFavourite,
|
||||
isTombstoned: roomInfo.successorRoom != nil)
|
||||
}
|
||||
|
||||
private func buildDiff(from diff: RoomListEntriesUpdate, on rooms: [RoomSummary]) -> CollectionDifference<RoomSummary>? {
|
||||
|
||||
@@ -185,11 +185,13 @@ class TimelineController: TimelineControllerProtocol {
|
||||
sender: nil,
|
||||
attachments: nil)
|
||||
|
||||
let avatarURL = switch roomProxy.details.avatar {
|
||||
let avatarURL: URL? = switch roomProxy.details.avatar {
|
||||
case .room(_, _, let avatarURL):
|
||||
avatarURL
|
||||
case .heroes(let userProfiles):
|
||||
userProfiles.first?.avatarURL
|
||||
case .tombstoned:
|
||||
nil
|
||||
}
|
||||
|
||||
func addPlacehoder() {
|
||||
@@ -389,6 +391,7 @@ class TimelineController: TimelineControllerProtocol {
|
||||
|
||||
let isDM = roomProxy.isDirectOneToOneRoom
|
||||
let displayName = roomProxy.infoPublisher.value.displayName
|
||||
let hasPredecessor = roomProxy.predecessorRoom != nil
|
||||
|
||||
var newTimelineItems = await Task.detached { [timelineItemFactory, activeTimeline] in
|
||||
var newTimelineItems = [RoomTimelineItemProtocol]()
|
||||
@@ -401,6 +404,7 @@ class TimelineController: TimelineControllerProtocol {
|
||||
let items = collapsibleChunk.compactMap { itemProxy in
|
||||
let timelineItem = self.buildTimelineItem(for: itemProxy,
|
||||
isDM: isDM,
|
||||
hasPredecessor: hasPredecessor,
|
||||
roomDisplayName: displayName,
|
||||
timelineItemFactory: timelineItemFactory,
|
||||
activeTimeline: activeTimeline)
|
||||
@@ -451,6 +455,7 @@ class TimelineController: TimelineControllerProtocol {
|
||||
|
||||
private nonisolated func buildTimelineItem(for itemProxy: TimelineItemProxy,
|
||||
isDM: Bool,
|
||||
hasPredecessor: Bool,
|
||||
roomDisplayName: String?,
|
||||
timelineItemFactory: RoomTimelineItemFactoryProtocol,
|
||||
activeTimeline: TimelineProxyProtocol) -> RoomTimelineItemProtocol? {
|
||||
@@ -475,7 +480,11 @@ class TimelineController: TimelineControllerProtocol {
|
||||
case .readMarker:
|
||||
return ReadMarkerRoomTimelineItem(id: .virtual(uniqueID: uniqueID))
|
||||
case .timelineStart:
|
||||
return isDM ? nil : TimelineStartRoomTimelineItem(name: roomDisplayName)
|
||||
if hasPredecessor {
|
||||
return TimelineStartRoomTimelineItem(name: roomDisplayName)
|
||||
} else {
|
||||
return isDM ? nil : TimelineStartRoomTimelineItem(name: roomDisplayName)
|
||||
}
|
||||
}
|
||||
case .unknown:
|
||||
return nil
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@
|
||||
import Foundation
|
||||
|
||||
struct TimelineStartRoomTimelineItem: DecorationTimelineItemProtocol, Equatable {
|
||||
let id: TimelineItemIdentifier = .virtual(uniqueID: .init(UUID().uuidString))
|
||||
let id: TimelineItemIdentifier = .virtual(uniqueID: .init("TimelineStart"))
|
||||
let name: String?
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:35951ab2ca021aacb1d40c8ae270efe23f47b38d0715b0475b93e0878300253d
|
||||
size 163854
|
||||
oid sha256:8330191544e3657e0e3533d668e9b0a87d026a657d85df753b59d7ac7dcc0a88
|
||||
size 169757
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:31ddb9be88bf2a6469fc8d3c8178170ca246b7c5429f9db98bb6f737cb282703
|
||||
size 164238
|
||||
oid sha256:634dace53b6cf3fd5333581f6af4b7a4fc61aea536f9c3521d4066eff5bf4bf9
|
||||
size 170141
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8687afad034254066ea656378022ae61aed58cc2b2214edaf323ab13aded7c73
|
||||
size 99720
|
||||
oid sha256:76d43f9eeaed0fc25fef35f560cfef46968f58406a2856616b27eea74853b93d
|
||||
size 103810
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:03d9f85d77b1e75bbc8ab40ce84756067a30d35d09a7ce6e821302ba35dbdece
|
||||
size 100052
|
||||
oid sha256:4437a44dfc2fda3db1823458d07043f82610f70065bece40e5178301bd536536
|
||||
size 104142
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4e891998fd95aa30f8c191deab533a059a9c1feb815ae5bf0852540c9b1e9ab4
|
||||
size 251107
|
||||
oid sha256:d8857f34fc49bd98435b4e5595c10b1a463987f83084edc7682591993f69137e
|
||||
size 260979
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ecf700e5999db8abed896b329e74903335c481cce0e06dc7d6568561168c45ad
|
||||
size 255196
|
||||
oid sha256:93bec421deab287621f9491cb3c8f1f6c5a2032f035b33c0e694eab5e73e40ae
|
||||
size 269355
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:28f525c2f84acf155af7b5eaa7d3c9726a7d0861fad83c7e5249925d57fefd81
|
||||
size 188085
|
||||
oid sha256:5c17c1409da49b67f48bbc12856a7411368741c1e987933d1304fef98aa1a81f
|
||||
size 195209
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2582a1c209166a3488335a70697fb0be7c7c81228db2ca2198e4a959b9cff3f7
|
||||
size 190520
|
||||
oid sha256:bdc4b92d1659096dc1bc61acfeab73799d520a990b34621ff398fa1563cbbf83
|
||||
size 202572
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:511bbebdefd00ca3169790a06c4286fda86e90a0c814b6327dbcd3b54aa9fa95
|
||||
size 228009
|
||||
oid sha256:5049db4e463707a92bf4d6a82001f6bf06f63221f182870bf0efb88a9390fbf4
|
||||
size 242678
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:79a8204c246186be948bfd1d1ac0ccf87edf3a047304705b077436540fad299a
|
||||
size 229275
|
||||
oid sha256:32da7e0537cbd586dba8bdb79d155a81c7f5fae7a9749555a0ee26b90bd5b715
|
||||
size 248416
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fba85304ab17f100b391904278da5b82fbaa458e3b53de446ba98d088c0908a1
|
||||
size 169063
|
||||
oid sha256:a1cd038069eeba5235567fb9ca53768b3675e4e3a6ccea351c7ef846b005f310
|
||||
size 180368
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0586a60dc2d7cbc8d0679015b11e88e163c4ab2749233db1948685f52c69b8c0
|
||||
size 168689
|
||||
oid sha256:0998f864dfeca1c729cdd5aad48edc0509c611ec0974538ed1cfb0f443893d00
|
||||
size 184752
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:18a5a2705faf3823e0db694088206dc582621b4c52f31b7e5bdf5682889d5b94
|
||||
size 165467
|
||||
oid sha256:e8070b141426f12f70536ec19130566f1d33b4a8e163f60696bab457c806076d
|
||||
size 169986
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cae43b115dc17061874c1338042c62d71b0e41eebfee30e8c6e8c094490be64a
|
||||
size 167363
|
||||
oid sha256:515b38dd917617cd93d3db645bb4e5a187da6d2057a1e8ffac98b58df9e67500
|
||||
size 171882
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:70ad8dc0e88cd46109fea561c0b7e220ca6bad6c7eb124d5b9f14b233f537820
|
||||
size 112987
|
||||
oid sha256:b9b027ff00710c620f8fe31d278d5ba6b65820d3463686327f6fe9c63c9e8623
|
||||
size 116692
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b2c4306135e1efa0552deddcaa09e22cae4f23687b0dcf840c9e39bad61635c0
|
||||
size 112846
|
||||
oid sha256:37a1f360bc89ee6025f7f91cdb88ada5d5dcace0ae4001001b64ff47ccb91d4f
|
||||
size 116551
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf1b83a17875ff7f68adf737693f70b4b5b8d48260488d01165f5f3f0433660f
|
||||
size 125352
|
||||
oid sha256:e902bdfcd9a475267b1eefda4833c3d94fcc250cdfa7460b7c1c53ba1cacf4ff
|
||||
size 130244
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf1b83a17875ff7f68adf737693f70b4b5b8d48260488d01165f5f3f0433660f
|
||||
size 125352
|
||||
oid sha256:e902bdfcd9a475267b1eefda4833c3d94fcc250cdfa7460b7c1c53ba1cacf4ff
|
||||
size 130244
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d2e6632fe1a83c6bd4f1601025027dd1e2515b56b98d0a4fde35eb56c3e56b40
|
||||
size 82324
|
||||
oid sha256:efd42154d6ed807c7de34d79bafcfc25767796aa6d9ce31a346d0bd39cf87db2
|
||||
size 86366
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d2e6632fe1a83c6bd4f1601025027dd1e2515b56b98d0a4fde35eb56c3e56b40
|
||||
size 82324
|
||||
oid sha256:efd42154d6ed807c7de34d79bafcfc25767796aa6d9ce31a346d0bd39cf87db2
|
||||
size 86366
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eaa4236ec02b96b3883fccefc5e45b0b296448ab52ecc87201a837e5b1b23a83
|
||||
size 96810
|
||||
oid sha256:acc53e8fc7d224fc2ec0ce663efde39aaa625dcf11de3ca43f52704c814d0825
|
||||
size 101058
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eaa4236ec02b96b3883fccefc5e45b0b296448ab52ecc87201a837e5b1b23a83
|
||||
size 96810
|
||||
oid sha256:acc53e8fc7d224fc2ec0ce663efde39aaa625dcf11de3ca43f52704c814d0825
|
||||
size 101058
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:21089ce2daaa37f7e86031e11eab89d2dd9e80bb319c004fb86a9fc0e83d84f1
|
||||
size 55228
|
||||
oid sha256:ec055acc51709c62fe9d76a93db885da6de917eb014bde88c51307b9582e352e
|
||||
size 59276
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:21089ce2daaa37f7e86031e11eab89d2dd9e80bb319c004fb86a9fc0e83d84f1
|
||||
size 55228
|
||||
oid sha256:ec055acc51709c62fe9d76a93db885da6de917eb014bde88c51307b9582e352e
|
||||
size 59276
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1ce3b3010ca5fbfdd4c4e44e1b5042bfd4b42edbba6e5546d8f95e3597ce8ffd
|
||||
size 101458
|
||||
oid sha256:1896e5328d738494310900bf5d0f4a7441bb70f91103a20bce20ca064b6e6d5e
|
||||
size 103499
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1ce3b3010ca5fbfdd4c4e44e1b5042bfd4b42edbba6e5546d8f95e3597ce8ffd
|
||||
size 101458
|
||||
oid sha256:1896e5328d738494310900bf5d0f4a7441bb70f91103a20bce20ca064b6e6d5e
|
||||
size 103499
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:887d9c813a0a286e9b635713218e50042b8c1a5e49c753f4745abf7b6dc98d8d
|
||||
size 57309
|
||||
oid sha256:d84daf5a9f2f6caed69fca648e8f677b3a1055f238d482bbfd7ede5769605bb6
|
||||
size 58978
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:887d9c813a0a286e9b635713218e50042b8c1a5e49c753f4745abf7b6dc98d8d
|
||||
size 57309
|
||||
oid sha256:d84daf5a9f2f6caed69fca648e8f677b3a1055f238d482bbfd7ede5769605bb6
|
||||
size 58978
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:42ce084b1cd46ffd146b54c669bae1fa6f842e02e9f840ae92972af4f035ba3e
|
||||
size 352872
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7d73de09a9fbe543821b29fa1261d5175e3a0d994b90e21b71157bd05d463a48
|
||||
size 365960
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:816d2ea7bd4c6653e9c27a7735575ba05890a5f16d39d3d38db344a10e8c0ce9
|
||||
size 205525
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2a46c473e05f8b8fa538e78dc0bf33ba3867fe5b7a33fc2be325bfb75e7cd688
|
||||
size 213588
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:69544d0b3042e3997689f0131e87af191929ef1b62647b22b13bfe362307db1d
|
||||
size 162531
|
||||
oid sha256:348e37e04af9dc3297e28c01a33176594b63d01a701f16a1e3278666d4ffd41d
|
||||
size 167050
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d224a0f3ea5243508744166a1ce4b635eeb4f08363e6c2558bf1ec2574ce8a1d
|
||||
size 164014
|
||||
oid sha256:29acfd6916630e8a47dd3fc51eda53a0f3fbb0af609a72ceee08a7db5dec2396
|
||||
size 168533
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a995e503150a60c80666fba9135b70b3d21a59134ec400f8caf9bac3df16c54c
|
||||
size 110886
|
||||
oid sha256:993b6d680dd7fea259ab9debaeb45e5ee4fd58c0f029f87446692f5010eeacf8
|
||||
size 114591
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f5921b93c625428f436a43fec74d940a277d11fabbcf0e1412efbe574222101d
|
||||
size 112186
|
||||
oid sha256:8eb5e58c5cdf0000578dbb5cf2185e80ba1bbf95e418b29bc850e9ba5eb05864
|
||||
size 115891
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:405dfc63227335d693dd6411d80516090c3ba34b029bd8e6d437734838e3019b
|
||||
size 72781
|
||||
oid sha256:f6a23002b129e657affa39005cfd798b7cba69410cfc2217e8ca68473c9c1904
|
||||
size 12023
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:09f0344ac2df6a6480c4023c4172df5afebb9ef3520f6cde9ee16233f903df8a
|
||||
size 76139
|
||||
oid sha256:af63be3b23ffe433d52a494b13182630cedbec07ef1787ef39904b8a085f206f
|
||||
size 15444
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8a79e77f39d2ff11558b0cd813b81e6bedcb25349872d151dfa02639e72835e9
|
||||
size 32196
|
||||
oid sha256:ca6209bc798f344af1923871ae59ce1c8bd91913dd50d7740d6352b5428e5d07
|
||||
size 8416
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:89c98670abb61eeb3e8af31bb4d0401f73f02645d9d2e777db85b401c540e501
|
||||
size 35560
|
||||
oid sha256:90137e56f48b5c2c84907876e21cebcfd4fd4c62b030669144e830fcb1a9bea1
|
||||
size 12081
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f4bc3686bbbd334bd0e159e5baed9580462fe18c10d22742604dae738d377f9a
|
||||
size 86439
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:205fe4317844539ef5f9fcfb2ea1e36d6a877272c3ee1804654cd25d9da08b28
|
||||
size 95010
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b4a9f8adea22b87db13d8f99f95908fdcf17010117857f98731921b15d214095
|
||||
size 44895
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cb0db63457ff2bfc24377e28ddd6d32833199ea5edceb23317dedee88547c381
|
||||
size 67013
|
||||
Reference in New Issue
Block a user