mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Read Receipts display with the user avatar (#1038)
* added the read receipt into the code * fixed some things lost during merge * implemented the status view to be always at the trailing side * preview code for better testing * removed timelineStyle modifier * removed also the group style * added some UI tests for the read receipts
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 51;
|
objectVersion = 54;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@@ -99,7 +99,6 @@
|
|||||||
281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
|
281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
|
||||||
282A5F3375DDC774AE09B0C3 /* TracingConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */; };
|
282A5F3375DDC774AE09B0C3 /* TracingConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */; };
|
||||||
2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7310D8DFE01AF45F0689C3AA /* Publisher.swift */; };
|
2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7310D8DFE01AF45F0689C3AA /* Publisher.swift */; };
|
||||||
28A94A7DF684F2A29C4ADFE9 /* TimelineReceiptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5457B0320D028A676C248F /* TimelineReceiptView.swift */; };
|
|
||||||
290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */; };
|
290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */; };
|
||||||
292827744227DF61C930BDDB /* CreateRoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */; };
|
292827744227DF61C930BDDB /* CreateRoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */; };
|
||||||
2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; };
|
2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; };
|
||||||
@@ -175,6 +174,7 @@
|
|||||||
48FE5F0E3921146DBF4E61E7 /* OnboardingBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06A27D9C70E0DCC1E199163 /* OnboardingBackgroundView.swift */; };
|
48FE5F0E3921146DBF4E61E7 /* OnboardingBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06A27D9C70E0DCC1E199163 /* OnboardingBackgroundView.swift */; };
|
||||||
492274DA6691EE985C2FCCAA /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; };
|
492274DA6691EE985C2FCCAA /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; };
|
||||||
496CC9D59ACFAB84FD9B3B5F /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840E86A67DB2C92C09771EAD /* AnalyticsPromptScreenModels.swift */; };
|
496CC9D59ACFAB84FD9B3B5F /* AnalyticsPromptScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840E86A67DB2C92C09771EAD /* AnalyticsPromptScreenModels.swift */; };
|
||||||
|
49814A48470F347426513B07 /* TimelineReadReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1877038D1AD3D5A029F8AE2C /* TimelineReadReceiptsView.swift */; };
|
||||||
49F2E7DD8CAACE09CEECE3E6 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */; };
|
49F2E7DD8CAACE09CEECE3E6 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */; };
|
||||||
4A618590DEB72C4F186BFED4 /* UserSessionFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */; };
|
4A618590DEB72C4F186BFED4 /* UserSessionFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C99FDEEB71173C4C6FA2734C /* UserSessionFlowCoordinator.swift */; };
|
||||||
4A85928E27D4C1A548A06EE9 /* StartChatScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */; };
|
4A85928E27D4C1A548A06EE9 /* StartChatScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */; };
|
||||||
@@ -360,6 +360,7 @@
|
|||||||
8F2FAA98457750D9D664136F /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
|
8F2FAA98457750D9D664136F /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
|
||||||
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
|
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
|
||||||
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
|
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
|
||||||
|
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; };
|
||||||
9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; };
|
9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; };
|
||||||
92B95779840CD749117B3615 /* EmojiMartStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38AE3617D7619EF30CDD229 /* EmojiMartStore.swift */; };
|
92B95779840CD749117B3615 /* EmojiMartStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38AE3617D7619EF30CDD229 /* EmojiMartStore.swift */; };
|
||||||
92D9088B901CEBB1A99ECA4E /* RoomMemberProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */; };
|
92D9088B901CEBB1A99ECA4E /* RoomMemberProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */; };
|
||||||
@@ -656,6 +657,7 @@
|
|||||||
FC10228E73323BDC09526F97 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; };
|
FC10228E73323BDC09526F97 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; };
|
||||||
FCD3F2B82CAB29A07887A127 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 2B43F2AF7456567FE37270A7 /* KeychainAccess */; };
|
FCD3F2B82CAB29A07887A127 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 2B43F2AF7456567FE37270A7 /* KeychainAccess */; };
|
||||||
FD762761C5D0C30E6255C3D8 /* ServerConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */; };
|
FD762761C5D0C30E6255C3D8 /* ServerConfirmationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */; };
|
||||||
|
FDFB75880BC21B297E66AB28 /* TimelineItemStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47A78A43F3971B1BE8CF642E /* TimelineItemStatusView.swift */; };
|
||||||
FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; };
|
FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; };
|
||||||
FF149F0A3550A54C50ECBE7A /* AppRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C843CF833BF6485B64AC87E1 /* AppRouter.swift */; };
|
FF149F0A3550A54C50ECBE7A /* AppRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C843CF833BF6485B64AC87E1 /* AppRouter.swift */; };
|
||||||
FFD3E4FF948E06C7585317FC /* TimelineStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892E29C98C4E8182C9037F84 /* TimelineStyler.swift */; };
|
FFD3E4FF948E06C7585317FC /* TimelineStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892E29C98C4E8182C9037F84 /* TimelineStyler.swift */; };
|
||||||
@@ -761,7 +763,7 @@
|
|||||||
1222DB76B917EB8A55365BA5 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
1222DB76B917EB8A55365BA5 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
||||||
127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = "<group>"; };
|
127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = "<group>"; };
|
||||||
127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = "<group>"; };
|
127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = "<group>"; };
|
||||||
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>"; };
|
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>"; };
|
||||||
@@ -774,6 +776,7 @@
|
|||||||
1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogAnalyticsClient.swift; sourceTree = "<group>"; };
|
1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogAnalyticsClient.swift; sourceTree = "<group>"; };
|
||||||
1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfigurationTests.swift; sourceTree = "<group>"; };
|
1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfigurationTests.swift; sourceTree = "<group>"; };
|
||||||
184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
1877038D1AD3D5A029F8AE2C /* TimelineReadReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReadReceiptsView.swift; sourceTree = "<group>"; };
|
||||||
18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; };
|
18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; };
|
||||||
18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryProtocol.swift; sourceTree = "<group>"; };
|
18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryProtocol.swift; sourceTree = "<group>"; };
|
||||||
1941C8817E6B6971BA4415F5 /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = "<group>"; };
|
1941C8817E6B6971BA4415F5 /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
@@ -825,6 +828,7 @@
|
|||||||
2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxy.swift; sourceTree = "<group>"; };
|
2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxy.swift; sourceTree = "<group>"; };
|
||||||
303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModel.swift; sourceTree = "<group>"; };
|
303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerTests.swift; sourceTree = "<group>"; };
|
30ED584467DB380E3CEFB1DB /* NotificationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerTests.swift; sourceTree = "<group>"; };
|
||||||
|
314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceipt.swift; sourceTree = "<group>"; };
|
||||||
31B35311C7FED04B0E1B80C2 /* RoomMemberDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetails.swift; sourceTree = "<group>"; };
|
31B35311C7FED04B0E1B80C2 /* RoomMemberDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetails.swift; sourceTree = "<group>"; };
|
||||||
31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModel.swift; sourceTree = "<group>"; };
|
31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyProtocol.swift; sourceTree = "<group>"; };
|
32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyProtocol.swift; sourceTree = "<group>"; };
|
||||||
@@ -845,7 +849,6 @@
|
|||||||
3948D16F021DFDB2CD26EAA8 /* MockBackgroundTaskService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBackgroundTaskService.swift; sourceTree = "<group>"; };
|
3948D16F021DFDB2CD26EAA8 /* MockBackgroundTaskService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBackgroundTaskService.swift; sourceTree = "<group>"; };
|
||||||
398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadableFrameModifier.swift; sourceTree = "<group>"; };
|
398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadableFrameModifier.swift; sourceTree = "<group>"; };
|
||||||
39B6C8690AEA1E49FF1BAF95 /* MediaUploadPreviewScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenUITests.swift; sourceTree = "<group>"; };
|
39B6C8690AEA1E49FF1BAF95 /* MediaUploadPreviewScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
3A5457B0320D028A676C248F /* TimelineReceiptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReceiptView.swift; sourceTree = "<group>"; };
|
|
||||||
3B5E97E9615A158C76B2AB77 /* DateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = "<group>"; };
|
3B5E97E9615A158C76B2AB77 /* DateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = "<group>"; };
|
||||||
3BFDAF6918BB096C44788FC9 /* RoomDetailsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenUITests.swift; sourceTree = "<group>"; };
|
3BFDAF6918BB096C44788FC9 /* RoomDetailsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
3C1A3D524D63815B28FA4D62 /* EmojiCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiCategory.swift; sourceTree = "<group>"; };
|
3C1A3D524D63815B28FA4D62 /* EmojiCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiCategory.swift; sourceTree = "<group>"; };
|
||||||
@@ -880,8 +883,9 @@
|
|||||||
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; name = DesignKit; path = DesignKit; sourceTree = SOURCE_ROOT; };
|
478BE8591BD13E908EF70C0C /* DesignKit */ = {isa = PBXFileReference; lastKnownFileType = folder; 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>"; };
|
||||||
|
47A78A43F3971B1BE8CF642E /* TimelineItemStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemStatusView.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>"; };
|
||||||
4959CECEC984B3995616F427 /* DataProtectionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataProtectionManager.swift; sourceTree = "<group>"; };
|
4959CECEC984B3995616F427 /* DataProtectionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataProtectionManager.swift; sourceTree = "<group>"; };
|
||||||
@@ -1033,7 +1037,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; path = UITests.xctestplan; sourceTree = "<group>"; };
|
8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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>"; };
|
||||||
8F61A0DD8243B395499C99A2 /* InvitesScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenUITests.swift; sourceTree = "<group>"; };
|
8F61A0DD8243B395499C99A2 /* InvitesScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
@@ -1132,7 +1136,7 @@
|
|||||||
B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModel.swift; sourceTree = "<group>"; };
|
B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModel.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; path = ConfettiScene.scn; sourceTree = "<group>"; };
|
B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; 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>"; };
|
||||||
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>"; };
|
||||||
B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsSignalling.swift; sourceTree = "<group>"; };
|
B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsSignalling.swift; sourceTree = "<group>"; };
|
||||||
@@ -1196,7 +1200,7 @@
|
|||||||
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; path = UnitTests.xctestplan; sourceTree = "<group>"; };
|
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; 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>"; };
|
||||||
D06A27D9C70E0DCC1E199163 /* OnboardingBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBackgroundView.swift; sourceTree = "<group>"; };
|
D06A27D9C70E0DCC1E199163 /* OnboardingBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBackgroundView.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>"; };
|
||||||
@@ -1262,7 +1266,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; path = message.caf; sourceTree = "<group>"; };
|
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; 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>"; };
|
||||||
@@ -2158,6 +2162,7 @@
|
|||||||
children = (
|
children = (
|
||||||
B858A61F2A570DFB8DE570A7 /* AggregratedReaction.swift */,
|
B858A61F2A570DFB8DE570A7 /* AggregratedReaction.swift */,
|
||||||
96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */,
|
96C4762F8D6112E43117DB2F /* CustomStringConvertible.swift */,
|
||||||
|
314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */,
|
||||||
5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */,
|
5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */,
|
||||||
BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */,
|
BE89A8BD65CCE3FCC925CA14 /* TimelineItemReplyDetails.swift */,
|
||||||
);
|
);
|
||||||
@@ -2964,7 +2969,8 @@
|
|||||||
children = (
|
children = (
|
||||||
D5AC06FC11B6638F7BF1670E /* TimelineDeliveryStatusView.swift */,
|
D5AC06FC11B6638F7BF1670E /* TimelineDeliveryStatusView.swift */,
|
||||||
351E89CE2ED9B73C5CC47955 /* TimelineReactionsView.swift */,
|
351E89CE2ED9B73C5CC47955 /* TimelineReactionsView.swift */,
|
||||||
3A5457B0320D028A676C248F /* TimelineReceiptView.swift */,
|
1877038D1AD3D5A029F8AE2C /* TimelineReadReceiptsView.swift */,
|
||||||
|
47A78A43F3971B1BE8CF642E /* TimelineItemStatusView.swift */,
|
||||||
);
|
);
|
||||||
path = Supplementary;
|
path = Supplementary;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -4005,6 +4011,7 @@
|
|||||||
2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */,
|
2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */,
|
||||||
743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */,
|
743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */,
|
||||||
8EF63DDDC1B54F122070B04D /* ReadMarkerRoomTimelineView.swift in Sources */,
|
8EF63DDDC1B54F122070B04D /* ReadMarkerRoomTimelineView.swift in Sources */,
|
||||||
|
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */,
|
||||||
C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */,
|
C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */,
|
||||||
AF19D65A9C60C6B2646F3210 /* RedactedRoomTimelineItem.swift in Sources */,
|
AF19D65A9C60C6B2646F3210 /* RedactedRoomTimelineItem.swift in Sources */,
|
||||||
13853973A5E24374FCEDE8A3 /* RedactedRoomTimelineView.swift in Sources */,
|
13853973A5E24374FCEDE8A3 /* RedactedRoomTimelineView.swift in Sources */,
|
||||||
@@ -4147,11 +4154,12 @@
|
|||||||
9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */,
|
9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */,
|
||||||
1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */,
|
1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */,
|
||||||
9B582B3EEFEA615D4A6FBF1A /* TimelineReactionsView.swift in Sources */,
|
9B582B3EEFEA615D4A6FBF1A /* TimelineReactionsView.swift in Sources */,
|
||||||
28A94A7DF684F2A29C4ADFE9 /* TimelineReceiptView.swift in Sources */,
|
49814A48470F347426513B07 /* TimelineReadReceiptsView.swift in Sources */,
|
||||||
2A90DD14DE5C891BFA433950 /* TimelineReplyView.swift in Sources */,
|
2A90DD14DE5C891BFA433950 /* TimelineReplyView.swift in Sources */,
|
||||||
ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */,
|
ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */,
|
||||||
C4FE0E11A907C8999F92D5A8 /* TimelineStartRoomTimelineItem.swift in Sources */,
|
C4FE0E11A907C8999F92D5A8 /* TimelineStartRoomTimelineItem.swift in Sources */,
|
||||||
6FF51EB400DBA0668FC38B97 /* TimelineStartRoomTimelineView.swift in Sources */,
|
6FF51EB400DBA0668FC38B97 /* TimelineStartRoomTimelineView.swift in Sources */,
|
||||||
|
FDFB75880BC21B297E66AB28 /* TimelineItemStatusView.swift in Sources */,
|
||||||
69BCBB4FB2DC3D61A28D3FD8 /* TimelineStyle.swift in Sources */,
|
69BCBB4FB2DC3D61A28D3FD8 /* TimelineStyle.swift in Sources */,
|
||||||
FFD3E4FF948E06C7585317FC /* TimelineStyler.swift in Sources */,
|
FFD3E4FF948E06C7585317FC /* TimelineStyler.swift in Sources */,
|
||||||
702694459B649B9D3A3C34F8 /* TimelineTableViewController.swift in Sources */,
|
702694459B649B9D3A3C34F8 /* TimelineTableViewController.swift in Sources */,
|
||||||
|
|||||||
@@ -165,8 +165,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/pointfreeco/swift-parsing",
|
"location" : "https://github.com/pointfreeco/swift-parsing",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "c6e2241daa46e5c6e5027a93b161bca6ba692bcc",
|
"revision" : "27c941bbd22a4bbc53005a15a0440443fd892f70",
|
||||||
"version" : "0.12.0"
|
"version" : "0.12.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,9 +49,12 @@ enum UserAvatarSizeOnScreen {
|
|||||||
case startChat
|
case startChat
|
||||||
case memberDetails
|
case memberDetails
|
||||||
case inviteUsers
|
case inviteUsers
|
||||||
|
case readReceipt
|
||||||
|
|
||||||
var value: CGFloat {
|
var value: CGFloat {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .readReceipt:
|
||||||
|
return 16
|
||||||
case .timeline:
|
case .timeline:
|
||||||
return 32
|
return 32
|
||||||
case .home:
|
case .home:
|
||||||
|
|||||||
@@ -77,10 +77,12 @@ struct RoomScreenViewState: BindableState {
|
|||||||
var roomTitle = ""
|
var roomTitle = ""
|
||||||
var roomAvatarURL: URL?
|
var roomAvatarURL: URL?
|
||||||
var items: [RoomTimelineViewProvider] = []
|
var items: [RoomTimelineViewProvider] = []
|
||||||
|
var members: [String: RoomMemberState] = [:]
|
||||||
var canBackPaginate = true
|
var canBackPaginate = true
|
||||||
var isBackPaginating = false
|
var isBackPaginating = false
|
||||||
var showLoading = false
|
var showLoading = false
|
||||||
var timelineStyle: TimelineStyle
|
var timelineStyle: TimelineStyle
|
||||||
|
var readReceiptsEnabled: Bool
|
||||||
|
|
||||||
var bindings: RoomScreenViewStateBindings
|
var bindings: RoomScreenViewStateBindings
|
||||||
|
|
||||||
@@ -123,3 +125,8 @@ enum RoomScreenErrorType: Hashable {
|
|||||||
/// A specific error message shown in a toast.
|
/// A specific error message shown in a toast.
|
||||||
case toast(String)
|
case toast(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RoomMemberState {
|
||||||
|
let displayName: String?
|
||||||
|
let avatarURL: URL?
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
roomTitle: roomProxy.roomTitle,
|
roomTitle: roomProxy.roomTitle,
|
||||||
roomAvatarURL: roomProxy.avatarURL,
|
roomAvatarURL: roomProxy.avatarURL,
|
||||||
timelineStyle: ServiceLocator.shared.settings.timelineStyle,
|
timelineStyle: ServiceLocator.shared.settings.timelineStyle,
|
||||||
|
readReceiptsEnabled: ServiceLocator.shared.settings.readReceiptsEnabled,
|
||||||
bindings: .init(composerText: "", composerFocused: false)),
|
bindings: .init(composerText: "", composerFocused: false)),
|
||||||
imageProvider: mediaProvider)
|
imageProvider: mediaProvider)
|
||||||
|
|
||||||
@@ -88,6 +89,19 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
ServiceLocator.shared.settings.$timelineStyle
|
ServiceLocator.shared.settings.$timelineStyle
|
||||||
.weakAssign(to: \.state.timelineStyle, on: self)
|
.weakAssign(to: \.state.timelineStyle, on: self)
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
ServiceLocator.shared.settings.$readReceiptsEnabled
|
||||||
|
.weakAssign(to: \.state.readReceiptsEnabled, on: self)
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
roomProxy.membersPublisher
|
||||||
|
.map { members in
|
||||||
|
members.reduce(into: [String: RoomMemberState]()) { dictionary, member in
|
||||||
|
dictionary[member.userID] = RoomMemberState(displayName: member.displayName, avatarURL: member.avatarURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.weakAssign(to: \.state.members, on: self)
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
buildTimelineViews()
|
buildTimelineViews()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ struct RoomScreen: View {
|
|||||||
TimelineView()
|
TimelineView()
|
||||||
.id(context.viewState.roomId)
|
.id(context.viewState.roomId)
|
||||||
.environmentObject(context)
|
.environmentObject(context)
|
||||||
.timelineStyle(context.viewState.timelineStyle)
|
.environment(\.timelineStyle, context.viewState.timelineStyle)
|
||||||
|
.environment(\.readReceiptsEnabled, context.viewState.readReceiptsEnabled)
|
||||||
.overlay(alignment: .bottomTrailing) { scrollToBottomButton }
|
.overlay(alignment: .bottomTrailing) { scrollToBottomButton }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-14
@@ -42,16 +42,28 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
|||||||
header
|
header
|
||||||
.zIndex(1)
|
.zIndex(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack {
|
VStack(alignment: alignment, spacing: 0) {
|
||||||
if timelineItem.isOutgoing {
|
HStack {
|
||||||
Spacer()
|
if timelineItem.isOutgoing {
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
|
||||||
|
messageBubbleWithReactions
|
||||||
}
|
}
|
||||||
|
.padding(timelineItem.isOutgoing ? .leading : .trailing, 40) // Extra padding to differentiate alignment.
|
||||||
|
|
||||||
messageBubbleWithReactions
|
HStack(spacing: 0) {
|
||||||
|
if !timelineItem.isOutgoing {
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
TimelineItemStatusView(timelineItem: timelineItem)
|
||||||
|
.environmentObject(context)
|
||||||
|
.padding(.top, 8)
|
||||||
|
.padding(.bottom, 3)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 16.0)
|
.padding(.horizontal, 16)
|
||||||
.padding(timelineItem.isOutgoing ? .leading : .trailing, 40) // Extra padding to differentiate alignment.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,11 +104,6 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
|||||||
context.send(viewAction: .sendReaction(key: key, eventID: timelineItem.id))
|
context.send(viewAction: .sendReaction(key: key, eventID: timelineItem.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineReceiptView(timelineItem: timelineItem)
|
|
||||||
.environmentObject(context)
|
|
||||||
.padding(.top, 10)
|
|
||||||
.padding(.bottom, 3)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +127,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
|||||||
}
|
}
|
||||||
.padding(.top, messageBubbleTopPadding)
|
.padding(.top, messageBubbleTopPadding)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
var styledContent: some View {
|
var styledContent: some View {
|
||||||
if shouldAvoidBubbling {
|
if shouldAvoidBubbling {
|
||||||
@@ -254,6 +261,9 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider {
|
|||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
mockTimeline
|
mockTimeline
|
||||||
.previewDisplayName("Mock Timeline")
|
.previewDisplayName("Mock Timeline")
|
||||||
|
mockTimeline
|
||||||
|
.environment(\.readReceiptsEnabled, true)
|
||||||
|
.previewDisplayName("Mock Timeline with read receipts")
|
||||||
mockTimeline
|
mockTimeline
|
||||||
.environment(\.layoutDirection, .rightToLeft)
|
.environment(\.layoutDirection, .rightToLeft)
|
||||||
.previewDisplayName("Mock Timeline RTL")
|
.previewDisplayName("Mock Timeline RTL")
|
||||||
@@ -267,7 +277,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider {
|
|||||||
item.padding(TimelineStyle.bubbles.rowInsets) // Insets added in the table view cells
|
item.padding(TimelineStyle.bubbles.rowInsets) // Insets added in the table view cells
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.timelineStyle(.bubbles)
|
.environment(\.timelineStyle, .bubbles)
|
||||||
.previewLayout(.sizeThatFits)
|
.previewLayout(.sizeThatFits)
|
||||||
.environmentObject(viewModel.context)
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ struct TimelineItemPlainStylerView<Content: View>: View {
|
|||||||
supplementaryViews
|
supplementaryViews
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TimelineReceiptView(timelineItem: timelineItem)
|
TimelineItemStatusView(timelineItem: timelineItem)
|
||||||
.environmentObject(context)
|
.environmentObject(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ struct TimelineItemPlainStylerView_Previews: PreviewProvider {
|
|||||||
.padding(TimelineStyle.plain.rowInsets) // Insets added in the table view cells
|
.padding(TimelineStyle.plain.rowInsets) // Insets added in the table view cells
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.timelineStyle(.plain)
|
.environment(\.timelineStyle, .plain)
|
||||||
.previewLayout(.sizeThatFits)
|
.previewLayout(.sizeThatFits)
|
||||||
.environmentObject(viewModel.context)
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ private struct TimelineGroupStyleKey: EnvironmentKey {
|
|||||||
static let defaultValue = TimelineGroupStyle.single
|
static let defaultValue = TimelineGroupStyle.single
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct ReadReceiptsEnabledKey: EnvironmentKey {
|
||||||
|
static let defaultValue = false
|
||||||
|
}
|
||||||
|
|
||||||
extension EnvironmentValues {
|
extension EnvironmentValues {
|
||||||
var timelineStyle: TimelineStyle {
|
var timelineStyle: TimelineStyle {
|
||||||
get { self[TimelineStyleKey.self] }
|
get { self[TimelineStyleKey.self] }
|
||||||
@@ -68,14 +72,9 @@ extension EnvironmentValues {
|
|||||||
get { self[TimelineGroupStyleKey.self] }
|
get { self[TimelineGroupStyleKey.self] }
|
||||||
set { self[TimelineGroupStyleKey.self] = newValue }
|
set { self[TimelineGroupStyleKey.self] = newValue }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extension View {
|
var readReceiptsEnabled: Bool {
|
||||||
func timelineStyle(_ style: TimelineStyle) -> some View {
|
get { self[ReadReceiptsEnabledKey.self] }
|
||||||
environment(\.timelineStyle, style)
|
set { self[ReadReceiptsEnabledKey.self] = newValue }
|
||||||
}
|
|
||||||
|
|
||||||
func timelineGroupStyle(_ groupStyle: TimelineGroupStyle) -> some View {
|
|
||||||
environment(\.timelineGroupStyle, groupStyle)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
// This is also going to be used for read receipts in the future
|
struct TimelineItemStatusView: View {
|
||||||
struct TimelineReceiptView: View {
|
|
||||||
let timelineItem: EventBasedTimelineItemProtocol
|
let timelineItem: EventBasedTimelineItemProtocol
|
||||||
@Environment(\.timelineStyle) private var style
|
@Environment(\.timelineStyle) private var style
|
||||||
|
@Environment(\.readReceiptsEnabled) private var readReceiptsEnabled
|
||||||
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
||||||
|
|
||||||
@State private var shouldShowDeliveryStatus = true
|
@State private var shouldShowDeliveryStatus = true
|
||||||
@@ -34,7 +34,9 @@ struct TimelineReceiptView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if shouldShowDeliveryStatus {
|
if !timelineItem.properties.orderedReadReceipts.isEmpty, readReceiptsEnabled {
|
||||||
|
readReceipts
|
||||||
|
} else if shouldShowDeliveryStatus {
|
||||||
deliveryStatus
|
deliveryStatus
|
||||||
.onChange(of: timelineItem.properties.deliveryStatus) { newValue in
|
.onChange(of: timelineItem.properties.deliveryStatus) { newValue in
|
||||||
if newValue == .sent, !isLast {
|
if newValue == .sent, !isLast {
|
||||||
@@ -71,4 +73,9 @@ struct TimelineReceiptView: View {
|
|||||||
// The bubbles handle the failure internally
|
// The bubbles handle the failure internally
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var readReceipts: some View {
|
||||||
|
TimelineReadReceiptsView(timelineItem: timelineItem)
|
||||||
|
.environmentObject(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
struct TimelineReadReceiptsView: View {
|
||||||
|
let displayNumber = 3
|
||||||
|
let timelineItem: EventBasedTimelineItemProtocol
|
||||||
|
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack(spacing: 2) {
|
||||||
|
HStack(spacing: -4) {
|
||||||
|
let receiptsToDisplay = timelineItem.properties.orderedReadReceipts.prefix(displayNumber)
|
||||||
|
ForEach(0..<receiptsToDisplay.count, id: \.self) { index in
|
||||||
|
let receipt = receiptsToDisplay[index]
|
||||||
|
LoadableAvatarImage(url: context.viewState.members[receipt.userID]?.avatarURL,
|
||||||
|
name: context.viewState.members[receipt.userID]?.displayName,
|
||||||
|
contentID: receipt.userID,
|
||||||
|
avatarSize: .user(on: .readReceipt),
|
||||||
|
imageProvider: context.imageProvider)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: .infinity)
|
||||||
|
.stroke(Color.element.background, lineWidth: 1)
|
||||||
|
)
|
||||||
|
.zIndex(Double(displayNumber - index))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if timelineItem.properties.orderedReadReceipts.count > displayNumber {
|
||||||
|
let remaining = timelineItem.properties.orderedReadReceipts.count - displayNumber
|
||||||
|
Text("+\(remaining)")
|
||||||
|
.font(.compound.bodySM)
|
||||||
|
.foregroundColor(.element.primaryContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TimelineReadReceiptsView_Previews: PreviewProvider {
|
||||||
|
static let members: [RoomMemberProxyMock] = [
|
||||||
|
.mockAlice,
|
||||||
|
.mockBob,
|
||||||
|
.mockCharlie,
|
||||||
|
.mockDan,
|
||||||
|
.mockMe
|
||||||
|
]
|
||||||
|
|
||||||
|
static let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(),
|
||||||
|
mediaProvider: MockMediaProvider(),
|
||||||
|
roomProxy: RoomProxyMock(with: .init(displayName: "Test",
|
||||||
|
members: members)))
|
||||||
|
|
||||||
|
static let singleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now")]
|
||||||
|
static let doubleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"),
|
||||||
|
ReadReceipt(userID: RoomMemberProxyMock.mockBob.userID, formattedTimestamp: "Before")]
|
||||||
|
static let tripleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"),
|
||||||
|
ReadReceipt(userID: RoomMemberProxyMock.mockBob.userID, formattedTimestamp: "Before"),
|
||||||
|
ReadReceipt(userID: RoomMemberProxyMock.mockCharlie.userID, formattedTimestamp: "Way before")]
|
||||||
|
static let quadrupleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"),
|
||||||
|
ReadReceipt(userID: RoomMemberProxyMock.mockBob.userID, formattedTimestamp: "Before"),
|
||||||
|
ReadReceipt(userID: RoomMemberProxyMock.mockCharlie.userID, formattedTimestamp: "Way before"),
|
||||||
|
ReadReceipt(userID: RoomMemberProxyMock.mockDan.userID, formattedTimestamp: "Way, way before")]
|
||||||
|
|
||||||
|
static func mockTimelineItem(with receipts: [ReadReceipt]) -> TextRoomTimelineItem {
|
||||||
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
|
timestamp: "Now",
|
||||||
|
isOutgoing: true,
|
||||||
|
isEditable: false, sender: .init(id: UUID().uuidString), content: .init(body: "Test"),
|
||||||
|
properties: .init(orderedReadReceipts: receipts))
|
||||||
|
}
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
VStack {
|
||||||
|
TimelineReadReceiptsView(timelineItem: mockTimelineItem(with: singleReceipt))
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
|
TimelineReadReceiptsView(timelineItem: mockTimelineItem(with: doubleReceipt))
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
|
TimelineReadReceiptsView(timelineItem: mockTimelineItem(with: tripleReceipt))
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
|
TimelineReadReceiptsView(timelineItem: mockTimelineItem(with: quadrupleReceipt))
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,7 +38,9 @@ struct AudioRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ struct EmoteRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ struct EncryptedRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ struct FileRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ struct FormattedBodyText_Previews: PreviewProvider {
|
|||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body
|
body
|
||||||
body
|
body
|
||||||
.timelineStyle(.plain)
|
.environment(\.timelineStyle, .plain)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ struct ImageRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ struct NoticeRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ struct StateRoomTimelineView: View {
|
|||||||
struct StateRoomTimelineView_Previews: PreviewProvider {
|
struct StateRoomTimelineView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body
|
body
|
||||||
body.timelineStyle(.plain)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -51,7 +51,9 @@ struct StickerRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ struct TextRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ struct UnsupportedRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
@@ -70,7 +70,9 @@ struct VideoRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
body.environmentObject(viewModel.context)
|
body.environmentObject(viewModel.context)
|
||||||
body.timelineStyle(.plain).environmentObject(viewModel.context)
|
body
|
||||||
|
.environment(\.timelineStyle, .plain)
|
||||||
|
.environmentObject(viewModel.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: some View {
|
static var body: some View {
|
||||||
|
|||||||
+2
@@ -27,10 +27,12 @@ struct DeveloperOptionsScreenViewState: BindableState {
|
|||||||
struct DeveloperOptionsScreenViewStateBindings {
|
struct DeveloperOptionsScreenViewStateBindings {
|
||||||
var shouldCollapseRoomStateEvents: Bool
|
var shouldCollapseRoomStateEvents: Bool
|
||||||
var userSuggestionsEnabled: Bool
|
var userSuggestionsEnabled: Bool
|
||||||
|
var readReceiptsEnabled: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DeveloperOptionsScreenViewAction {
|
enum DeveloperOptionsScreenViewAction {
|
||||||
case changedShouldCollapseRoomStateEvents
|
case changedShouldCollapseRoomStateEvents
|
||||||
case changedUserSuggestionsEnabled
|
case changedUserSuggestionsEnabled
|
||||||
|
case changedReadReceiptsEnabled
|
||||||
case clearCache
|
case clearCache
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -26,7 +26,8 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve
|
|||||||
init() {
|
init() {
|
||||||
appSettings = ServiceLocator.shared.settings
|
appSettings = ServiceLocator.shared.settings
|
||||||
let bindings = DeveloperOptionsScreenViewStateBindings(shouldCollapseRoomStateEvents: appSettings.shouldCollapseRoomStateEvents,
|
let bindings = DeveloperOptionsScreenViewStateBindings(shouldCollapseRoomStateEvents: appSettings.shouldCollapseRoomStateEvents,
|
||||||
userSuggestionsEnabled: appSettings.userSuggestionsEnabled)
|
userSuggestionsEnabled: appSettings.userSuggestionsEnabled,
|
||||||
|
readReceiptsEnabled: appSettings.readReceiptsEnabled)
|
||||||
let state = DeveloperOptionsScreenViewState(bindings: bindings)
|
let state = DeveloperOptionsScreenViewState(bindings: bindings)
|
||||||
|
|
||||||
super.init(initialViewState: state)
|
super.init(initialViewState: state)
|
||||||
@@ -42,6 +43,8 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve
|
|||||||
appSettings.shouldCollapseRoomStateEvents = state.bindings.shouldCollapseRoomStateEvents
|
appSettings.shouldCollapseRoomStateEvents = state.bindings.shouldCollapseRoomStateEvents
|
||||||
case .changedUserSuggestionsEnabled:
|
case .changedUserSuggestionsEnabled:
|
||||||
appSettings.userSuggestionsEnabled = state.bindings.userSuggestionsEnabled
|
appSettings.userSuggestionsEnabled = state.bindings.userSuggestionsEnabled
|
||||||
|
case .changedReadReceiptsEnabled:
|
||||||
|
appSettings.readReceiptsEnabled = state.bindings.readReceiptsEnabled
|
||||||
case .clearCache:
|
case .clearCache:
|
||||||
callback?(.clearCache)
|
callback?(.clearCache)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -36,6 +36,13 @@ struct DeveloperOptionsScreen: View {
|
|||||||
.onChange(of: context.userSuggestionsEnabled) { _ in
|
.onChange(of: context.userSuggestionsEnabled) { _ in
|
||||||
context.send(viewAction: .changedUserSuggestionsEnabled)
|
context.send(viewAction: .changedUserSuggestionsEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Toggle(isOn: $context.readReceiptsEnabled) {
|
||||||
|
Text("Show read receipts")
|
||||||
|
}
|
||||||
|
.onChange(of: context.readReceiptsEnabled) { _ in
|
||||||
|
context.send(viewAction: .changedReadReceiptsEnabled)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ enum RoomTimelineItemFixtures {
|
|||||||
isOutgoing: false,
|
isOutgoing: false,
|
||||||
isEditable: false,
|
isEditable: false,
|
||||||
sender: .init(id: "", displayName: "Helena"),
|
sender: .init(id: "", displayName: "Helena"),
|
||||||
content: .init(body: "Wow, cool. Ok, lets go the usual place tomorrow?! Is that too soon? Here’s the menu, let me know what you want it’s on me!")),
|
content: .init(body: "Wow, cool. Ok, lets go the usual place tomorrow?! Is that too soon? Here’s the menu, let me know what you want it’s on me!"),
|
||||||
|
properties: RoomTimelineItemProperties(orderedReadReceipts: [ReadReceipt(userID: "alice", formattedTimestamp: nil)])),
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
timestamp: "5 PM",
|
timestamp: "5 PM",
|
||||||
isOutgoing: true,
|
isOutgoing: true,
|
||||||
@@ -68,7 +69,11 @@ enum RoomTimelineItemFixtures {
|
|||||||
properties: RoomTimelineItemProperties(reactions: [
|
properties: RoomTimelineItemProperties(reactions: [
|
||||||
AggregatedReaction(key: "🙏", count: 1, isHighlighted: false),
|
AggregatedReaction(key: "🙏", count: 1, isHighlighted: false),
|
||||||
AggregatedReaction(key: "😁", count: 3, isHighlighted: false)
|
AggregatedReaction(key: "😁", count: 3, isHighlighted: false)
|
||||||
])),
|
],
|
||||||
|
orderedReadReceipts: [ReadReceipt(userID: "alice", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "bob", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "charlie", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "dan", formattedTimestamp: nil)])),
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
timestamp: "5 PM",
|
timestamp: "5 PM",
|
||||||
isOutgoing: false,
|
isOutgoing: false,
|
||||||
@@ -85,6 +90,28 @@ enum RoomTimelineItemFixtures {
|
|||||||
TextRoomTimelineItem(text: "How are you?",
|
TextRoomTimelineItem(text: "How are you?",
|
||||||
senderDisplayName: "Alice")]
|
senderDisplayName: "Alice")]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A small chunk of events, containing 2 text items.
|
||||||
|
static var smallChunkWithReadReceipts: [RoomTimelineItemProtocol] {
|
||||||
|
[TextRoomTimelineItem(text: "Hey there 👋",
|
||||||
|
senderDisplayName: "Alice")
|
||||||
|
.withReadReceipts([ReadReceipt(userID: "a1", formattedTimestamp: nil)]),
|
||||||
|
TextRoomTimelineItem(text: "How are you?",
|
||||||
|
senderDisplayName: "Alice")
|
||||||
|
.withReadReceipts([ReadReceipt(userID: "a2", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "b2", formattedTimestamp: nil)]),
|
||||||
|
TextRoomTimelineItem(text: "Fine, Thanks!",
|
||||||
|
senderDisplayName: "Bob")
|
||||||
|
.withReadReceipts([ReadReceipt(userID: "a3", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "b3", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "c3", formattedTimestamp: nil)]),
|
||||||
|
TextRoomTimelineItem(text: "What about you?",
|
||||||
|
senderDisplayName: "Bob")
|
||||||
|
.withReadReceipts([ReadReceipt(userID: "a4", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "b4", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "c4", formattedTimestamp: nil),
|
||||||
|
ReadReceipt(userID: "d4", formattedTimestamp: nil)])]
|
||||||
|
}
|
||||||
|
|
||||||
/// A chunk of events that contains a single text item.
|
/// A chunk of events that contains a single text item.
|
||||||
static var singleMessageChunk: [RoomTimelineItemProtocol] {
|
static var singleMessageChunk: [RoomTimelineItemProtocol] {
|
||||||
@@ -194,3 +221,11 @@ private extension TextRoomTimelineItem {
|
|||||||
content: .init(body: text))
|
content: .init(body: text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension TextRoomTimelineItem {
|
||||||
|
func withReadReceipts(_ receipts: [ReadReceipt]) -> TextRoomTimelineItem {
|
||||||
|
var newSelf = self
|
||||||
|
newSelf.properties.orderedReadReceipts = receipts
|
||||||
|
return newSelf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// 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 ReadReceipt: Hashable {
|
||||||
|
let userID: String
|
||||||
|
let formattedTimestamp: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ReadReceipt: Identifiable {
|
||||||
|
var id: String { userID }
|
||||||
|
}
|
||||||
+2
@@ -24,4 +24,6 @@ struct RoomTimelineItemProperties: Hashable {
|
|||||||
var reactions: [AggregatedReaction] = []
|
var reactions: [AggregatedReaction] = []
|
||||||
/// The delivery status for this item. If a sent message is echoed the value is nil.
|
/// The delivery status for this item. If a sent message is echoed the value is nil.
|
||||||
var deliveryStatus: TimelineItemDeliveryStatus?
|
var deliveryStatus: TimelineItemDeliveryStatus?
|
||||||
|
/// The read receipts of the item, ordered from newest to oldest
|
||||||
|
var orderedReadReceipts: [ReadReceipt] = []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
aspectRatio: aspectRatio,
|
aspectRatio: aspectRatio,
|
||||||
blurhash: imageInfo.blurhash,
|
blurhash: imageInfo.blurhash,
|
||||||
properties: RoomTimelineItemProperties(reactions: aggregateReactions(eventItemProxy.reactions),
|
properties: RoomTimelineItemProperties(reactions: aggregateReactions(eventItemProxy.reactions),
|
||||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||||
|
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func buildEncryptedTimelineItem(_ eventItemProxy: EventTimelineItemProxy,
|
private func buildEncryptedTimelineItem(_ eventItemProxy: EventTimelineItemProxy,
|
||||||
@@ -182,7 +183,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
||||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||||
|
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func buildImageTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
private func buildImageTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||||
@@ -198,7 +200,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
||||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||||
|
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func buildVideoTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
private func buildVideoTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||||
@@ -214,7 +217,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
||||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||||
|
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func buildAudioTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
private func buildAudioTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||||
@@ -230,7 +234,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
||||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||||
|
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func buildFileTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
private func buildFileTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||||
@@ -246,7 +251,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
||||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||||
|
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func buildNoticeTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
private func buildNoticeTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||||
@@ -262,7 +268,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
||||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||||
|
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func buildEmoteTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
private func buildEmoteTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||||
@@ -278,7 +285,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
replyDetails: buildReplyToDetailsFrom(details: messageTimelineItem.inReplyTo()),
|
||||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||||
deliveryStatus: eventItemProxy.deliveryStatus))
|
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||||
|
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func aggregateReactions(_ reactions: [Reaction]) -> [AggregatedReaction] {
|
private func aggregateReactions(_ reactions: [Reaction]) -> [AggregatedReaction] {
|
||||||
@@ -287,6 +295,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
return AggregatedReaction(key: reaction.key, count: Int(reaction.count), isHighlighted: isHighlighted)
|
return AggregatedReaction(key: reaction.key, count: Int(reaction.count), isHighlighted: isHighlighted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func orderReadReceipts(_ receipts: [String: Receipt]) -> [ReadReceipt] {
|
||||||
|
receipts
|
||||||
|
.sorted { firstElement, secondElement in
|
||||||
|
// If there is no timestamp we order them as last
|
||||||
|
let firstTimestamp = firstElement.value.dateTimestamp ?? Date(timeIntervalSince1970: 0)
|
||||||
|
let secondTimestamp = secondElement.value.dateTimestamp ?? Date(timeIntervalSince1970: 0)
|
||||||
|
return firstTimestamp > secondTimestamp
|
||||||
|
}
|
||||||
|
.map { key, receipt in
|
||||||
|
ReadReceipt(userID: key, formattedTimestamp: receipt.dateTimestamp?.formatted(date: .omitted, time: .shortened))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Message events content
|
// MARK: - Message events content
|
||||||
|
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ enum RoomTimelineViewProvider: Identifiable, Hashable {
|
|||||||
extension RoomTimelineViewProvider: View {
|
extension RoomTimelineViewProvider: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
timelineView
|
timelineView
|
||||||
.timelineGroupStyle(timelineGroupStyle)
|
.environment(\.timelineGroupStyle, timelineGroupStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder private var timelineView: some View {
|
@ViewBuilder private var timelineView: some View {
|
||||||
|
|||||||
@@ -197,6 +197,18 @@ class MockScreen: Identifiable {
|
|||||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
return navigationStackCoordinator
|
return navigationStackCoordinator
|
||||||
|
case .roomSmallTimelineWithReadReceipts:
|
||||||
|
ServiceLocator.shared.settings.readReceiptsEnabled = true
|
||||||
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
|
let timelineController = MockRoomTimelineController()
|
||||||
|
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunkWithReadReceipts
|
||||||
|
let parameters = RoomScreenCoordinatorParameters(roomProxy: RoomProxyMock(with: .init(displayName: "New room", avatarURL: URL.picturesDirectory)),
|
||||||
|
timelineController: timelineController,
|
||||||
|
mediaProvider: MockMediaProvider(),
|
||||||
|
emojiProvider: EmojiProvider())
|
||||||
|
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||||
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
|
return navigationStackCoordinator
|
||||||
case .roomSmallTimelineIncomingAndSmallPagination:
|
case .roomSmallTimelineIncomingAndSmallPagination:
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ enum UITestsScreenIdentifier: String {
|
|||||||
case roomPlainNoAvatar
|
case roomPlainNoAvatar
|
||||||
case roomEncryptedWithAvatar
|
case roomEncryptedWithAvatar
|
||||||
case roomSmallTimeline
|
case roomSmallTimeline
|
||||||
|
case roomSmallTimelineWithReadReceipts
|
||||||
case roomSmallTimelineIncomingAndSmallPagination
|
case roomSmallTimelineIncomingAndSmallPagination
|
||||||
case roomSmallTimelineLargePagination
|
case roomSmallTimelineLargePagination
|
||||||
case roomLayoutTop
|
case roomLayoutTop
|
||||||
|
|||||||
@@ -153,6 +153,13 @@ class RoomScreenUITests: XCTestCase {
|
|||||||
|
|
||||||
try await app.assertScreenshot(.roomLayoutBottom, step: 1)
|
try await app.assertScreenshot(.roomLayoutBottom, step: 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testTimelineReadReceipts() async throws {
|
||||||
|
let app = Application.launch(.roomSmallTimelineWithReadReceipts)
|
||||||
|
|
||||||
|
// The messages should be bottom aligned.
|
||||||
|
try await app.assertScreenshot(.roomSmallTimelineWithReadReceipts)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Helper Methods
|
// MARK: - Helper Methods
|
||||||
|
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e1a51a634a8e8f9c4c55a8068d7f0cbf6b6658dd31fd8dfc82bb59dd83a9b31c
|
||||||
|
size 123189
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a64e6084d03b2b61b52528525f39042f95d1a01544d729af236ef81e9359540b
|
||||||
|
size 188024
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:bace67ffd6d2f7df36127fb6499ce7f9af2182d49acb89ab475bc9269e7b7447
|
||||||
|
size 124167
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:126045309c9d7d8f7ebf5a55076cdc2258ff96c4a91fb018639096445a7e7b62
|
||||||
|
size 189910
|
||||||
Reference in New Issue
Block a user