mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Polls history (#2244)
This commit is contained in:
@@ -92,6 +92,7 @@
|
|||||||
1471A080552631358D152C18 /* AudioPlayerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */; };
|
1471A080552631358D152C18 /* AudioPlayerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */; };
|
||||||
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */; };
|
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */; };
|
||||||
14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */; };
|
14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A9F49B3EE59147AF2F70BB /* SeparatorRoomTimelineItem.swift */; };
|
||||||
|
151D2477F75782C8702F2873 /* PollInteractionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */; };
|
||||||
152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */; };
|
152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */; };
|
||||||
153E22E8227F46545E5D681C /* PollRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C936FDD017808FE416742D64 /* PollRoomTimelineView.swift */; };
|
153E22E8227F46545E5D681C /* PollRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C936FDD017808FE416742D64 /* PollRoomTimelineView.swift */; };
|
||||||
155063E980E763D4910EA3CF /* Analytics+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */; };
|
155063E980E763D4910EA3CF /* Analytics+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */; };
|
||||||
@@ -127,6 +128,7 @@
|
|||||||
1D623953F970D11F6F38499C /* AppLockService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851B95BB98649B8E773D6790 /* AppLockService.swift */; };
|
1D623953F970D11F6F38499C /* AppLockService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851B95BB98649B8E773D6790 /* AppLockService.swift */; };
|
||||||
1D69E31913DF66426985909B /* EmojiPickerScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */; };
|
1D69E31913DF66426985909B /* EmojiPickerScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */; };
|
||||||
1E59B77A0B2CE83DCC1B203C /* LoginViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05707BF550D770168A406DB /* LoginViewModelTests.swift */; };
|
1E59B77A0B2CE83DCC1B203C /* LoginViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05707BF550D770168A406DB /* LoginViewModelTests.swift */; };
|
||||||
|
1EC6D1B58B24369734CD62BA /* PollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317F41A4B5C4F457AF710666 /* PollView.swift */; };
|
||||||
1F04C63D4FA95948E3F52147 /* FileRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51E3D86A84341C3A0CB8A40 /* FileRoomTimelineView.swift */; };
|
1F04C63D4FA95948E3F52147 /* FileRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51E3D86A84341C3A0CB8A40 /* FileRoomTimelineView.swift */; };
|
||||||
1F3232BD368DF430AB433907 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 07FEEEDB11543A7DED420F04 /* Compound */; };
|
1F3232BD368DF430AB433907 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 07FEEEDB11543A7DED420F04 /* Compound */; };
|
||||||
1FE593ECEC40A43789105D80 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; };
|
1FE593ECEC40A43789105D80 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; };
|
||||||
@@ -315,6 +317,7 @@
|
|||||||
50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; };
|
50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542D4F49FABA056DEEEB3400 /* RustTracing.swift */; };
|
||||||
5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */; };
|
5100F53E6884A15F9BA07CC3 /* AttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */; };
|
||||||
518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; };
|
518C93DC6516D3D018DE065F /* UNNotificationRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */; };
|
||||||
|
51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */; };
|
||||||
51C240F4660F7269203A9B3A /* MigrationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */; };
|
51C240F4660F7269203A9B3A /* MigrationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */; };
|
||||||
520EEDAFBC778AB0B41F2F53 /* ClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */; };
|
520EEDAFBC778AB0B41F2F53 /* ClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE6170EFE6A161B0A68AB61 /* ClientMock.swift */; };
|
||||||
523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */; };
|
523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */; };
|
||||||
@@ -410,7 +413,6 @@
|
|||||||
6AECC84BE14A13440120FED8 /* NSESettingsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB4F169D653296023ED65E6 /* NSESettingsProtocol.swift */; };
|
6AECC84BE14A13440120FED8 /* NSESettingsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FB4F169D653296023ED65E6 /* NSESettingsProtocol.swift */; };
|
||||||
6B05AA5D9BBCD6D8D63B80EB /* TimelineItemAccessibilityModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C6F3DAD167F972702C8893 /* TimelineItemAccessibilityModifier.swift */; };
|
6B05AA5D9BBCD6D8D63B80EB /* TimelineItemAccessibilityModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C6F3DAD167F972702C8893 /* TimelineItemAccessibilityModifier.swift */; };
|
||||||
6B31508C6334C617360C2EAB /* RoomMemberDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */; };
|
6B31508C6334C617360C2EAB /* RoomMemberDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */; };
|
||||||
6B4BF4A6450F55939B49FAEF /* PollOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67779D9A1B797285A09B7720 /* PollOptionView.swift */; };
|
|
||||||
6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */; };
|
6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */; };
|
||||||
6BB6944443C421C722ED1E7D /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */; };
|
6BB6944443C421C722ED1E7D /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */; };
|
||||||
6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; };
|
6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; };
|
||||||
@@ -464,10 +466,13 @@
|
|||||||
784592335560C2E91D32D177 /* DeveloperOptionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */; };
|
784592335560C2E91D32D177 /* DeveloperOptionsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06B098A612DCB5A7358EECD5 /* DeveloperOptionsScreenModels.swift */; };
|
||||||
78A3392047E9D1C6FEA659B6 /* InvitesScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33649299575BADC34924ABC6 /* InvitesScreenCoordinator.swift */; };
|
78A3392047E9D1C6FEA659B6 /* InvitesScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33649299575BADC34924ABC6 /* InvitesScreenCoordinator.swift */; };
|
||||||
795A854F63301DC6B46217B9 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; };
|
795A854F63301DC6B46217B9 /* AccessibilityIdentifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */; };
|
||||||
|
79741C1953269FF1A211D246 /* RoomPollsHistoryScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */; };
|
||||||
|
7A02EB29F3B993AB20E0A198 /* RoomPollsHistoryScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */; };
|
||||||
7A0A0929556792FB19B812C5 /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84816E0D2F34E368BF64FA60 /* SessionVerificationScreen.swift */; };
|
7A0A0929556792FB19B812C5 /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84816E0D2F34E368BF64FA60 /* SessionVerificationScreen.swift */; };
|
||||||
7A642EE5F1ADC5D520F21924 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; };
|
7A642EE5F1ADC5D520F21924 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85EB16E7FE59A947CA441531 /* MediaProviderProtocol.swift */; };
|
||||||
7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; };
|
7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; };
|
||||||
7AEC56ADEFC5A7198A17412F /* InviteUsersScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADB35E2DB4EFE8E6F3959629 /* InviteUsersScreenUITests.swift */; };
|
7AEC56ADEFC5A7198A17412F /* InviteUsersScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADB35E2DB4EFE8E6F3959629 /* InviteUsersScreenUITests.swift */; };
|
||||||
|
7B1605C6FFD4D195F264A684 /* RoomPollsHistoryScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40233F2989AD49906BB310D /* RoomPollsHistoryScreenViewModelTests.swift */; };
|
||||||
7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */; };
|
7B5DAB915357BE596529BF25 /* MapTilerStaticMapProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20872C3887F835958CE2F1D0 /* MapTilerStaticMapProtocol.swift */; };
|
||||||
7BB31E67648CF32D2AB5E502 /* RoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */; };
|
7BB31E67648CF32D2AB5E502 /* RoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */; };
|
||||||
7BF368A78E6D9AFD222F25AF /* SecureBackupScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE094FCB6387D268C436161 /* SecureBackupScreenViewModel.swift */; };
|
7BF368A78E6D9AFD222F25AF /* SecureBackupScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE094FCB6387D268C436161 /* SecureBackupScreenViewModel.swift */; };
|
||||||
@@ -497,6 +502,7 @@
|
|||||||
828EA5009557C2B9DCD4CA0F /* UserDiscoverySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */; };
|
828EA5009557C2B9DCD4CA0F /* UserDiscoverySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */; };
|
||||||
829062DD3C3F7016FE1A6476 /* RoomDetailsScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BFDAF6918BB096C44788FC9 /* RoomDetailsScreenUITests.swift */; };
|
829062DD3C3F7016FE1A6476 /* RoomDetailsScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BFDAF6918BB096C44788FC9 /* RoomDetailsScreenUITests.swift */; };
|
||||||
8317E1314C00DCCC99D30DA8 /* TextBasedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9227F7495DA43324050A863 /* TextBasedRoomTimelineItem.swift */; };
|
8317E1314C00DCCC99D30DA8 /* TextBasedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9227F7495DA43324050A863 /* TextBasedRoomTimelineItem.swift */; };
|
||||||
|
835B7AD20407F766C747BEC5 /* RoomPollsHistoryScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D147EB979902DBBE452EADC /* RoomPollsHistoryScreenUITests.swift */; };
|
||||||
83A4DAB181C56987C3E804FF /* MapTilerStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B9F5BC4C80543DE7228B9D /* MapTilerStyle.swift */; };
|
83A4DAB181C56987C3E804FF /* MapTilerStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B9F5BC4C80543DE7228B9D /* MapTilerStyle.swift */; };
|
||||||
84226AD2E1F1FBC965F3B09E /* UnitTestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8E19C4645D3F5F9FB02355 /* UnitTestsAppCoordinator.swift */; };
|
84226AD2E1F1FBC965F3B09E /* UnitTestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8E19C4645D3F5F9FB02355 /* UnitTestsAppCoordinator.swift */; };
|
||||||
8478992479B296C45150208F /* AppLockScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */; };
|
8478992479B296C45150208F /* AppLockScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */; };
|
||||||
@@ -554,6 +560,7 @@
|
|||||||
9095B9E40DB5CF8BA26CE0D8 /* ReactionsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 153726EDCE1ACBB3D466A916 /* ReactionsSummaryView.swift */; };
|
9095B9E40DB5CF8BA26CE0D8 /* ReactionsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 153726EDCE1ACBB3D466A916 /* ReactionsSummaryView.swift */; };
|
||||||
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 */; };
|
||||||
|
915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; };
|
||||||
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; };
|
91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; };
|
||||||
92133B170A1F917685E9FF78 /* OnboardingScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D168471461717AF5689F64B /* OnboardingScreenUITests.swift */; };
|
92133B170A1F917685E9FF78 /* OnboardingScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D168471461717AF5689F64B /* OnboardingScreenUITests.swift */; };
|
||||||
9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; };
|
9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; };
|
||||||
@@ -884,6 +891,7 @@
|
|||||||
E4B07FF075C99D04D9AF792D /* AppLockSetupPINScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */; };
|
E4B07FF075C99D04D9AF792D /* AppLockSetupPINScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */; };
|
||||||
E4BAEED438A843D7B01D8069 /* CompletionSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F421E51DF00377DE1A01354 /* CompletionSuggestionView.swift */; };
|
E4BAEED438A843D7B01D8069 /* CompletionSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F421E51DF00377DE1A01354 /* CompletionSuggestionView.swift */; };
|
||||||
E570117376826665640F0CFD /* SessionVerificationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16CAF20C9AC874A210E2DCF /* SessionVerificationScreenViewModelProtocol.swift */; };
|
E570117376826665640F0CFD /* SessionVerificationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16CAF20C9AC874A210E2DCF /* SessionVerificationScreenViewModelProtocol.swift */; };
|
||||||
|
E58F1F3276E98A93F7D39219 /* RoomPollsHistoryScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1D8479BB704B7EF696F8ABE /* RoomPollsHistoryScreenCoordinator.swift */; };
|
||||||
E5F4C992845388B50BABACAA /* ServerSelectionScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */; };
|
E5F4C992845388B50BABACAA /* ServerSelectionScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */; };
|
||||||
E62EC30B39354A391E32A126 /* AudioRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2D505742FDA21FCDC4C18A /* AudioRoomTimelineView.swift */; };
|
E62EC30B39354A391E32A126 /* AudioRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2D505742FDA21FCDC4C18A /* AudioRoomTimelineView.swift */; };
|
||||||
E67418DACEDBC29E988E6ACD /* message.caf in Resources */ = {isa = PBXBuildFile; fileRef = ED482057AE39D5C6D9C5F3D8 /* message.caf */; };
|
E67418DACEDBC29E988E6ACD /* message.caf in Resources */ = {isa = PBXBuildFile; fileRef = ED482057AE39D5C6D9C5F3D8 /* message.caf */; };
|
||||||
@@ -933,6 +941,7 @@
|
|||||||
F07D88421A9BC4D03D4A5055 /* VideoRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */; };
|
F07D88421A9BC4D03D4A5055 /* VideoRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */; };
|
||||||
F0A26CD502C3A5868353B0FA /* ServerConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */; };
|
F0A26CD502C3A5868353B0FA /* ServerConfirmationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */; };
|
||||||
F0F82C3C848C865C3098AA52 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 21C83087604B154AA30E9A8F /* SnapshotTesting */; };
|
F0F82C3C848C865C3098AA52 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 21C83087604B154AA30E9A8F /* SnapshotTesting */; };
|
||||||
|
F103924DED414ADFE398CE99 /* RoomPollsHistoryScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */; };
|
||||||
F118DD449066E594F63C697D /* RoomMemberProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */; };
|
F118DD449066E594F63C697D /* RoomMemberProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B5E17028C02DFA7DDA3931 /* RoomMemberProxyProtocol.swift */; };
|
||||||
F12F6BED7B6D7EE4BEE55039 /* PlainMentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */; };
|
F12F6BED7B6D7EE4BEE55039 /* PlainMentionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AE78FA0011E07920AE83135 /* PlainMentionBuilder.swift */; };
|
||||||
F16109A6F6DF03DA26D59233 /* RoomDetailsEditScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 122186B7CD1BC46A9C629DD9 /* RoomDetailsEditScreenUITests.swift */; };
|
F16109A6F6DF03DA26D59233 /* RoomDetailsEditScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 122186B7CD1BC46A9C629DD9 /* RoomDetailsEditScreenUITests.swift */; };
|
||||||
@@ -948,6 +957,7 @@
|
|||||||
F4433EF57B4BB3C077F8B00E /* SessionVerificationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD9E0FFA29EAACFF3AB9732 /* SessionVerificationScreenViewModel.swift */; };
|
F4433EF57B4BB3C077F8B00E /* SessionVerificationScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD9E0FFA29EAACFF3AB9732 /* SessionVerificationScreenViewModel.swift */; };
|
||||||
F4971845B5C4F270F6BC5745 /* ScaledFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */; };
|
F4971845B5C4F270F6BC5745 /* ScaledFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D82F234B3576BD6268C7950 /* ScaledFrameModifier.swift */; };
|
||||||
F508683B76EF7B23BB2CBD6D /* TimelineItemPlainStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94BCC8A9C73C1F838122C645 /* TimelineItemPlainStylerView.swift */; };
|
F508683B76EF7B23BB2CBD6D /* TimelineItemPlainStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94BCC8A9C73C1F838122C645 /* TimelineItemPlainStylerView.swift */; };
|
||||||
|
F50A6FCE26714E27FE5495DD /* PollOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50F23B21CF15F9F4BAA0788B /* PollOptionView.swift */; };
|
||||||
F519DE17A3A0F760307B2E6D /* InviteUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */; };
|
F519DE17A3A0F760307B2E6D /* InviteUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D155E09BF961BBA8F85263 /* InviteUsersScreenViewModel.swift */; };
|
||||||
F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */; };
|
F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E60332509665C00179ACF6 /* MessageForwardingScreenViewModel.swift */; };
|
||||||
F5D2270B5021D521C0D22E11 /* FlowCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */; };
|
F5D2270B5021D521C0D22E11 /* FlowCoordinatorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9FCA1CFD07B8CF9BD21266 /* FlowCoordinatorProtocol.swift */; };
|
||||||
@@ -1083,6 +1093,7 @@
|
|||||||
0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenCoordinator.swift; sourceTree = "<group>"; };
|
0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
0CCC6C31102E1D8B9106DEDE /* AppLockSetupBiometricsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenModels.swift; sourceTree = "<group>"; };
|
0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenModels.swift; sourceTree = "<group>"; };
|
||||||
|
0D147EB979902DBBE452EADC /* RoomPollsHistoryScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
0D8F620C8B314840D8602E3F /* NSE.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = NSE.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
0D8F620C8B314840D8602E3F /* NSE.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = NSE.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupFlowCoordinator.swift; sourceTree = "<group>"; };
|
0DBB08A95EFA668F2CF27211 /* AppLockSetupFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupFlowCoordinator.swift; sourceTree = "<group>"; };
|
||||||
0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentionalMentions.swift; sourceTree = "<group>"; };
|
0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentionalMentions.swift; sourceTree = "<group>"; };
|
||||||
@@ -1180,6 +1191,7 @@
|
|||||||
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxyMock.swift; sourceTree = "<group>"; };
|
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxyMock.swift; sourceTree = "<group>"; };
|
||||||
24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModel.swift; sourceTree = "<group>"; };
|
24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollInteractionHandlerProtocol.swift; sourceTree = "<group>"; };
|
||||||
25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = "<group>"; };
|
||||||
@@ -1216,6 +1228,7 @@
|
|||||||
309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriver.swift; sourceTree = "<group>"; };
|
309AD8BAE6437C31BA7157BF /* ElementCallWidgetDriver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriver.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>"; };
|
314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceipt.swift; sourceTree = "<group>"; };
|
||||||
|
317F41A4B5C4F457AF710666 /* PollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollView.swift; sourceTree = "<group>"; };
|
||||||
31A6314FDC51DA25712D9A81 /* PillContextTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillContextTests.swift; sourceTree = "<group>"; };
|
31A6314FDC51DA25712D9A81 /* PillContextTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillContextTests.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>"; };
|
||||||
@@ -1280,6 +1293,7 @@
|
|||||||
422724361B6555364C43281E /* RoomHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomHeaderView.swift; sourceTree = "<group>"; };
|
422724361B6555364C43281E /* RoomHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomHeaderView.swift; sourceTree = "<group>"; };
|
||||||
42ADEA322D2089391E049535 /* InvitesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreen.swift; sourceTree = "<group>"; };
|
42ADEA322D2089391E049535 /* InvitesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreen.swift; sourceTree = "<group>"; };
|
||||||
42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenModels.swift; sourceTree = "<group>"; };
|
42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenModels.swift; sourceTree = "<group>"; };
|
||||||
|
42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreen.swift; sourceTree = "<group>"; };
|
||||||
42EEA67A6796BDC2761619C5 /* PaginationIndicatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIndicatorRoomTimelineView.swift; sourceTree = "<group>"; };
|
42EEA67A6796BDC2761619C5 /* PaginationIndicatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationIndicatorRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
43A84EE187D0C772E18A4E39 /* VoiceMessageCacheProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCacheProtocol.swift; sourceTree = "<group>"; };
|
43A84EE187D0C772E18A4E39 /* VoiceMessageCacheProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCacheProtocol.swift; sourceTree = "<group>"; };
|
||||||
4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareToMapsAppActivity.swift; sourceTree = "<group>"; };
|
4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareToMapsAppActivity.swift; sourceTree = "<group>"; };
|
||||||
@@ -1330,6 +1344,7 @@
|
|||||||
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
|
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItem.swift; sourceTree = "<group>"; };
|
5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixUserShareLink.swift; sourceTree = "<group>"; };
|
50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixUserShareLink.swift; sourceTree = "<group>"; };
|
||||||
|
50F23B21CF15F9F4BAA0788B /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
|
||||||
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
|
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
514923AA9640C34F39E0500A /* GenericCallLinkCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericCallLinkCoordinator.swift; sourceTree = "<group>"; };
|
514923AA9640C34F39E0500A /* GenericCallLinkCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericCallLinkCoordinator.swift; sourceTree = "<group>"; };
|
||||||
51C2BCE0BC1FC69C1B36E688 /* BugReportScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenModels.swift; sourceTree = "<group>"; };
|
51C2BCE0BC1FC69C1B36E688 /* BugReportScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenModels.swift; sourceTree = "<group>"; };
|
||||||
@@ -1405,7 +1420,6 @@
|
|||||||
66901977F6469D03C333DF32 /* RoomNotificationSettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenUITests.swift; sourceTree = "<group>"; };
|
66901977F6469D03C333DF32 /* RoomNotificationSettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessor.swift; sourceTree = "<group>"; };
|
669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessor.swift; sourceTree = "<group>"; };
|
||||||
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
|
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
|
||||||
67779D9A1B797285A09B7720 /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
|
|
||||||
68010886142843705E342645 /* ProgressMaskModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressMaskModifier.swift; sourceTree = "<group>"; };
|
68010886142843705E342645 /* ProgressMaskModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressMaskModifier.swift; sourceTree = "<group>"; };
|
||||||
6861FE915C7B5466E6962BBA /* StartChatScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreen.swift; sourceTree = "<group>"; };
|
6861FE915C7B5466E6962BBA /* StartChatScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreen.swift; sourceTree = "<group>"; };
|
||||||
693E16574C6F7F9FA1015A8C /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = "<group>"; };
|
693E16574C6F7F9FA1015A8C /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = "<group>"; };
|
||||||
@@ -1429,6 +1443,7 @@
|
|||||||
6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleRoomTimelineView.swift; sourceTree = "<group>"; };
|
6E2656184491C505700D2405 /* CollapsibleRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModelTests.swift; sourceTree = "<group>"; };
|
6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
6E5E9C044BEB7C70B1378E91 /* UserSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSession.swift; sourceTree = "<group>"; };
|
6E5E9C044BEB7C70B1378E91 /* UserSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSession.swift; sourceTree = "<group>"; };
|
||||||
|
6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenModels.swift; sourceTree = "<group>"; };
|
||||||
6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableState.swift; sourceTree = "<group>"; };
|
6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableState.swift; sourceTree = "<group>"; };
|
||||||
6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = "<group>"; };
|
6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = "<group>"; };
|
||||||
6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelTests.swift; sourceTree = "<group>"; };
|
6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
@@ -1590,6 +1605,7 @@
|
|||||||
A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; };
|
A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; };
|
||||||
A0A01AECFF54281CF35909A6 /* MessageComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposer.swift; sourceTree = "<group>"; };
|
A0A01AECFF54281CF35909A6 /* MessageComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposer.swift; sourceTree = "<group>"; };
|
||||||
A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerProtocol.swift; sourceTree = "<group>"; };
|
A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenCoordinator.swift; sourceTree = "<group>"; };
|
A16CD2C62CB7DB78A4238485 /* ReportContentScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
A1BF12A5E7C76777C4BF0F2B /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = "<group>"; };
|
A1BF12A5E7C76777C4BF0F2B /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = "<group>"; };
|
||||||
A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationStateMachineTests.swift; sourceTree = "<group>"; };
|
A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationStateMachineTests.swift; sourceTree = "<group>"; };
|
||||||
@@ -1657,6 +1673,7 @@
|
|||||||
B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationDialog.swift; sourceTree = "<group>"; };
|
B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationDialog.swift; sourceTree = "<group>"; };
|
||||||
B3A1398EFF65090FDA1CB639 /* ProcessInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessInfo.swift; sourceTree = "<group>"; };
|
B3A1398EFF65090FDA1CB639 /* ProcessInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessInfo.swift; sourceTree = "<group>"; };
|
||||||
B4005D82E9D27BAF006A8FE1 /* AppLockScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModel.swift; sourceTree = "<group>"; };
|
B4005D82E9D27BAF006A8FE1 /* AppLockScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
B40233F2989AD49906BB310D /* RoomPollsHistoryScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenModels.swift; sourceTree = "<group>"; };
|
B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenModels.swift; sourceTree = "<group>"; };
|
||||||
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>"; };
|
||||||
B48B7AD4908C5C374517B892 /* MapAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = MapAssets.xcassets; sourceTree = "<group>"; };
|
B48B7AD4908C5C374517B892 /* MapAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = MapAssets.xcassets; sourceTree = "<group>"; };
|
||||||
@@ -1778,6 +1795,7 @@
|
|||||||
D0C2D52E36AD614B3C003EF6 /* RoomTimelineItemViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemViewState.swift; sourceTree = "<group>"; };
|
D0C2D52E36AD614B3C003EF6 /* RoomTimelineItemViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemViewState.swift; sourceTree = "<group>"; };
|
||||||
D121B4FCFC38DBCC17BCC6D6 /* ComposerToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbar.swift; sourceTree = "<group>"; };
|
D121B4FCFC38DBCC17BCC6D6 /* ComposerToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbar.swift; sourceTree = "<group>"; };
|
||||||
D1BC84BA0AF11C2128D58ABD /* Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Common.swift; sourceTree = "<group>"; };
|
D1BC84BA0AF11C2128D58ABD /* Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Common.swift; sourceTree = "<group>"; };
|
||||||
|
D1D8479BB704B7EF696F8ABE /* RoomPollsHistoryScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
D263254AFE5B7993FFBBF324 /* NSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NSE.entitlements; sourceTree = "<group>"; };
|
D263254AFE5B7993FFBBF324 /* NSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NSE.entitlements; sourceTree = "<group>"; };
|
||||||
D26813CCE39221FE30BF22CD /* PlatformViewVersionPredicate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformViewVersionPredicate.swift; sourceTree = "<group>"; };
|
D26813CCE39221FE30BF22CD /* PlatformViewVersionPredicate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformViewVersionPredicate.swift; sourceTree = "<group>"; };
|
||||||
D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsFlowCoordinator.swift; sourceTree = "<group>"; };
|
D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsFlowCoordinator.swift; sourceTree = "<group>"; };
|
||||||
@@ -1817,6 +1835,7 @@
|
|||||||
DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreen.swift; sourceTree = "<group>"; };
|
DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreen.swift; sourceTree = "<group>"; };
|
||||||
DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNNotification+Creator.swift"; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
||||||
DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenModels.swift; sourceTree = "<group>"; };
|
DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenModels.swift; sourceTree = "<group>"; };
|
||||||
DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceTests.swift; sourceTree = "<group>"; };
|
DD97F9661ABF08CE002054A2 /* AppLockServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceTests.swift; sourceTree = "<group>"; };
|
||||||
DE846DDA83BFD7EC5C03760B /* ServerConfirmationScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenUITests.swift; sourceTree = "<group>"; };
|
DE846DDA83BFD7EC5C03760B /* ServerConfirmationScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenUITests.swift; sourceTree = "<group>"; };
|
||||||
@@ -1885,6 +1904,7 @@
|
|||||||
F012CB5EE3F2B67359F6CC52 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
F012CB5EE3F2B67359F6CC52 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
||||||
F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelTests.swift; sourceTree = "<group>"; };
|
F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
F0B9F5BC4C80543DE7228B9D /* MapTilerStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyle.swift; sourceTree = "<group>"; };
|
F0B9F5BC4C80543DE7228B9D /* MapTilerStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyle.swift; sourceTree = "<group>"; };
|
||||||
|
F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = "<group>"; };
|
F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = "<group>"; };
|
||||||
F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = "<group>"; };
|
F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = "<group>"; };
|
||||||
F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = "<group>"; };
|
F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
@@ -2115,6 +2135,7 @@
|
|||||||
6709362D60732DED2069AE0F /* MediaPlayer */,
|
6709362D60732DED2069AE0F /* MediaPlayer */,
|
||||||
6DE13A7AE6587B079F4049D7 /* Notification */,
|
6DE13A7AE6587B079F4049D7 /* Notification */,
|
||||||
114DC16B28140F885FD833E2 /* NotificationSettings */,
|
114DC16B28140F885FD833E2 /* NotificationSettings */,
|
||||||
|
599DFFE0805B08454E40D64A /* Polls */,
|
||||||
40E6246F03D1FE377BC5D963 /* Room */,
|
40E6246F03D1FE377BC5D963 /* Room */,
|
||||||
07900E9BFFD109F91B35B4C5 /* RoomMember */,
|
07900E9BFFD109F91B35B4C5 /* RoomMember */,
|
||||||
BDCEF7C3BF6D09F5611CFC8B /* SecureBackup */,
|
BDCEF7C3BF6D09F5611CFC8B /* SecureBackup */,
|
||||||
@@ -2762,6 +2783,15 @@
|
|||||||
path = AppLockSetupBiometricsScreen;
|
path = AppLockSetupBiometricsScreen;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
45778D52AECD4EB99A289214 /* Polls */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
50F23B21CF15F9F4BAA0788B /* PollOptionView.swift */,
|
||||||
|
317F41A4B5C4F457AF710666 /* PollView.swift */,
|
||||||
|
);
|
||||||
|
path = Polls;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4775A7D6FBB210BF21318AD9 /* UserDetailsEditScreen */ = {
|
4775A7D6FBB210BF21318AD9 /* UserDetailsEditScreen */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -2974,6 +3004,15 @@
|
|||||||
path = ReportContentScreen;
|
path = ReportContentScreen;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
599DFFE0805B08454E40D64A /* Polls */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */,
|
||||||
|
259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */,
|
||||||
|
);
|
||||||
|
path = Polls;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
5B2C520AB9863B8CBC8EB3CA /* SoftLogoutScreen */ = {
|
5B2C520AB9863B8CBC8EB3CA /* SoftLogoutScreen */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -3244,6 +3283,7 @@
|
|||||||
EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */,
|
EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */,
|
||||||
69B63F817FE305548DB4B512 /* RoomMembersListViewModelTests.swift */,
|
69B63F817FE305548DB4B512 /* RoomMembersListViewModelTests.swift */,
|
||||||
58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */,
|
58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */,
|
||||||
|
B40233F2989AD49906BB310D /* RoomPollsHistoryScreenViewModelTests.swift */,
|
||||||
93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */,
|
93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */,
|
||||||
AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */,
|
AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */,
|
||||||
2E88534A39781D76487D59DF /* SecureBackupKeyBackupScreenViewModelTests.swift */,
|
2E88534A39781D76487D59DF /* SecureBackupKeyBackupScreenViewModelTests.swift */,
|
||||||
@@ -3387,6 +3427,7 @@
|
|||||||
A1BF12A5E7C76777C4BF0F2B /* TimelineItemMenu.swift */,
|
A1BF12A5E7C76777C4BF0F2B /* TimelineItemMenu.swift */,
|
||||||
0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */,
|
0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */,
|
||||||
874A1842477895F199567BD7 /* TimelineView.swift */,
|
874A1842477895F199567BD7 /* TimelineView.swift */,
|
||||||
|
45778D52AECD4EB99A289214 /* Polls */,
|
||||||
4820FFB9F4FDDFD95763D498 /* ReadReceipts */,
|
4820FFB9F4FDDFD95763D498 /* ReadReceipts */,
|
||||||
1D8572B713A11CFDBF009B2F /* Replies */,
|
1D8572B713A11CFDBF009B2F /* Replies */,
|
||||||
A312471EA62EFB0FD94E60DC /* Style */,
|
A312471EA62EFB0FD94E60DC /* Style */,
|
||||||
@@ -3713,6 +3754,7 @@
|
|||||||
0F19DBE940499D3E3DD405D8 /* RoomMemberDetailsScreenUITests.swift */,
|
0F19DBE940499D3E3DD405D8 /* RoomMemberDetailsScreenUITests.swift */,
|
||||||
C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */,
|
C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */,
|
||||||
66901977F6469D03C333DF32 /* RoomNotificationSettingsScreenUITests.swift */,
|
66901977F6469D03C333DF32 /* RoomNotificationSettingsScreenUITests.swift */,
|
||||||
|
0D147EB979902DBBE452EADC /* RoomPollsHistoryScreenUITests.swift */,
|
||||||
086B997409328F091EBA43CE /* RoomScreenUITests.swift */,
|
086B997409328F091EBA43CE /* RoomScreenUITests.swift */,
|
||||||
58DCB219D7B7B0299358FF81 /* SecureBackupKeyBackupScreenUITests.swift */,
|
58DCB219D7B7B0299358FF81 /* SecureBackupKeyBackupScreenUITests.swift */,
|
||||||
1CC09F30B0E1010951952BDC /* SecureBackupLogoutConfirmationScreenUITests.swift */,
|
1CC09F30B0E1010951952BDC /* SecureBackupLogoutConfirmationScreenUITests.swift */,
|
||||||
@@ -4089,7 +4131,6 @@
|
|||||||
772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */,
|
772334731A8BF8E6D90B194D /* LocationRoomTimelineView.swift */,
|
||||||
B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */,
|
B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */,
|
||||||
42EEA67A6796BDC2761619C5 /* PaginationIndicatorRoomTimelineView.swift */,
|
42EEA67A6796BDC2761619C5 /* PaginationIndicatorRoomTimelineView.swift */,
|
||||||
67779D9A1B797285A09B7720 /* PollOptionView.swift */,
|
|
||||||
C936FDD017808FE416742D64 /* PollRoomTimelineView.swift */,
|
C936FDD017808FE416742D64 /* PollRoomTimelineView.swift */,
|
||||||
B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */,
|
B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */,
|
||||||
C8F2A7A4E3F5060F52ACFFB0 /* RedactedRoomTimelineView.swift */,
|
C8F2A7A4E3F5060F52ACFFB0 /* RedactedRoomTimelineView.swift */,
|
||||||
@@ -4306,6 +4347,14 @@
|
|||||||
path = Layout;
|
path = Layout;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D4B487C81A239A9C71807601 /* View */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */,
|
||||||
|
);
|
||||||
|
path = View;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D4DB8163C10389C069458252 /* RoomMemberListScreen */ = {
|
D4DB8163C10389C069458252 /* RoomMemberListScreen */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -4326,6 +4375,18 @@
|
|||||||
path = View;
|
path = View;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D57B3BC211BB74420C9138D7 /* RoomPollsHistoryScreen */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D1D8479BB704B7EF696F8ABE /* RoomPollsHistoryScreenCoordinator.swift */,
|
||||||
|
6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */,
|
||||||
|
F0E14FF533D25A0692F7CEB0 /* RoomPollsHistoryScreenViewModel.swift */,
|
||||||
|
A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */,
|
||||||
|
D4B487C81A239A9C71807601 /* View */,
|
||||||
|
);
|
||||||
|
path = RoomPollsHistoryScreen;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D977D4E565C06D3F41C8F8FC /* Virtual */ = {
|
D977D4E565C06D3F41C8F8FC /* Virtual */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -4425,6 +4486,7 @@
|
|||||||
B86CF59E083C82C2A842E4AD /* RoomMemberDetailsScreen */,
|
B86CF59E083C82C2A842E4AD /* RoomMemberDetailsScreen */,
|
||||||
D4DB8163C10389C069458252 /* RoomMemberListScreen */,
|
D4DB8163C10389C069458252 /* RoomMemberListScreen */,
|
||||||
0210F4932B59277E2EEEF7BC /* RoomNotificationSettingsScreen */,
|
0210F4932B59277E2EEEF7BC /* RoomNotificationSettingsScreen */,
|
||||||
|
D57B3BC211BB74420C9138D7 /* RoomPollsHistoryScreen */,
|
||||||
679E9837ECA8D6776079D16E /* RoomScreen */,
|
679E9837ECA8D6776079D16E /* RoomScreen */,
|
||||||
2565414373E6F68005966B8E /* SecureBackup */,
|
2565414373E6F68005966B8E /* SecureBackup */,
|
||||||
3153FCA3F4B0E88B16D99D12 /* SessionVerificationScreen */,
|
3153FCA3F4B0E88B16D99D12 /* SessionVerificationScreen */,
|
||||||
@@ -5189,6 +5251,7 @@
|
|||||||
6B31508C6334C617360C2EAB /* RoomMemberDetailsViewModelTests.swift in Sources */,
|
6B31508C6334C617360C2EAB /* RoomMemberDetailsViewModelTests.swift in Sources */,
|
||||||
CAF8755E152204F55F8D6B5B /* RoomMembersListViewModelTests.swift in Sources */,
|
CAF8755E152204F55F8D6B5B /* RoomMembersListViewModelTests.swift in Sources */,
|
||||||
E49F74BD93230BDEFFE5EA51 /* RoomNotificationSettingsScreenViewModelTests.swift in Sources */,
|
E49F74BD93230BDEFFE5EA51 /* RoomNotificationSettingsScreenViewModelTests.swift in Sources */,
|
||||||
|
7B1605C6FFD4D195F264A684 /* RoomPollsHistoryScreenViewModelTests.swift in Sources */,
|
||||||
46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */,
|
46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */,
|
||||||
CC0D088F505F33A20DC5590F /* RoomStateEventStringBuilderTests.swift in Sources */,
|
CC0D088F505F33A20DC5590F /* RoomStateEventStringBuilderTests.swift in Sources */,
|
||||||
7691233E3572A9173FD96CB3 /* SecureBackupKeyBackupScreenViewModelTests.swift in Sources */,
|
7691233E3572A9173FD96CB3 /* SecureBackupKeyBackupScreenViewModelTests.swift in Sources */,
|
||||||
@@ -5602,10 +5665,13 @@
|
|||||||
70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */,
|
70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */,
|
||||||
F9EA79092C18A8CFE4922DD2 /* PollFormScreenViewModel.swift in Sources */,
|
F9EA79092C18A8CFE4922DD2 /* PollFormScreenViewModel.swift in Sources */,
|
||||||
260FFC1475EE94F641C3F3F9 /* PollFormScreenViewModelProtocol.swift in Sources */,
|
260FFC1475EE94F641C3F3F9 /* PollFormScreenViewModelProtocol.swift in Sources */,
|
||||||
|
151D2477F75782C8702F2873 /* PollInteractionHandler.swift in Sources */,
|
||||||
|
915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */,
|
||||||
16CBD087038DE3815CDA512C /* PollMock.swift in Sources */,
|
16CBD087038DE3815CDA512C /* PollMock.swift in Sources */,
|
||||||
6B4BF4A6450F55939B49FAEF /* PollOptionView.swift in Sources */,
|
F50A6FCE26714E27FE5495DD /* PollOptionView.swift in Sources */,
|
||||||
864C0D3A4077BF433DBC691F /* PollRoomTimelineItem.swift in Sources */,
|
864C0D3A4077BF433DBC691F /* PollRoomTimelineItem.swift in Sources */,
|
||||||
153E22E8227F46545E5D681C /* PollRoomTimelineView.swift in Sources */,
|
153E22E8227F46545E5D681C /* PollRoomTimelineView.swift in Sources */,
|
||||||
|
1EC6D1B58B24369734CD62BA /* PollView.swift in Sources */,
|
||||||
DF504B10A4918F971A57BEF2 /* PostHogAnalyticsClient.swift in Sources */,
|
DF504B10A4918F971A57BEF2 /* PostHogAnalyticsClient.swift in Sources */,
|
||||||
FD4DEC88210F35C35B2FB386 /* ProcessInfo.swift in Sources */,
|
FD4DEC88210F35C35B2FB386 /* ProcessInfo.swift in Sources */,
|
||||||
69DE29C3E3180BB17D840690 /* ProgressCursorModifier.swift in Sources */,
|
69DE29C3E3180BB17D840690 /* ProgressCursorModifier.swift in Sources */,
|
||||||
@@ -5668,6 +5734,11 @@
|
|||||||
E9347F56CF0683208F4D9249 /* RoomNotificationSettingsScreenViewModel.swift in Sources */,
|
E9347F56CF0683208F4D9249 /* RoomNotificationSettingsScreenViewModel.swift in Sources */,
|
||||||
BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */,
|
BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */,
|
||||||
491D62ACD19E6F134B1766AF /* RoomNotificationSettingsUserDefinedScreen.swift in Sources */,
|
491D62ACD19E6F134B1766AF /* RoomNotificationSettingsUserDefinedScreen.swift in Sources */,
|
||||||
|
7A02EB29F3B993AB20E0A198 /* RoomPollsHistoryScreen.swift in Sources */,
|
||||||
|
E58F1F3276E98A93F7D39219 /* RoomPollsHistoryScreenCoordinator.swift in Sources */,
|
||||||
|
51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */,
|
||||||
|
79741C1953269FF1A211D246 /* RoomPollsHistoryScreenViewModel.swift in Sources */,
|
||||||
|
F103924DED414ADFE398CE99 /* RoomPollsHistoryScreenViewModelProtocol.swift in Sources */,
|
||||||
4FC1EFE4968A259CBBACFAFB /* RoomProxy.swift in Sources */,
|
4FC1EFE4968A259CBBACFAFB /* RoomProxy.swift in Sources */,
|
||||||
BD203FC6A7AE7637EA003643 /* RoomProxyMock.swift in Sources */,
|
BD203FC6A7AE7637EA003643 /* RoomProxyMock.swift in Sources */,
|
||||||
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */,
|
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */,
|
||||||
@@ -5937,6 +6008,7 @@
|
|||||||
A8771F5975A82759FA5138AE /* RoomMemberDetailsScreenUITests.swift in Sources */,
|
A8771F5975A82759FA5138AE /* RoomMemberDetailsScreenUITests.swift in Sources */,
|
||||||
44121202B4A260C98BF615A7 /* RoomMembersListScreenUITests.swift in Sources */,
|
44121202B4A260C98BF615A7 /* RoomMembersListScreenUITests.swift in Sources */,
|
||||||
06AA515C7053FD7E17A5CF81 /* RoomNotificationSettingsScreenUITests.swift in Sources */,
|
06AA515C7053FD7E17A5CF81 /* RoomNotificationSettingsScreenUITests.swift in Sources */,
|
||||||
|
835B7AD20407F766C747BEC5 /* RoomPollsHistoryScreenUITests.swift in Sources */,
|
||||||
2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */,
|
2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */,
|
||||||
A743841F91B62B0E56217B04 /* SecureBackupKeyBackupScreenUITests.swift in Sources */,
|
A743841F91B62B0E56217B04 /* SecureBackupKeyBackupScreenUITests.swift in Sources */,
|
||||||
F421FD5979EF53C8204BDC77 /* SecureBackupLogoutConfirmationScreenUITests.swift in Sources */,
|
F421FD5979EF53C8204BDC77 /* SecureBackupLogoutConfirmationScreenUITests.swift in Sources */,
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
"action_try_again" = "Try again";
|
"action_try_again" = "Try again";
|
||||||
"action_view_source" = "View source";
|
"action_view_source" = "View source";
|
||||||
"action_yes" = "Yes";
|
"action_yes" = "Yes";
|
||||||
|
"action.load_more" = "Load more";
|
||||||
"common_about" = "About";
|
"common_about" = "About";
|
||||||
"common_acceptable_use_policy" = "Acceptable use policy";
|
"common_acceptable_use_policy" = "Acceptable use policy";
|
||||||
"common_advanced_settings" = "Advanced settings";
|
"common_advanced_settings" = "Advanced settings";
|
||||||
@@ -444,6 +445,11 @@
|
|||||||
"screen_onboarding_welcome_message" = "Welcome to the fastest Element ever. Supercharged for speed and simplicity.";
|
"screen_onboarding_welcome_message" = "Welcome to the fastest Element ever. Supercharged for speed and simplicity.";
|
||||||
"screen_onboarding_welcome_subtitle" = "Welcome to %1$@. Supercharged, for speed and simplicity.";
|
"screen_onboarding_welcome_subtitle" = "Welcome to %1$@. Supercharged, for speed and simplicity.";
|
||||||
"screen_onboarding_welcome_title" = "Be in your element";
|
"screen_onboarding_welcome_title" = "Be in your element";
|
||||||
|
"screen_polls_history_empty_ongoing" = "Can't find any ongoing polls.";
|
||||||
|
"screen_polls_history_empty_past" = "Can't find any past polls.";
|
||||||
|
"screen_polls_history_filter_ongoing" = "Ongoing";
|
||||||
|
"screen_polls_history_filter_past" = "Past";
|
||||||
|
"screen_polls_history_title" = "Polls";
|
||||||
"screen_recovery_key_change_description" = "Get a new recovery key if you've lost your existing one. After changing your recovery key, your old one will no longer work.";
|
"screen_recovery_key_change_description" = "Get a new recovery key if you've lost your existing one. After changing your recovery key, your old one will no longer work.";
|
||||||
"screen_recovery_key_change_generate_key" = "Generate a new recovery key";
|
"screen_recovery_key_change_generate_key" = "Generate a new recovery key";
|
||||||
"screen_recovery_key_change_generate_key_description" = "Make sure you can store your recovery key somewhere safe";
|
"screen_recovery_key_change_generate_key_description" = "Make sure you can store your recovery key somewhere safe";
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ final class AppSettings {
|
|||||||
|
|
||||||
@UserPreference(key: UserDefaultsKeys.chatBackupEnabled, defaultValue: false, storageType: .userDefaults(store))
|
@UserPreference(key: UserDefaultsKeys.chatBackupEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||||
var chatBackupEnabled
|
var chatBackupEnabled
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// MARK: - Shared
|
// MARK: - Shared
|
||||||
|
|||||||
@@ -206,12 +206,22 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
return .mapNavigator(roomID: roomID)
|
return .mapNavigator(roomID: roomID)
|
||||||
case (.mapNavigator(let roomID), .dismissMapNavigator):
|
case (.mapNavigator(let roomID), .dismissMapNavigator):
|
||||||
return .room(roomID: roomID)
|
return .room(roomID: roomID)
|
||||||
|
|
||||||
case (.room(let roomID), .presentPollForm):
|
case (.room(let roomID), .presentPollForm):
|
||||||
return .pollForm(roomID: roomID)
|
return .pollForm(roomID: roomID)
|
||||||
case (.pollForm(let roomID), .dismissPollForm):
|
case (.pollForm(let roomID), .dismissPollForm):
|
||||||
return .room(roomID: roomID)
|
return .room(roomID: roomID)
|
||||||
|
|
||||||
|
case (.roomDetails(let roomID, _), .presentPollsHistory):
|
||||||
|
return .pollsHistory(roomID: roomID)
|
||||||
|
case (.pollsHistory(let roomID), .dismissPollsHistory):
|
||||||
|
return .roomDetails(roomID: roomID, isRoot: false)
|
||||||
|
|
||||||
|
case (.pollsHistory(let roomID), .presentPollForm):
|
||||||
|
return .pollsHistoryForm(roomID: roomID)
|
||||||
|
case (.pollsHistoryForm(let roomID), .dismissPollForm):
|
||||||
|
return .pollsHistory(roomID: roomID)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -320,6 +330,16 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case (.pollForm, .dismissPollForm, .room):
|
case (.pollForm, .dismissPollForm, .room):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case (.roomDetails(let roomID, _), .presentPollsHistory, .pollsHistory):
|
||||||
|
presentPollsHistory(roomID: roomID)
|
||||||
|
case (.pollsHistory, .dismissPollsHistory, .roomDetails):
|
||||||
|
break
|
||||||
|
|
||||||
|
case (.pollsHistory, .presentPollForm(let mode), .pollsHistoryForm):
|
||||||
|
presentPollForm(mode: mode)
|
||||||
|
case (.pollsHistoryForm, .dismissPollForm, .pollsHistory):
|
||||||
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatalError("Unknown transition: \(context)")
|
fatalError("Unknown transition: \(context)")
|
||||||
}
|
}
|
||||||
@@ -516,6 +536,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
stateMachine.tryEvent(.presentNotificationSettingsScreen)
|
stateMachine.tryEvent(.presentNotificationSettingsScreen)
|
||||||
case .presentInviteUsersScreen:
|
case .presentInviteUsersScreen:
|
||||||
stateMachine.tryEvent(.presentInviteUsersScreen)
|
stateMachine.tryEvent(.presentInviteUsersScreen)
|
||||||
|
case .presentPollsHistory:
|
||||||
|
stateMachine.tryEvent(.presentPollsHistory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
@@ -845,6 +867,58 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func presentPollsHistory(roomID: String) {
|
||||||
|
Task {
|
||||||
|
await asyncPresentRoomPollsHistory(roomID: roomID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func asyncPresentRoomPollsHistory(roomID: String) async {
|
||||||
|
let roomProxy: RoomProxyProtocol
|
||||||
|
|
||||||
|
guard let proxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||||
|
MXLog.error("Invalid room identifier: \(roomID)")
|
||||||
|
stateMachine.tryEvent(.dismissPollsHistory)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
roomProxy = proxy
|
||||||
|
|
||||||
|
await roomProxy.subscribeForUpdates()
|
||||||
|
|
||||||
|
let userID = userSession.clientProxy.userID
|
||||||
|
|
||||||
|
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
||||||
|
mediaProvider: userSession.mediaProvider,
|
||||||
|
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: appSettings.permalinkBaseURL,
|
||||||
|
mentionBuilder: MentionBuilder()),
|
||||||
|
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID),
|
||||||
|
appSettings: appSettings)
|
||||||
|
|
||||||
|
let roomTimelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy,
|
||||||
|
timelineItemFactory: timelineItemFactory,
|
||||||
|
secureBackupController: userSession.clientProxy.secureBackupController)
|
||||||
|
|
||||||
|
let parameters = RoomPollsHistoryScreenCoordinatorParameters(roomProxy: roomProxy,
|
||||||
|
pollInteractionHandler: PollInteractionHandler(analyticsService: analytics, roomProxy: roomProxy),
|
||||||
|
roomTimelineController: roomTimelineController)
|
||||||
|
let coordinator = RoomPollsHistoryScreenCoordinator(parameters: parameters)
|
||||||
|
coordinator.actions
|
||||||
|
.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case .editPoll(let pollStartID, let poll):
|
||||||
|
stateMachine.tryEvent(.presentPollForm(mode: .edit(eventID: pollStartID, poll: poll)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
navigationStackCoordinator.push(coordinator) { [weak self] in
|
||||||
|
self?.stateMachine.tryEvent(.dismissPollsHistory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func presentRoomMemberDetails(member: RoomMemberProxyProtocol) {
|
private func presentRoomMemberDetails(member: RoomMemberProxyProtocol) {
|
||||||
guard let roomProxy else {
|
guard let roomProxy else {
|
||||||
fatalError()
|
fatalError()
|
||||||
@@ -1106,6 +1180,8 @@ private extension RoomFlowCoordinator {
|
|||||||
case messageForwarding(roomID: String, itemID: TimelineItemIdentifier)
|
case messageForwarding(roomID: String, itemID: TimelineItemIdentifier)
|
||||||
case reportContent(roomID: String, itemID: TimelineItemIdentifier, senderID: String)
|
case reportContent(roomID: String, itemID: TimelineItemIdentifier, senderID: String)
|
||||||
case pollForm(roomID: String)
|
case pollForm(roomID: String)
|
||||||
|
case pollsHistory(roomID: String)
|
||||||
|
case pollsHistoryForm(roomID: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EventUserInfo {
|
struct EventUserInfo {
|
||||||
@@ -1158,6 +1234,9 @@ private extension RoomFlowCoordinator {
|
|||||||
|
|
||||||
case presentPollForm(mode: PollFormMode)
|
case presentPollForm(mode: PollFormMode)
|
||||||
case dismissPollForm
|
case dismissPollForm
|
||||||
|
|
||||||
|
case presentPollsHistory
|
||||||
|
case dismissPollsHistory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1084,6 +1084,16 @@ public enum L10n {
|
|||||||
}
|
}
|
||||||
/// Be in your element
|
/// Be in your element
|
||||||
public static var screenOnboardingWelcomeTitle: String { return L10n.tr("Localizable", "screen_onboarding_welcome_title") }
|
public static var screenOnboardingWelcomeTitle: String { return L10n.tr("Localizable", "screen_onboarding_welcome_title") }
|
||||||
|
/// Can't find any ongoing polls.
|
||||||
|
public static var screenPollsHistoryEmptyOngoing: String { return L10n.tr("Localizable", "screen_polls_history_empty_ongoing") }
|
||||||
|
/// Can't find any past polls.
|
||||||
|
public static var screenPollsHistoryEmptyPast: String { return L10n.tr("Localizable", "screen_polls_history_empty_past") }
|
||||||
|
/// Ongoing
|
||||||
|
public static var screenPollsHistoryFilterOngoing: String { return L10n.tr("Localizable", "screen_polls_history_filter_ongoing") }
|
||||||
|
/// Past
|
||||||
|
public static var screenPollsHistoryFilterPast: String { return L10n.tr("Localizable", "screen_polls_history_filter_past") }
|
||||||
|
/// Polls
|
||||||
|
public static var screenPollsHistoryTitle: String { return L10n.tr("Localizable", "screen_polls_history_title") }
|
||||||
/// Get a new recovery key if you've lost your existing one. After changing your recovery key, your old one will no longer work.
|
/// Get a new recovery key if you've lost your existing one. After changing your recovery key, your old one will no longer work.
|
||||||
public static var screenRecoveryKeyChangeDescription: String { return L10n.tr("Localizable", "screen_recovery_key_change_description") }
|
public static var screenRecoveryKeyChangeDescription: String { return L10n.tr("Localizable", "screen_recovery_key_change_description") }
|
||||||
/// Generate a new recovery key
|
/// Generate a new recovery key
|
||||||
@@ -1626,6 +1636,11 @@ public enum L10n {
|
|||||||
public static var testLanguageIdentifier: String { return L10n.tr("Localizable", "test_language_identifier") }
|
public static var testLanguageIdentifier: String { return L10n.tr("Localizable", "test_language_identifier") }
|
||||||
/// en
|
/// en
|
||||||
public static var testUntranslatedDefaultLanguageIdentifier: String { return L10n.tr("Localizable", "test_untranslated_default_language_identifier") }
|
public static var testUntranslatedDefaultLanguageIdentifier: String { return L10n.tr("Localizable", "test_untranslated_default_language_identifier") }
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
|
/// Load more
|
||||||
|
public static var loadMore: String { return L10n.tr("Localizable", "action.load_more") }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
|
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
|
||||||
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
|
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||||
|
|||||||
@@ -1632,6 +1632,51 @@ class NotificationSettingsProxyMock: NotificationSettingsProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class PollInteractionHandlerMock: PollInteractionHandlerProtocol {
|
||||||
|
|
||||||
|
//MARK: - sendPollResponse
|
||||||
|
|
||||||
|
var sendPollResponsePollStartIDOptionIDCallsCount = 0
|
||||||
|
var sendPollResponsePollStartIDOptionIDCalled: Bool {
|
||||||
|
return sendPollResponsePollStartIDOptionIDCallsCount > 0
|
||||||
|
}
|
||||||
|
var sendPollResponsePollStartIDOptionIDReceivedArguments: (pollStartID: String, optionID: String)?
|
||||||
|
var sendPollResponsePollStartIDOptionIDReceivedInvocations: [(pollStartID: String, optionID: String)] = []
|
||||||
|
var sendPollResponsePollStartIDOptionIDReturnValue: Result<Void, Error>!
|
||||||
|
var sendPollResponsePollStartIDOptionIDClosure: ((String, String) async -> Result<Void, Error>)?
|
||||||
|
|
||||||
|
func sendPollResponse(pollStartID: String, optionID: String) async -> Result<Void, Error> {
|
||||||
|
sendPollResponsePollStartIDOptionIDCallsCount += 1
|
||||||
|
sendPollResponsePollStartIDOptionIDReceivedArguments = (pollStartID: pollStartID, optionID: optionID)
|
||||||
|
sendPollResponsePollStartIDOptionIDReceivedInvocations.append((pollStartID: pollStartID, optionID: optionID))
|
||||||
|
if let sendPollResponsePollStartIDOptionIDClosure = sendPollResponsePollStartIDOptionIDClosure {
|
||||||
|
return await sendPollResponsePollStartIDOptionIDClosure(pollStartID, optionID)
|
||||||
|
} else {
|
||||||
|
return sendPollResponsePollStartIDOptionIDReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - endPoll
|
||||||
|
|
||||||
|
var endPollPollStartIDCallsCount = 0
|
||||||
|
var endPollPollStartIDCalled: Bool {
|
||||||
|
return endPollPollStartIDCallsCount > 0
|
||||||
|
}
|
||||||
|
var endPollPollStartIDReceivedPollStartID: String?
|
||||||
|
var endPollPollStartIDReceivedInvocations: [String] = []
|
||||||
|
var endPollPollStartIDReturnValue: Result<Void, Error>!
|
||||||
|
var endPollPollStartIDClosure: ((String) async -> Result<Void, Error>)?
|
||||||
|
|
||||||
|
func endPoll(pollStartID: String) async -> Result<Void, Error> {
|
||||||
|
endPollPollStartIDCallsCount += 1
|
||||||
|
endPollPollStartIDReceivedPollStartID = pollStartID
|
||||||
|
endPollPollStartIDReceivedInvocations.append(pollStartID)
|
||||||
|
if let endPollPollStartIDClosure = endPollPollStartIDClosure {
|
||||||
|
return await endPollPollStartIDClosure(pollStartID)
|
||||||
|
} else {
|
||||||
|
return endPollPollStartIDReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
class RoomMemberProxyMock: RoomMemberProxyProtocol {
|
class RoomMemberProxyMock: RoomMemberProxyProtocol {
|
||||||
var userID: String {
|
var userID: String {
|
||||||
get { return underlyingUserID }
|
get { return underlyingUserID }
|
||||||
@@ -2402,6 +2447,11 @@ class TimelineProxyMock: TimelineProxyProtocol {
|
|||||||
set(value) { underlyingTimelineProvider = value }
|
set(value) { underlyingTimelineProvider = value }
|
||||||
}
|
}
|
||||||
var underlyingTimelineProvider: RoomTimelineProviderProtocol!
|
var underlyingTimelineProvider: RoomTimelineProviderProtocol!
|
||||||
|
var timelineStartReached: Bool {
|
||||||
|
get { return underlyingTimelineStartReached }
|
||||||
|
set(value) { underlyingTimelineStartReached = value }
|
||||||
|
}
|
||||||
|
var underlyingTimelineStartReached: Bool!
|
||||||
|
|
||||||
//MARK: - subscribeForUpdates
|
//MARK: - subscribeForUpdates
|
||||||
|
|
||||||
@@ -2523,6 +2573,27 @@ class TimelineProxyMock: TimelineProxyProtocol {
|
|||||||
}
|
}
|
||||||
//MARK: - paginateBackwards
|
//MARK: - paginateBackwards
|
||||||
|
|
||||||
|
var paginateBackwardsRequestSizeCallsCount = 0
|
||||||
|
var paginateBackwardsRequestSizeCalled: Bool {
|
||||||
|
return paginateBackwardsRequestSizeCallsCount > 0
|
||||||
|
}
|
||||||
|
var paginateBackwardsRequestSizeReceivedRequestSize: UInt?
|
||||||
|
var paginateBackwardsRequestSizeReceivedInvocations: [UInt] = []
|
||||||
|
var paginateBackwardsRequestSizeReturnValue: Result<Void, TimelineProxyError>!
|
||||||
|
var paginateBackwardsRequestSizeClosure: ((UInt) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
|
func paginateBackwards(requestSize: UInt) async -> Result<Void, TimelineProxyError> {
|
||||||
|
paginateBackwardsRequestSizeCallsCount += 1
|
||||||
|
paginateBackwardsRequestSizeReceivedRequestSize = requestSize
|
||||||
|
paginateBackwardsRequestSizeReceivedInvocations.append(requestSize)
|
||||||
|
if let paginateBackwardsRequestSizeClosure = paginateBackwardsRequestSizeClosure {
|
||||||
|
return await paginateBackwardsRequestSizeClosure(requestSize)
|
||||||
|
} else {
|
||||||
|
return paginateBackwardsRequestSizeReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - paginateBackwards
|
||||||
|
|
||||||
var paginateBackwardsRequestSizeUntilNumberOfItemsCallsCount = 0
|
var paginateBackwardsRequestSizeUntilNumberOfItemsCallsCount = 0
|
||||||
var paginateBackwardsRequestSizeUntilNumberOfItemsCalled: Bool {
|
var paginateBackwardsRequestSizeUntilNumberOfItemsCalled: Bool {
|
||||||
return paginateBackwardsRequestSizeUntilNumberOfItemsCallsCount > 0
|
return paginateBackwardsRequestSizeUntilNumberOfItemsCallsCount > 0
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ struct RoomProxyMockConfiguration {
|
|||||||
var timeline = {
|
var timeline = {
|
||||||
let mock = TimelineProxyMock()
|
let mock = TimelineProxyMock()
|
||||||
mock.underlyingActions = Empty(completeImmediately: false).eraseToAnyPublisher()
|
mock.underlyingActions = Empty(completeImmediately: false).eraseToAnyPublisher()
|
||||||
|
mock.timelineStartReached = false
|
||||||
return mock
|
return mock
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ enum A11yIdentifiers {
|
|||||||
static let notificationSettingsScreen = NotificationSettingsScreen()
|
static let notificationSettingsScreen = NotificationSettingsScreen()
|
||||||
static let notificationSettingsEditScreen = NotificationSettingsEditScreen()
|
static let notificationSettingsEditScreen = NotificationSettingsEditScreen()
|
||||||
static let pollFormScreen = PollFormScreen()
|
static let pollFormScreen = PollFormScreen()
|
||||||
|
static let roomPollsHistoryScreen = RoomPollsHistoryScreen()
|
||||||
|
|
||||||
struct AlertInfo {
|
struct AlertInfo {
|
||||||
let primaryButton = "alert_info-primary_button"
|
let primaryButton = "alert_info-primary_button"
|
||||||
@@ -169,6 +170,7 @@ enum A11yIdentifiers {
|
|||||||
let people = "room_details-people"
|
let people = "room_details-people"
|
||||||
let invite = "room_details-invite"
|
let invite = "room_details-invite"
|
||||||
let notifications = "room_details-notifications"
|
let notifications = "room_details-notifications"
|
||||||
|
let pollsHistory = "romm_details-polls_history"
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RoomMemberDetailsScreen {
|
struct RoomMemberDetailsScreen {
|
||||||
@@ -263,4 +265,8 @@ enum A11yIdentifiers {
|
|||||||
"\(roomNamePrefix):\(name)"
|
"\(roomNamePrefix):\(name)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RoomPollsHistoryScreen {
|
||||||
|
let loadMore = "room_polls_history_screen-load_more"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ enum RoomDetailsScreenCoordinatorAction {
|
|||||||
case presentRoomDetailsEditScreen(accountOwner: RoomMemberProxyProtocol)
|
case presentRoomDetailsEditScreen(accountOwner: RoomMemberProxyProtocol)
|
||||||
case presentNotificationSettingsScreen
|
case presentNotificationSettingsScreen
|
||||||
case presentInviteUsersScreen
|
case presentInviteUsersScreen
|
||||||
|
case presentPollsHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
|
final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
|
||||||
@@ -71,6 +72,8 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
|
|||||||
actionsSubject.send(.presentRoomDetailsEditScreen(accountOwner: accountOwner))
|
actionsSubject.send(.presentRoomDetailsEditScreen(accountOwner: accountOwner))
|
||||||
case .requestNotificationSettingsPresentation:
|
case .requestNotificationSettingsPresentation:
|
||||||
actionsSubject.send(.presentNotificationSettingsScreen)
|
actionsSubject.send(.presentNotificationSettingsScreen)
|
||||||
|
case .requestPollsHistoryPresentation:
|
||||||
|
actionsSubject.send(.presentPollsHistory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ enum RoomDetailsScreenViewModelAction {
|
|||||||
case requestInvitePeoplePresentation
|
case requestInvitePeoplePresentation
|
||||||
case leftRoom
|
case leftRoom
|
||||||
case requestEditDetailsPresentation(RoomMemberProxyProtocol)
|
case requestEditDetailsPresentation(RoomMemberProxyProtocol)
|
||||||
|
case requestPollsHistoryPresentation
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: View
|
// MARK: View
|
||||||
@@ -174,6 +175,7 @@ enum RoomDetailsScreenViewAction {
|
|||||||
case processTapNotifications
|
case processTapNotifications
|
||||||
case processToogleMuteNotifications
|
case processToogleMuteNotifications
|
||||||
case displayAvatar
|
case displayAvatar
|
||||||
|
case processTapPolls
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RoomDetailsScreenViewShortcut {
|
enum RoomDetailsScreenViewShortcut {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
notificationSettingsState: .loading,
|
notificationSettingsState: .loading,
|
||||||
bindings: .init()),
|
bindings: .init()),
|
||||||
imageProvider: mediaProvider)
|
imageProvider: mediaProvider)
|
||||||
|
|
||||||
setupRoomSubscription()
|
setupRoomSubscription()
|
||||||
fetchMembers()
|
fetchMembers()
|
||||||
|
|
||||||
@@ -120,6 +120,8 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
Task { await toggleMuteNotifications() }
|
Task { await toggleMuteNotifications() }
|
||||||
case .displayAvatar:
|
case .displayAvatar:
|
||||||
displayFullScreenAvatar()
|
displayFullScreenAvatar()
|
||||||
|
case .processTapPolls:
|
||||||
|
actionsSubject.send(.requestPollsHistoryPresentation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,7 @@ struct RoomDetailsScreen: View {
|
|||||||
|
|
||||||
notificationSection
|
notificationSection
|
||||||
|
|
||||||
if context.viewState.dmRecipient == nil {
|
aboutSection
|
||||||
aboutSection
|
|
||||||
}
|
|
||||||
|
|
||||||
securitySection
|
securitySection
|
||||||
|
|
||||||
@@ -150,22 +148,30 @@ struct RoomDetailsScreen: View {
|
|||||||
|
|
||||||
private var aboutSection: some View {
|
private var aboutSection: some View {
|
||||||
Section {
|
Section {
|
||||||
ListRow(label: .default(title: L10n.commonPeople,
|
if context.viewState.dmRecipient == nil {
|
||||||
icon: CompoundIcon(asset: Asset.Images.user)),
|
ListRow(label: .default(title: L10n.commonPeople,
|
||||||
details: .title(String(context.viewState.joinedMembersCount)),
|
icon: CompoundIcon(asset: Asset.Images.user)),
|
||||||
kind: .navigationLink {
|
details: .title(String(context.viewState.joinedMembersCount)),
|
||||||
context.send(viewAction: .processTapPeople)
|
|
||||||
})
|
|
||||||
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.people)
|
|
||||||
|
|
||||||
if context.viewState.canInviteUsers {
|
|
||||||
ListRow(label: .default(title: L10n.screenRoomDetailsInvitePeopleTitle,
|
|
||||||
icon: CompoundIcon(asset: Asset.Images.userAdd)),
|
|
||||||
kind: .navigationLink {
|
kind: .navigationLink {
|
||||||
context.send(viewAction: .processTapInvite)
|
context.send(viewAction: .processTapPeople)
|
||||||
})
|
})
|
||||||
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.invite)
|
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.people)
|
||||||
|
|
||||||
|
if context.viewState.canInviteUsers {
|
||||||
|
ListRow(label: .default(title: L10n.screenRoomDetailsInvitePeopleTitle,
|
||||||
|
icon: CompoundIcon(asset: Asset.Images.userAdd)),
|
||||||
|
kind: .navigationLink {
|
||||||
|
context.send(viewAction: .processTapInvite)
|
||||||
|
})
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.invite)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ListRow(label: .default(title: L10n.screenPollsHistoryTitle,
|
||||||
|
icon: CompoundIcon(asset: Asset.Images.polls)),
|
||||||
|
kind: .navigationLink {
|
||||||
|
context.send(viewAction: .processTapPolls)
|
||||||
|
})
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.roomDetailsScreen.pollsHistory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct RoomPollsHistoryScreenCoordinatorParameters {
|
||||||
|
let roomProxy: RoomProxyProtocol
|
||||||
|
let pollInteractionHandler: PollInteractionHandlerProtocol
|
||||||
|
let roomTimelineController: RoomTimelineControllerProtocol
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RoomPollsHistoryScreenCoordinatorAction {
|
||||||
|
case editPoll(pollStartID: String, poll: Poll)
|
||||||
|
}
|
||||||
|
|
||||||
|
final class RoomPollsHistoryScreenCoordinator: CoordinatorProtocol {
|
||||||
|
private var viewModel: RoomPollsHistoryScreenViewModelProtocol
|
||||||
|
private let actionsSubject: PassthroughSubject<RoomPollsHistoryScreenCoordinatorAction, Never> = .init()
|
||||||
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
var actions: AnyPublisher<RoomPollsHistoryScreenCoordinatorAction, Never> {
|
||||||
|
actionsSubject.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(parameters: RoomPollsHistoryScreenCoordinatorParameters) {
|
||||||
|
viewModel = RoomPollsHistoryScreenViewModel(roomProxy: parameters.roomProxy,
|
||||||
|
pollInteractionHandler: parameters.pollInteractionHandler,
|
||||||
|
roomTimelineController: parameters.roomTimelineController,
|
||||||
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
}
|
||||||
|
|
||||||
|
func start() {
|
||||||
|
viewModel.actions.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
|
switch action {
|
||||||
|
case .editPoll(let pollStartID, let poll):
|
||||||
|
actionsSubject.send(.editPoll(pollStartID: pollStartID, poll: poll))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toPresentable() -> AnyView {
|
||||||
|
AnyView(RoomPollsHistoryScreen(context: viewModel.context))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum RoomPollsHistoryScreenViewModelAction {
|
||||||
|
case editPoll(pollStartID: String, poll: Poll)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RoomPollsHistoryScreenViewState: BindableState {
|
||||||
|
let title: String
|
||||||
|
let filters: [RoomPollsHistoryFilter] = [.ongoing, .past]
|
||||||
|
var pollTimelineItems: [RoomPollsHistoryPollDetails] = []
|
||||||
|
var canBackPaginate = false
|
||||||
|
var isBackPaginating = false
|
||||||
|
var bindings: RoomPollsHistoryScreenViewStateBindings
|
||||||
|
|
||||||
|
var emptyStateMessage: String {
|
||||||
|
switch bindings.filter {
|
||||||
|
case .ongoing:
|
||||||
|
L10n.screenPollsHistoryEmptyOngoing
|
||||||
|
case .past:
|
||||||
|
L10n.screenPollsHistoryEmptyPast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RoomPollsHistoryScreenViewStateBindings {
|
||||||
|
/// Polls list filter
|
||||||
|
var filter: RoomPollsHistoryFilter
|
||||||
|
|
||||||
|
/// Information describing the currently displayed alert.
|
||||||
|
var alertInfo: AlertInfo<RoomPollsHistoryScreenErrorType>?
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RoomPollsHistoryScreenViewAction {
|
||||||
|
case filter(RoomPollsHistoryFilter)
|
||||||
|
case end(pollStartID: String)
|
||||||
|
case edit(pollStartID: String, poll: Poll)
|
||||||
|
case sendPollResponse(pollStartID: String, optionID: String)
|
||||||
|
case loadMore
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RoomPollsHistoryFilter: Equatable {
|
||||||
|
case ongoing
|
||||||
|
case past
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RoomPollsHistoryPollDetails {
|
||||||
|
let timestamp: Date
|
||||||
|
let item: PollRoomTimelineItem
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RoomPollsHistoryFilter: CustomStringConvertible {
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .ongoing:
|
||||||
|
L10n.screenPollsHistoryFilterOngoing
|
||||||
|
case .past:
|
||||||
|
L10n.screenPollsHistoryFilterPast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RoomPollsHistoryScreenErrorType: Hashable {
|
||||||
|
/// A specific error message shown in an alert.
|
||||||
|
case alert
|
||||||
|
}
|
||||||
+200
@@ -0,0 +1,200 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Algorithms
|
||||||
|
import Combine
|
||||||
|
import OrderedCollections
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
typealias RoomPollsHistoryScreenViewModelType = StateStoreViewModel<RoomPollsHistoryScreenViewState, RoomPollsHistoryScreenViewAction>
|
||||||
|
|
||||||
|
class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, RoomPollsHistoryScreenViewModelProtocol {
|
||||||
|
private enum Constants {
|
||||||
|
static let backPaginationEventLimit: UInt = 250
|
||||||
|
}
|
||||||
|
|
||||||
|
private let roomProxy: RoomProxyProtocol
|
||||||
|
private let pollInteractionHandler: PollInteractionHandlerProtocol
|
||||||
|
private let roomTimelineController: RoomTimelineControllerProtocol
|
||||||
|
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
|
|
||||||
|
private var paginateBackwardsTask: Task<Void, Never>?
|
||||||
|
private let isPaginatingIndicatorID = UUID().uuidString
|
||||||
|
|
||||||
|
private var actionsSubject: PassthroughSubject<RoomPollsHistoryScreenViewModelAction, Never> = .init()
|
||||||
|
|
||||||
|
var actions: AnyPublisher<RoomPollsHistoryScreenViewModelAction, Never> {
|
||||||
|
actionsSubject.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(roomProxy: RoomProxyProtocol,
|
||||||
|
pollInteractionHandler: PollInteractionHandlerProtocol,
|
||||||
|
roomTimelineController: RoomTimelineControllerProtocol,
|
||||||
|
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||||
|
self.roomProxy = roomProxy
|
||||||
|
self.pollInteractionHandler = pollInteractionHandler
|
||||||
|
self.roomTimelineController = roomTimelineController
|
||||||
|
self.userIndicatorController = userIndicatorController
|
||||||
|
|
||||||
|
super.init(initialViewState: RoomPollsHistoryScreenViewState(title: L10n.screenPollsHistoryTitle,
|
||||||
|
canBackPaginate: true,
|
||||||
|
bindings: .init(filter: .ongoing)))
|
||||||
|
|
||||||
|
setupSubscriptions()
|
||||||
|
updatePollsList(filter: state.bindings.filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Public
|
||||||
|
|
||||||
|
override func process(viewAction: RoomPollsHistoryScreenViewAction) {
|
||||||
|
switch viewAction {
|
||||||
|
case .edit(let pollStartID, let poll):
|
||||||
|
actionsSubject.send(.editPoll(pollStartID: pollStartID, poll: poll))
|
||||||
|
case .end(let pollStartID):
|
||||||
|
endPoll(pollStartID: pollStartID)
|
||||||
|
case .filter(let filter):
|
||||||
|
updatePollsList(filter: filter)
|
||||||
|
case .loadMore:
|
||||||
|
paginateBackwards()
|
||||||
|
case .sendPollResponse(let pollStartID, let optionID):
|
||||||
|
sendPollResponse(pollStartID: pollStartID, optionID: optionID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Private
|
||||||
|
|
||||||
|
private func setupSubscriptions() {
|
||||||
|
roomTimelineController.callbacks
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] callback in
|
||||||
|
guard let self else { return }
|
||||||
|
|
||||||
|
switch callback {
|
||||||
|
case .updatedTimelineItems:
|
||||||
|
self.updatePollsList(filter: state.bindings.filter)
|
||||||
|
case .canBackPaginate(let canBackPaginate):
|
||||||
|
if self.state.canBackPaginate != canBackPaginate {
|
||||||
|
self.state.canBackPaginate = canBackPaginate
|
||||||
|
}
|
||||||
|
case .isBackPaginating:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
context.$viewState
|
||||||
|
.map(\.isBackPaginating)
|
||||||
|
.removeDuplicates()
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] isBackPaginating in
|
||||||
|
guard let self else { return }
|
||||||
|
if isBackPaginating {
|
||||||
|
userIndicatorController.submitIndicator(.init(id: isPaginatingIndicatorID, type: .modal(progress: .indeterminate, interactiveDismissDisabled: true, allowsInteraction: false), title: L10n.commonLoading))
|
||||||
|
} else {
|
||||||
|
userIndicatorController.retractIndicatorWithId(isPaginatingIndicatorID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func displayError(message: String) {
|
||||||
|
state.bindings.alertInfo = .init(id: .alert, title: message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Poll Interaction Handler
|
||||||
|
|
||||||
|
private func endPoll(pollStartID: String) {
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
try await pollInteractionHandler.endPoll(pollStartID: pollStartID).get()
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed to end poll. \(error)")
|
||||||
|
displayError(message: L10n.errorUnknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func sendPollResponse(pollStartID: String, optionID: String) {
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
try await pollInteractionHandler.sendPollResponse(pollStartID: pollStartID, optionID: optionID).get()
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed to send poll response. \(error)")
|
||||||
|
displayError(message: L10n.errorUnknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Timeline
|
||||||
|
|
||||||
|
private func updatePollsList(filter: RoomPollsHistoryFilter) {
|
||||||
|
// Get the poll timeline items to display
|
||||||
|
var items: [PollRoomTimelineItem] = []
|
||||||
|
for timelineItem in roomTimelineController.timelineItems {
|
||||||
|
if let pollRoomTimelineItem = timelineItem as? PollRoomTimelineItem {
|
||||||
|
// Apply the filter
|
||||||
|
switch filter {
|
||||||
|
case .ongoing where !pollRoomTimelineItem.poll.hasEnded:
|
||||||
|
items.append(pollRoomTimelineItem)
|
||||||
|
case .past where pollRoomTimelineItem.poll.hasEnded:
|
||||||
|
items.append(pollRoomTimelineItem)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map into RoomPollsHistoryPollDetails to have both the event timestamp and the timeline item
|
||||||
|
state.pollTimelineItems = items.map { item in
|
||||||
|
guard let timestamp = roomTimelineController.eventTimestamp(for: item.id) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return RoomPollsHistoryPollDetails(timestamp: timestamp, item: item)
|
||||||
|
}
|
||||||
|
.compactMap { $0 }
|
||||||
|
.sorted { $0.timestamp > $1.timestamp }
|
||||||
|
}
|
||||||
|
|
||||||
|
private func paginateBackwards() {
|
||||||
|
guard paginateBackwardsTask == nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
paginateBackwardsTask = Task { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.isBackPaginating = true
|
||||||
|
switch await roomTimelineController.paginateBackwards(requestSize: Constants.backPaginationEventLimit) {
|
||||||
|
case .failure(let error):
|
||||||
|
MXLog.error("failed to back paginate. \(error)")
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
paginateBackwardsTask = nil
|
||||||
|
state.isBackPaginating = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Mocks
|
||||||
|
|
||||||
|
extension RoomPollsHistoryScreenViewModel {
|
||||||
|
static let mock = RoomPollsHistoryScreenViewModel(roomProxy: RoomProxyMock(),
|
||||||
|
pollInteractionHandler: PollInteractionHandlerMock(),
|
||||||
|
roomTimelineController: MockRoomTimelineController(),
|
||||||
|
userIndicatorController: UserIndicatorControllerMock())
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
protocol RoomPollsHistoryScreenViewModelProtocol {
|
||||||
|
var actions: AnyPublisher<RoomPollsHistoryScreenViewModelAction, Never> { get }
|
||||||
|
var context: RoomPollsHistoryScreenViewModelType.Context { get }
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Compound
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct RoomPollsHistoryScreen: View {
|
||||||
|
@ObservedObject var context: RoomPollsHistoryScreenViewModel.Context
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView {
|
||||||
|
VStack(alignment: .center, spacing: 16) {
|
||||||
|
modePicker
|
||||||
|
|
||||||
|
polls
|
||||||
|
|
||||||
|
if context.viewState.pollTimelineItems.isEmpty {
|
||||||
|
emptyStateMessage
|
||||||
|
.padding(.top, 48)
|
||||||
|
}
|
||||||
|
|
||||||
|
if context.viewState.canBackPaginate {
|
||||||
|
loadMoreButton
|
||||||
|
.padding(.top, context.viewState.pollTimelineItems.isEmpty ? 0 : 16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.alert(item: $context.alertInfo)
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
|
.background(.compound.bgSubtleSecondaryLevel0)
|
||||||
|
.navigationTitle(context.viewState.title)
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Private
|
||||||
|
|
||||||
|
private var modePicker: some View {
|
||||||
|
Picker("", selection: $context.filter) {
|
||||||
|
ForEach(context.viewState.filters, id: \.self) { filter in
|
||||||
|
Text(filter.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pickerStyle(.segmented)
|
||||||
|
.readableFrame(maxWidth: 475)
|
||||||
|
.onChange(of: context.filter) { value in
|
||||||
|
context.send(viewAction: .filter(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var polls: some View {
|
||||||
|
ForEach(context.viewState.pollTimelineItems, id: \.item.id.eventID) { pollTimelineItem in
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
Text(DateFormatter.pollTimestamp.string(from: pollTimelineItem.timestamp))
|
||||||
|
.font(.compound.bodySM)
|
||||||
|
.foregroundColor(.compound.textSecondary)
|
||||||
|
PollView(poll: pollTimelineItem.item.poll, editable: pollTimelineItem.item.isEditable) { action in
|
||||||
|
switch action {
|
||||||
|
case .selectOption(let optionID):
|
||||||
|
guard let pollStartID = pollTimelineItem.item.id.eventID else { return }
|
||||||
|
context.send(viewAction: .sendPollResponse(pollStartID: pollStartID, optionID: optionID))
|
||||||
|
case .edit:
|
||||||
|
guard let pollStartID = pollTimelineItem.item.id.eventID else { return }
|
||||||
|
context.send(viewAction: .edit(pollStartID: pollStartID, poll: pollTimelineItem.item.poll))
|
||||||
|
case .end:
|
||||||
|
guard let pollStartID = pollTimelineItem.item.id.eventID else { return }
|
||||||
|
context.send(viewAction: .end(pollStartID: pollStartID))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.init(top: 12, leading: 12, bottom: 12, trailing: 12))
|
||||||
|
.background(.compound.bgCanvasDefaultLevel1)
|
||||||
|
.cornerRadius(12, corners: .allCorners)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var emptyStateMessage: some View {
|
||||||
|
Text(context.viewState.emptyStateMessage)
|
||||||
|
.font(.compound.bodyLG)
|
||||||
|
.foregroundColor(.compound.textSecondary)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.vertical, 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var loadMoreButton: some View {
|
||||||
|
Button {
|
||||||
|
context.send(viewAction: .loadMore)
|
||||||
|
} label: {
|
||||||
|
Text(L10n.Action.loadMore)
|
||||||
|
.font(.compound.bodyLGSemibold)
|
||||||
|
.padding(.horizontal, 12)
|
||||||
|
}
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.roomPollsHistoryScreen.loadMore)
|
||||||
|
.buttonStyle(.compound(.secondary))
|
||||||
|
.fixedSize()
|
||||||
|
.disabled(context.viewState.isBackPaginating)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension DateFormatter {
|
||||||
|
static let pollTimestamp: DateFormatter = {
|
||||||
|
let dateFormatter = DateFormatter()
|
||||||
|
dateFormatter.dateStyle = .short
|
||||||
|
return dateFormatter
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Previews
|
||||||
|
|
||||||
|
struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview {
|
||||||
|
static let viewModelEmpty: RoomPollsHistoryScreenViewModel = {
|
||||||
|
let roomTimelineController = MockRoomTimelineController()
|
||||||
|
roomTimelineController.timelineItems = []
|
||||||
|
let roomProxyMockConfiguration = RoomProxyMockConfiguration(displayName: "Polls")
|
||||||
|
roomProxyMockConfiguration.timeline.timelineStartReached = false
|
||||||
|
let viewModel = RoomPollsHistoryScreenViewModel(roomProxy: RoomProxyMock(with: roomProxyMockConfiguration),
|
||||||
|
pollInteractionHandler: PollInteractionHandlerMock(),
|
||||||
|
roomTimelineController: roomTimelineController,
|
||||||
|
userIndicatorController: UserIndicatorControllerMock())
|
||||||
|
return viewModel
|
||||||
|
}()
|
||||||
|
|
||||||
|
static let viewModel: RoomPollsHistoryScreenViewModel = {
|
||||||
|
let roomTimelineController = MockRoomTimelineController()
|
||||||
|
|
||||||
|
let polls = [PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: false)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: true)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true)]
|
||||||
|
|
||||||
|
roomTimelineController.timelineItems = polls
|
||||||
|
|
||||||
|
for i in 0..<polls.count {
|
||||||
|
let item = polls[i]
|
||||||
|
let date: Date! = DateComponents(calendar: .current, timeZone: .gmt, year: 2023, month: 12, day: 1 + i, hour: 12).date
|
||||||
|
roomTimelineController.timelineItemsTimestamp[item.id] = date
|
||||||
|
}
|
||||||
|
|
||||||
|
let roomProxyMockConfiguration = RoomProxyMockConfiguration(displayName: "Polls")
|
||||||
|
roomProxyMockConfiguration.timeline.timelineStartReached = true
|
||||||
|
let viewModel = RoomPollsHistoryScreenViewModel(roomProxy: RoomProxyMock(with: roomProxyMockConfiguration),
|
||||||
|
pollInteractionHandler: PollInteractionHandlerMock(),
|
||||||
|
roomTimelineController: roomTimelineController,
|
||||||
|
userIndicatorController: UserIndicatorControllerMock())
|
||||||
|
|
||||||
|
return viewModel
|
||||||
|
}()
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
NavigationStack {
|
||||||
|
RoomPollsHistoryScreen(context: viewModelEmpty.context)
|
||||||
|
}
|
||||||
|
.previewDisplayName("No polls")
|
||||||
|
.snapshot(delay: 1.0)
|
||||||
|
|
||||||
|
NavigationStack {
|
||||||
|
RoomPollsHistoryScreen(context: viewModel.context)
|
||||||
|
}
|
||||||
|
.previewDisplayName("polls")
|
||||||
|
.snapshot(delay: 1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ class RoomScreenInteractionHandler {
|
|||||||
private let application: ApplicationProtocol
|
private let application: ApplicationProtocol
|
||||||
private let appSettings: AppSettings
|
private let appSettings: AppSettings
|
||||||
private let analyticsService: AnalyticsService
|
private let analyticsService: AnalyticsService
|
||||||
|
private let pollInteractionHandler: PollInteractionHandlerProtocol
|
||||||
|
|
||||||
private let actionsSubject: PassthroughSubject<RoomScreenInteractionHandlerAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<RoomScreenInteractionHandlerAction, Never> = .init()
|
||||||
var actions: AnyPublisher<RoomScreenInteractionHandlerAction, Never> {
|
var actions: AnyPublisher<RoomScreenInteractionHandlerAction, Never> {
|
||||||
@@ -73,6 +74,7 @@ class RoomScreenInteractionHandler {
|
|||||||
self.application = application
|
self.application = application
|
||||||
self.appSettings = appSettings
|
self.appSettings = appSettings
|
||||||
self.analyticsService = analyticsService
|
self.analyticsService = analyticsService
|
||||||
|
pollInteractionHandler = PollInteractionHandler(analyticsService: analyticsService, roomProxy: roomProxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Timeline Item Action Menu
|
// MARK: Timeline Item Action Menu
|
||||||
@@ -274,9 +276,8 @@ class RoomScreenInteractionHandler {
|
|||||||
|
|
||||||
func sendPollResponse(pollStartID: String, optionID: String) {
|
func sendPollResponse(pollStartID: String, optionID: String) {
|
||||||
Task {
|
Task {
|
||||||
let sendPollResponseResult = await roomProxy.timeline.sendPollResponse(pollStartID: pollStartID, answers: [optionID])
|
let sendPollResponseResult = await pollInteractionHandler.sendPollResponse(pollStartID: pollStartID, optionID: optionID)
|
||||||
analyticsService.trackPollVote()
|
|
||||||
|
|
||||||
switch sendPollResponseResult {
|
switch sendPollResponseResult {
|
||||||
case .success:
|
case .success:
|
||||||
break
|
break
|
||||||
@@ -288,9 +289,8 @@ class RoomScreenInteractionHandler {
|
|||||||
|
|
||||||
func endPoll(pollStartID: String) {
|
func endPoll(pollStartID: String) {
|
||||||
Task {
|
Task {
|
||||||
let endPollResult = await roomProxy.timeline.endPoll(pollStartID: pollStartID,
|
let endPollResult = await pollInteractionHandler.endPoll(pollStartID: pollStartID)
|
||||||
text: "The poll with event id: \(pollStartID) has ended")
|
|
||||||
analyticsService.trackPollEnd()
|
|
||||||
switch endPollResult {
|
switch endPollResult {
|
||||||
case .success:
|
case .success:
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
enum PollViewAction {
|
||||||
|
case selectOption(optionID: String)
|
||||||
|
case edit
|
||||||
|
case end
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PollView: View {
|
||||||
|
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
||||||
|
|
||||||
|
let poll: Poll
|
||||||
|
let editable: Bool
|
||||||
|
let actionHandler: (PollViewAction) -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 16) {
|
||||||
|
questionView
|
||||||
|
optionsView
|
||||||
|
summaryView
|
||||||
|
toolbarView
|
||||||
|
}
|
||||||
|
.frame(maxWidth: 450)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Private
|
||||||
|
|
||||||
|
private var questionView: some View {
|
||||||
|
HStack(alignment: .top, spacing: 12) {
|
||||||
|
let asset = poll.hasEnded ? Asset.Images.pollsEnd : Asset.Images.polls
|
||||||
|
|
||||||
|
Image(asset.name)
|
||||||
|
.resizable()
|
||||||
|
.scaledFrame(size: 22)
|
||||||
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
|
Text(poll.question)
|
||||||
|
.multilineTextAlignment(.leading)
|
||||||
|
.font(.compound.bodyLGSemibold)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var optionsView: some View {
|
||||||
|
ForEach(poll.options, id: \.id) { option in
|
||||||
|
Button {
|
||||||
|
guard !option.isSelected else { return }
|
||||||
|
actionHandler(.selectOption(optionID: option.id))
|
||||||
|
feedbackGenerator.impactOccurred()
|
||||||
|
} label: {
|
||||||
|
PollOptionView(pollOption: option,
|
||||||
|
showVotes: showVotes,
|
||||||
|
isFinalResult: poll.hasEnded)
|
||||||
|
.foregroundColor(progressBarColor(for: option))
|
||||||
|
}
|
||||||
|
.disabled(poll.hasEnded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var summaryView: some View {
|
||||||
|
if let summaryText = poll.summaryText {
|
||||||
|
Text(summaryText)
|
||||||
|
.font(.compound.bodySM)
|
||||||
|
.scaledPadding(.leading, showVotes ? 0 : 32)
|
||||||
|
.foregroundColor(.compound.textSecondary)
|
||||||
|
.frame(maxWidth: .infinity, alignment: showVotes ? .trailing : .leading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var toolbarView: some View {
|
||||||
|
if !poll.hasEnded, poll.createdByAccountOwner {
|
||||||
|
Button {
|
||||||
|
toolbarAction()
|
||||||
|
} label: {
|
||||||
|
Text(editable ? L10n.actionEditPoll : L10n.actionEndPoll)
|
||||||
|
.lineLimit(2, reservesSpace: false)
|
||||||
|
.font(.compound.bodyLGSemibold)
|
||||||
|
.foregroundColor(.compound.textOnSolidPrimary)
|
||||||
|
.padding(.horizontal, 24)
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.background {
|
||||||
|
Capsule()
|
||||||
|
.foregroundColor(.compound.bgActionPrimaryRest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.top, 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func toolbarAction() {
|
||||||
|
if editable {
|
||||||
|
actionHandler(.edit)
|
||||||
|
} else {
|
||||||
|
actionHandler(.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func progressBarColor(for option: Poll.Option) -> Color {
|
||||||
|
if poll.hasEnded {
|
||||||
|
return option.isWinning ? .compound.textActionAccent : .compound.textDisabled
|
||||||
|
} else {
|
||||||
|
return .compound.textPrimary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var showVotes: Bool {
|
||||||
|
poll.hasEnded || poll.kind == .disclosed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension Poll {
|
||||||
|
var summaryText: String? {
|
||||||
|
guard !hasEnded else {
|
||||||
|
return options.first.map {
|
||||||
|
L10n.commonPollTotalVotes($0.allVotes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch kind {
|
||||||
|
case .disclosed:
|
||||||
|
return options.first.map {
|
||||||
|
L10n.commonPollTotalVotes($0.allVotes)
|
||||||
|
}
|
||||||
|
case .undisclosed:
|
||||||
|
return L10n.commonPollUndisclosedText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PollView_Previews: PreviewProvider, TestablePreview {
|
||||||
|
static var previews: some View {
|
||||||
|
PollView(poll: .disclosed(), editable: false) { _ in }
|
||||||
|
.padding()
|
||||||
|
.previewDisplayName("Disclosed")
|
||||||
|
|
||||||
|
PollView(poll: .undisclosed(), editable: false) { _ in }
|
||||||
|
.padding()
|
||||||
|
.previewDisplayName("Undisclosed")
|
||||||
|
|
||||||
|
PollView(poll: .endedDisclosed, editable: false) { _ in }
|
||||||
|
.padding()
|
||||||
|
.previewDisplayName("Ended, Disclosed")
|
||||||
|
|
||||||
|
PollView(poll: .endedUndisclosed, editable: false) { _ in }
|
||||||
|
.padding()
|
||||||
|
.previewDisplayName("Ended, Undisclosed")
|
||||||
|
|
||||||
|
PollView(poll: .disclosed(createdByAccountOwner: true), editable: true) { _ in }
|
||||||
|
.padding()
|
||||||
|
.previewDisplayName("Creator, disclosed")
|
||||||
|
|
||||||
|
PollView(poll: .emptyDisclosed, editable: true) { _ in }
|
||||||
|
.padding()
|
||||||
|
.previewDisplayName("Creator, no votes")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,136 +19,35 @@ import SwiftUI
|
|||||||
struct PollRoomTimelineView: View {
|
struct PollRoomTimelineView: View {
|
||||||
let timelineItem: PollRoomTimelineItem
|
let timelineItem: PollRoomTimelineItem
|
||||||
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
||||||
|
|
||||||
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TimelineStyler(timelineItem: timelineItem) {
|
TimelineStyler(timelineItem: timelineItem) {
|
||||||
VStack(alignment: .leading, spacing: 16) {
|
PollView(poll: poll, editable: timelineItem.isEditable) { action in
|
||||||
questionView
|
switch action {
|
||||||
optionsView
|
case .selectOption(let optionID):
|
||||||
summaryView
|
guard let eventID, let option = poll.options.first(where: { $0.id == optionID }), !option.isSelected else { return }
|
||||||
toolbarView
|
context.send(viewAction: .poll(.selectOption(pollStartID: eventID, optionID: option.id)))
|
||||||
|
case .edit:
|
||||||
|
guard let eventID else { return }
|
||||||
|
context.send(viewAction: .poll(.edit(pollStartID: eventID, poll: poll)))
|
||||||
|
case .end:
|
||||||
|
guard let eventID else { return }
|
||||||
|
context.send(viewAction: .poll(.end(pollStartID: eventID)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: 450)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Private
|
|
||||||
|
|
||||||
private var poll: Poll {
|
|
||||||
timelineItem.poll
|
|
||||||
}
|
|
||||||
|
|
||||||
private var eventID: String? {
|
|
||||||
timelineItem.id.eventID
|
|
||||||
}
|
|
||||||
|
|
||||||
private var questionView: some View {
|
|
||||||
HStack(alignment: .top, spacing: 12) {
|
|
||||||
let asset = poll.hasEnded ? Asset.Images.pollsEnd : Asset.Images.polls
|
|
||||||
|
|
||||||
Image(asset.name)
|
|
||||||
.resizable()
|
|
||||||
.scaledFrame(size: 22)
|
|
||||||
.accessibilityHidden(true)
|
|
||||||
|
|
||||||
Text(poll.question)
|
|
||||||
.multilineTextAlignment(.leading)
|
|
||||||
.font(.compound.bodyLGSemibold)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var optionsView: some View {
|
|
||||||
ForEach(poll.options, id: \.id) { option in
|
|
||||||
Button {
|
|
||||||
guard let eventID, !option.isSelected else { return }
|
|
||||||
context.send(viewAction: .poll(.selectOption(pollStartID: eventID, optionID: option.id)))
|
|
||||||
feedbackGenerator.impactOccurred()
|
|
||||||
} label: {
|
|
||||||
PollOptionView(pollOption: option,
|
|
||||||
showVotes: showVotes,
|
|
||||||
isFinalResult: poll.hasEnded)
|
|
||||||
.foregroundColor(progressBarColor(for: option))
|
|
||||||
}
|
|
||||||
.disabled(poll.hasEnded || eventID == nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var summaryView: some View {
|
|
||||||
if let summaryText = poll.summaryText {
|
|
||||||
Text(summaryText)
|
|
||||||
.font(.compound.bodySM)
|
|
||||||
.scaledPadding(.leading, showVotes ? 0 : 32)
|
|
||||||
.foregroundColor(.compound.textSecondary)
|
|
||||||
.frame(maxWidth: .infinity, alignment: showVotes ? .trailing : .leading)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var toolbarView: some View {
|
|
||||||
if !poll.hasEnded, poll.createdByAccountOwner {
|
|
||||||
Button {
|
|
||||||
toolbarAction()
|
|
||||||
} label: {
|
|
||||||
Text(timelineItem.isEditable ? L10n.actionEditPoll : L10n.actionEndPoll)
|
|
||||||
.lineLimit(2, reservesSpace: false)
|
|
||||||
.font(.compound.bodyLGSemibold)
|
|
||||||
.foregroundColor(.compound.textOnSolidPrimary)
|
|
||||||
.padding(.horizontal, 24)
|
|
||||||
.padding(.vertical, 10)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.background {
|
|
||||||
Capsule()
|
|
||||||
.foregroundColor(.compound.bgActionPrimaryRest)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.top, 8)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func toolbarAction() {
|
// MARK: - Private
|
||||||
guard let eventID else {
|
|
||||||
return
|
private var poll: Poll {
|
||||||
}
|
timelineItem.poll
|
||||||
|
|
||||||
if timelineItem.isEditable {
|
|
||||||
context.send(viewAction: .poll(.edit(pollStartID: eventID, poll: poll)))
|
|
||||||
} else {
|
|
||||||
context.send(viewAction: .poll(.end(pollStartID: eventID)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func progressBarColor(for option: Poll.Option) -> Color {
|
private var eventID: String? {
|
||||||
if poll.hasEnded {
|
timelineItem.id.eventID
|
||||||
return option.isWinning ? .compound.textActionAccent : .compound.textDisabled
|
|
||||||
} else {
|
|
||||||
return .compound.textPrimary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var showVotes: Bool {
|
|
||||||
poll.hasEnded || poll.kind == .disclosed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension Poll {
|
|
||||||
var summaryText: String? {
|
|
||||||
guard !hasEnded else {
|
|
||||||
return options.first.map {
|
|
||||||
L10n.commonPollTotalVotes($0.allVotes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch kind {
|
|
||||||
case .disclosed:
|
|
||||||
return options.first.map {
|
|
||||||
L10n.commonPollTotalVotes($0.allVotes)
|
|
||||||
}
|
|
||||||
case .undisclosed:
|
|
||||||
return L10n.commonPollUndisclosedText
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -74,7 +74,7 @@ struct DeveloperOptionsScreen: View {
|
|||||||
Text("Use encryption")
|
Text("Use encryption")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
Button {
|
Button {
|
||||||
showConfetti = true
|
showConfetti = true
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
class PollInteractionHandler: PollInteractionHandlerProtocol {
|
||||||
|
let analyticsService: AnalyticsService
|
||||||
|
let roomProxy: RoomProxyProtocol
|
||||||
|
|
||||||
|
init(analyticsService: AnalyticsService, roomProxy: RoomProxyProtocol) {
|
||||||
|
self.analyticsService = analyticsService
|
||||||
|
self.roomProxy = roomProxy
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendPollResponse(pollStartID: String, optionID: String) async -> Result<Void, Error> {
|
||||||
|
let sendPollResponseResult = await roomProxy.timeline.sendPollResponse(pollStartID: pollStartID, answers: [optionID])
|
||||||
|
analyticsService.trackPollVote()
|
||||||
|
|
||||||
|
return sendPollResponseResult.mapError { $0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
func endPoll(pollStartID: String) async -> Result<Void, Error> {
|
||||||
|
let endPollResult = await roomProxy.timeline.endPoll(pollStartID: pollStartID,
|
||||||
|
text: "The poll with event id: \(pollStartID) has ended")
|
||||||
|
analyticsService.trackPollEnd()
|
||||||
|
return endPollResult.mapError { $0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
protocol PollInteractionHandlerProtocol {
|
||||||
|
func sendPollResponse(pollStartID: String, optionID: String) async -> Result<Void, Error>
|
||||||
|
func endPoll(pollStartID: String) async -> Result<Void, Error>
|
||||||
|
}
|
||||||
|
|
||||||
|
// sourcery: AutoMockable
|
||||||
|
extension PollInteractionHandlerProtocol { }
|
||||||
+12
-1
@@ -31,6 +31,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
let callbacks = PassthroughSubject<RoomTimelineControllerCallback, Never>()
|
let callbacks = PassthroughSubject<RoomTimelineControllerCallback, Never>()
|
||||||
|
|
||||||
var timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default
|
var timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default
|
||||||
|
var timelineItemsTimestamp: [TimelineItemIdentifier: Date] = [:]
|
||||||
|
|
||||||
private var client: UITestsSignalling.Client?
|
private var client: UITestsSignalling.Client?
|
||||||
|
|
||||||
@@ -43,7 +44,12 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
fatalError("Failure setting up signalling: \(error)")
|
fatalError("Failure setting up signalling: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func paginateBackwards(requestSize: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
||||||
|
try? await simulateBackPagination()
|
||||||
|
return .success(())
|
||||||
|
}
|
||||||
|
|
||||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
||||||
callbacks.send(.canBackPaginate(false))
|
callbacks.send(.canBackPaginate(false))
|
||||||
return .success(())
|
return .success(())
|
||||||
@@ -99,6 +105,10 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
await roomProxy?.timeline.cancelSend(transactionID: transactionID)
|
await roomProxy?.timeline.cancelSend(transactionID: transactionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? {
|
||||||
|
timelineItemsTimestamp[itemID] ?? .now
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - UI Test signalling
|
// MARK: - UI Test signalling
|
||||||
|
|
||||||
/// The cancellable used for UI Tests signalling.
|
/// The cancellable used for UI Tests signalling.
|
||||||
@@ -153,6 +163,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
timelineItems.insert(contentsOf: newItems, at: 0)
|
timelineItems.insert(contentsOf: newItems, at: 0)
|
||||||
callbacks.send(.updatedTimelineItems)
|
callbacks.send(.updatedTimelineItems)
|
||||||
callbacks.send(.isBackPaginating(false))
|
callbacks.send(.isBackPaginating(false))
|
||||||
|
callbacks.send(.canBackPaginate(!backPaginationResponses.isEmpty))
|
||||||
|
|
||||||
try client?.send(.success)
|
try client?.send(.success)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,18 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func paginateBackwards(requestSize: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
||||||
|
MXLog.info("Started back pagination request")
|
||||||
|
switch await roomProxy.timeline.paginateBackwards(requestSize: requestSize) {
|
||||||
|
case .success:
|
||||||
|
MXLog.info("Finished back pagination request")
|
||||||
|
return .success(())
|
||||||
|
case .failure(let error):
|
||||||
|
MXLog.error("Failed back pagination request with error: \(error)")
|
||||||
|
return .failure(.generic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
||||||
MXLog.info("Started back pagination request")
|
MXLog.info("Started back pagination request")
|
||||||
switch await roomProxy.timeline.paginateBackwards(requestSize: requestSize, untilNumberOfItems: untilNumberOfItems) {
|
switch await roomProxy.timeline.paginateBackwards(requestSize: requestSize, untilNumberOfItems: untilNumberOfItems) {
|
||||||
@@ -236,7 +248,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
|
|
||||||
private func updateTimelineItems() {
|
private func updateTimelineItems() {
|
||||||
var newTimelineItems = [RoomTimelineItemProtocol]()
|
var newTimelineItems = [RoomTimelineItemProtocol]()
|
||||||
var canBackPaginate = true
|
var canBackPaginate = !roomProxy.timeline.timelineStartReached
|
||||||
var isBackPaginating = false
|
var isBackPaginating = false
|
||||||
var lastEncryptedHistoryItemIndex: Int?
|
var lastEncryptedHistoryItemIndex: Int?
|
||||||
|
|
||||||
@@ -299,7 +311,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timelineItems = newTimelineItems
|
timelineItems = newTimelineItems
|
||||||
|
|
||||||
callbacks.send(.updatedTimelineItems)
|
callbacks.send(.updatedTimelineItems)
|
||||||
@@ -384,4 +396,20 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? {
|
||||||
|
for itemProxy in roomProxy.timeline.timelineProvider.itemProxies {
|
||||||
|
switch itemProxy {
|
||||||
|
case .event(let eventTimelineItemProxy):
|
||||||
|
if eventTimelineItemProxy.id == itemID {
|
||||||
|
return eventTimelineItemProxy.timestamp
|
||||||
|
}
|
||||||
|
case .virtual:
|
||||||
|
break
|
||||||
|
case .unknown:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -45,6 +45,8 @@ protocol RoomTimelineControllerProtocol {
|
|||||||
|
|
||||||
func processItemDisappearance(_ itemID: TimelineItemIdentifier) async
|
func processItemDisappearance(_ itemID: TimelineItemIdentifier) async
|
||||||
|
|
||||||
|
func paginateBackwards(requestSize: UInt) async -> Result<Void, RoomTimelineControllerError>
|
||||||
|
|
||||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineControllerError>
|
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineControllerError>
|
||||||
|
|
||||||
func sendReadReceipt(for itemID: TimelineItemIdentifier) async -> Result<Void, RoomTimelineControllerError>
|
func sendReadReceipt(for itemID: TimelineItemIdentifier) async -> Result<Void, RoomTimelineControllerError>
|
||||||
@@ -70,6 +72,8 @@ protocol RoomTimelineControllerProtocol {
|
|||||||
func retrySending(itemID: TimelineItemIdentifier) async
|
func retrySending(itemID: TimelineItemIdentifier) async
|
||||||
|
|
||||||
func cancelSending(itemID: TimelineItemIdentifier) async
|
func cancelSending(itemID: TimelineItemIdentifier) async
|
||||||
|
|
||||||
|
func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date?
|
||||||
}
|
}
|
||||||
|
|
||||||
extension RoomTimelineControllerProtocol {
|
extension RoomTimelineControllerProtocol {
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
|
|
||||||
private let backPaginationStateSubject = PassthroughSubject<BackPaginationStatus, Never>()
|
private let backPaginationStateSubject = PassthroughSubject<BackPaginationStatus, Never>()
|
||||||
private let timelineUpdatesSubject = PassthroughSubject<[TimelineDiff], Never>()
|
private let timelineUpdatesSubject = PassthroughSubject<[TimelineDiff], Never>()
|
||||||
|
|
||||||
|
private(set) var timelineStartReached = false
|
||||||
|
|
||||||
private let actionsSubject = PassthroughSubject<TimelineProxyAction, Never>()
|
private let actionsSubject = PassthroughSubject<TimelineProxyAction, Never>()
|
||||||
var actions: AnyPublisher<TimelineProxyAction, Never> {
|
var actions: AnyPublisher<TimelineProxyAction, Never> {
|
||||||
@@ -134,6 +136,18 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
try? timeline.getTimelineEventContentByEventId(eventId: eventID)
|
try? timeline.getTimelineEventContentByEventId(eventId: eventID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func paginateBackwards(requestSize: UInt) async -> Result<Void, TimelineProxyError> {
|
||||||
|
do {
|
||||||
|
try await Task.dispatch(on: .global()) {
|
||||||
|
try self.timeline.paginateBackwards(opts: .simpleRequest(eventLimit: UInt16(requestSize), waitForToken: true))
|
||||||
|
}
|
||||||
|
|
||||||
|
return .success(())
|
||||||
|
} catch {
|
||||||
|
return .failure(.failedPaginatingBackwards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, TimelineProxyError> {
|
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, TimelineProxyError> {
|
||||||
do {
|
do {
|
||||||
try await Task.dispatch(on: .global()) {
|
try await Task.dispatch(on: .global()) {
|
||||||
@@ -480,6 +494,9 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
|
|
||||||
private func subscribeToBackpagination() {
|
private func subscribeToBackpagination() {
|
||||||
let listener = RoomBackpaginationStatusListener { [weak self] status in
|
let listener = RoomBackpaginationStatusListener { [weak self] status in
|
||||||
|
if status == .timelineStartReached {
|
||||||
|
self?.timelineStartReached = true
|
||||||
|
}
|
||||||
self?.backPaginationStateSubject.send(status)
|
self?.backPaginationStateSubject.send(status)
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ protocol TimelineProxyProtocol {
|
|||||||
|
|
||||||
var timelineProvider: RoomTimelineProviderProtocol { get }
|
var timelineProvider: RoomTimelineProviderProtocol { get }
|
||||||
|
|
||||||
|
var timelineStartReached: Bool { get }
|
||||||
|
|
||||||
func subscribeForUpdates() async
|
func subscribeForUpdates() async
|
||||||
|
|
||||||
/// Cancels a failed message given its transaction ID from the timeline
|
/// Cancels a failed message given its transaction ID from the timeline
|
||||||
@@ -62,6 +64,8 @@ protocol TimelineProxyProtocol {
|
|||||||
/// Retries sending a failed message given its transaction ID
|
/// Retries sending a failed message given its transaction ID
|
||||||
func retrySend(transactionID: String) async
|
func retrySend(transactionID: String) async
|
||||||
|
|
||||||
|
func paginateBackwards(requestSize: UInt) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, TimelineProxyError>
|
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendAudio(url: URL,
|
func sendAudio(url: URL,
|
||||||
|
|||||||
@@ -877,6 +877,40 @@ class MockScreen: Identifiable {
|
|||||||
let coordinator = PollFormScreenCoordinator(parameters: .init(mode: .new))
|
let coordinator = PollFormScreenCoordinator(parameters: .init(mode: .new))
|
||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
return navigationStackCoordinator
|
return navigationStackCoordinator
|
||||||
|
case .roomPollsHistoryEmptyLoadMore:
|
||||||
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
|
let interactionHandler = PollInteractionHandlerMock()
|
||||||
|
let roomTimelineController = MockRoomTimelineController()
|
||||||
|
roomTimelineController.backPaginationResponses = [
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
let roomProxyMockConfiguration = RoomProxyMockConfiguration(displayName: "Polls")
|
||||||
|
roomProxyMockConfiguration.timeline.timelineStartReached = false
|
||||||
|
let parameters = RoomPollsHistoryScreenCoordinatorParameters(roomProxy: RoomProxyMock(with: roomProxyMockConfiguration),
|
||||||
|
pollInteractionHandler: interactionHandler,
|
||||||
|
roomTimelineController: roomTimelineController)
|
||||||
|
let coordinator = RoomPollsHistoryScreenCoordinator(parameters: parameters)
|
||||||
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
|
return navigationStackCoordinator
|
||||||
|
case .roomPollsHistoryLoadMore:
|
||||||
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
|
let interactionHandler = PollInteractionHandlerMock()
|
||||||
|
let roomTimelineController = MockRoomTimelineController()
|
||||||
|
|
||||||
|
let poll = PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true)
|
||||||
|
roomTimelineController.timelineItems = [poll]
|
||||||
|
let date: Date! = DateComponents(calendar: .current, timeZone: .gmt, year: 2023, month: 12, day: 1, hour: 12).date
|
||||||
|
roomTimelineController.timelineItemsTimestamp = [poll.id: date]
|
||||||
|
|
||||||
|
let roomProxyMockConfiguration = RoomProxyMockConfiguration(displayName: "Polls")
|
||||||
|
roomProxyMockConfiguration.timeline.timelineStartReached = false
|
||||||
|
let parameters = RoomPollsHistoryScreenCoordinatorParameters(roomProxy: RoomProxyMock(with: roomProxyMockConfiguration),
|
||||||
|
pollInteractionHandler: interactionHandler,
|
||||||
|
roomTimelineController: roomTimelineController)
|
||||||
|
let coordinator = RoomPollsHistoryScreenCoordinator(parameters: parameters)
|
||||||
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
|
return navigationStackCoordinator
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ enum UITestsScreenIdentifier: String {
|
|||||||
case createRoom
|
case createRoom
|
||||||
case createRoomNoUsers
|
case createRoomNoUsers
|
||||||
case createPoll
|
case createPoll
|
||||||
|
case roomPollsHistoryEmptyLoadMore
|
||||||
|
case roomPollsHistoryLoadMore
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UITestsScreenIdentifier: CustomStringConvertible {
|
extension UITestsScreenIdentifier: CustomStringConvertible {
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class RoomPollsHistoryScreenUITests: XCTestCase {
|
||||||
|
func testEmptyPollsHistory() async throws {
|
||||||
|
let app = Application.launch(.roomPollsHistoryEmptyLoadMore)
|
||||||
|
|
||||||
|
XCTAssert(app.buttons[A11yIdentifiers.roomPollsHistoryScreen.loadMore].waitForExistence(timeout: 1))
|
||||||
|
|
||||||
|
try await app.assertScreenshot(.roomPollsHistoryEmptyLoadMore)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPollsHistory() async throws {
|
||||||
|
let app = Application.launch(.roomPollsHistoryLoadMore)
|
||||||
|
|
||||||
|
XCTAssert(app.buttons[A11yIdentifiers.roomPollsHistoryScreen.loadMore].waitForExistence(timeout: 1))
|
||||||
|
|
||||||
|
try await app.assertScreenshot(.roomPollsHistoryLoadMore)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:b0266cfccbe6a640908b54c226e1e2d544bedd1aa3343304163fc87f54c9d437
|
oid sha256:e0f0d0153b192c9d39095958380d457e2cf2857fb7de3e385c48dba4b15219d2
|
||||||
size 105010
|
size 108327
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:013cb46ed50d1a9c302218afbac4aec5a99c76876915dbe83e54354f444aedd3
|
oid sha256:ccb8342762f048022b0cb9b2100d235e120e56e485a7564c0bd572a807398bf2
|
||||||
size 134604
|
size 138647
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:0b01d2cef8bcd3400a276b8e4a4757ab2dd2c431ea00892e7a609319988022db
|
oid sha256:1c83c28c9e8ee2196c5874fe958f1003aae29156afac721478578dc372706d48
|
||||||
size 137928
|
size 140846
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:1c17e1eb73421a3c3ef948f0c1007673a67130ff126d4eb54833e56b82e3f96a
|
oid sha256:066a49f7d5f1e8fd46a3f35c403bd1b8257e5b30ad6c3af15ea666a783e1f399
|
||||||
size 109992
|
size 113268
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:010e94e5b3d969f7141afb1951fcb6c87dd9ea6a48dc944dfeb8bac3a1e66e74
|
oid sha256:337b7463033f2b86866f880461402139586b960333b6f0e628b57eb3b32a0454
|
||||||
size 142139
|
size 145428
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1f8bb38f2fef834933223d9f2fde4e9739a93e025dafbec63931e4f4e35e7a19
|
||||||
|
size 73279
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:c2b9a7343b1c186a071eed7a3c337101cc0efb569b612f1b5e0737a84e798355
|
||||||
|
size 113574
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:6398dc3faa59f76171d5b07d51189b28ea8c5b4842e65b2c6b2d2ef8c9a876fc
|
oid sha256:9e7814adddbd5a2ff51be824e5a842edd4c7ba7c2fdfdef635a6758e09cbf661
|
||||||
size 130901
|
size 133394
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:8cd5e793eaf7b9d7c49e7a941f80d3cda9006a91035e36fa74f973bd707605a7
|
oid sha256:1ff99b080b22b3c09001fc3fc835e3b41c877f5e7f2cd6cfe26ef2f7c01a54c1
|
||||||
size 178087
|
size 176256
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:879e4c49e9a0e3ea321f30f0fe4e157abb0576ec97d116037b3fbd45425ee4b8
|
oid sha256:9988534198d133d1f9e020e6af5628259bea9c6fdda64ac5b168230dc0a4621e
|
||||||
size 179235
|
size 176611
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9ce09743029cf0f0c0538c23dce32014338a186d3b647bbefba1c4eb43d5962b
|
oid sha256:e91d758ef441d68019b14c2416d761f9f522321f8d1e9d826072eb3fcf07dee6
|
||||||
size 137992
|
size 142550
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:374b2e5744e3006e6cf0424bfbe05126465bd8ef3e1926ab1bd370797bbce441
|
oid sha256:2a99249f04ea968b762cf14ff335f048eb7d91374c01761d8262c526f858431e
|
||||||
size 189541
|
size 194812
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:eddf4597e366941142a3df33e8341465b373eac43fb5f285a2a3a39f2d81d3df
|
||||||
|
size 79393
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:c6f01046e054115621ff5ef7189e5bf791555d9729af959c6e38a8a048f4350e
|
||||||
|
size 136913
|
||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9cccaa927653f0ad0c743af8b3638e9dc05329cee2c9be75b0c538b33ab248e8
|
oid sha256:3288dfb3ed775665e37c214c4f2d2033e3174f22f41006f5fe0d1878a60866c1
|
||||||
size 119658
|
size 123312
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:5ae457bdca037f41371586172d1ad7856d0e204257f55de0b8ac56e4e1cf0100
|
oid sha256:47e87c18eb21430919e24ebc8307531e479e03fefffc001e45623739ea9ec62f
|
||||||
size 149272
|
size 154961
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:6e50c3b2e4ea93ac0eb7ac8fe76ce705c2ad70acf9d45169deb27377d811b3b1
|
oid sha256:be36151a47830413040624f7d0922bd389321e11387e72c7581f691b3ea37b94
|
||||||
size 153678
|
size 156406
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:2012b95de7998c0321c7f8c7e14a5c336064eab574418f0110007c41098d1d75
|
oid sha256:40e4ca832c774e501232f9d4a5dfaceae34d72d3a8f4a0647ff26afa73f5552e
|
||||||
size 125205
|
size 129593
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:1e1582e788c142a48c58b95109f9e61ea4ca33039457614fe7abf329da331d72
|
oid sha256:46290c09fa96860d002308e7fdc80dd9840c3ed12567489343ed568e1d11c55c
|
||||||
size 157243
|
size 160957
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:9606120bc5a84596e5c8fd0fc5ed645327ad2dcb231520cb3359ee6fe3250a4a
|
||||||
|
size 76919
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:fd4d7f3b5f97247a3dabd79ad1349649b64f075c88cb7e44b79aa77e21930e1b
|
||||||
|
size 126359
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:83076ceeb1fab6a333305fd9810c6a4475ac2779ba0154ef9f94570f6131a4ea
|
oid sha256:380a2caf2250cba0f7f69763860958ef8d3107d6841b10e139221022f719f7e2
|
||||||
size 165487
|
size 165836
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:ce6b94d85f64b6687c8cfbe91b25811b3b28ce8ef2350ffc0bb18852be0930e9
|
oid sha256:ede47654000517fbf67ef6085f4b9c9574b50a73723925690a868dfad1c4684a
|
||||||
size 206487
|
size 207805
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:fe7064493f7f4838af12b13eb51295ae68163ceae6740bda6dbdbd36705ccc29
|
oid sha256:0ef967694784f25e8e3614498d8ada07569910917432815523e34a9a4f79f301
|
||||||
size 194311
|
size 178881
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:4502d0e8b1e37f8917226b425be5c6c50d9eaaf6c65d43cd80e6b391ad8e8157
|
oid sha256:360f724b77a289e54e99ecb225e33cb30252a23bcae18f7f6de287f550c37b70
|
||||||
size 168510
|
size 171690
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:7ff50bea189beb7dcfa9efb5d3cfcadbdf5abe5c5a3b7db924719de2ab48e545
|
oid sha256:e75114908cf9e7049ceafeda01d5c69eb48a54bef628245a5eecd805e00e8026
|
||||||
size 214384
|
size 201023
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:93857a1d768489bd8854e67520d436c31a73cb861a78509a1255cc92d8ceef5b
|
||||||
|
size 85920
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:b2c163403ced353a3d7871275cf8619d7d9ab8da7c2819282043458f233011ee
|
||||||
|
size 160495
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@testable import ElementX
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class RoomPollsHistoryScreenViewModelTests: XCTestCase {
|
||||||
|
var viewModel: RoomPollsHistoryScreenViewModelProtocol!
|
||||||
|
var interactionHandler: PollInteractionHandlerMock!
|
||||||
|
var timelineController: MockRoomTimelineController!
|
||||||
|
|
||||||
|
var context: RoomPollsHistoryScreenViewModelType.Context {
|
||||||
|
viewModel.context
|
||||||
|
}
|
||||||
|
|
||||||
|
override func setUpWithError() throws {
|
||||||
|
interactionHandler = PollInteractionHandlerMock()
|
||||||
|
timelineController = MockRoomTimelineController()
|
||||||
|
let roomProxyMockConfiguration = RoomProxyMockConfiguration(displayName: "Polls")
|
||||||
|
roomProxyMockConfiguration.timeline.timelineStartReached = false
|
||||||
|
viewModel = RoomPollsHistoryScreenViewModel(roomProxy: RoomProxyMock(with: roomProxyMockConfiguration),
|
||||||
|
pollInteractionHandler: interactionHandler,
|
||||||
|
roomTimelineController: timelineController,
|
||||||
|
userIndicatorController: UserIndicatorControllerMock())
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBackPaginate() async throws {
|
||||||
|
timelineController.backPaginationResponses = [
|
||||||
|
[PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: true)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: false)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .endedDisclosed)]
|
||||||
|
]
|
||||||
|
|
||||||
|
let deferredViewState = deferFulfillment(viewModel.context.$viewState, keyPath: \.isBackPaginating, transitionValues: [false, true, false])
|
||||||
|
|
||||||
|
viewModel.context.send(viewAction: .loadMore)
|
||||||
|
|
||||||
|
try await deferredViewState.fulfill()
|
||||||
|
|
||||||
|
XCTAssertEqual(viewModel.context.viewState.pollTimelineItems.count, 3)
|
||||||
|
XCTAssertFalse(viewModel.context.viewState.canBackPaginate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBackPaginateCanBackPaginate() async throws {
|
||||||
|
timelineController.backPaginationResponses = [
|
||||||
|
[PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: true)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: false)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .endedDisclosed)],
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
|
||||||
|
let deferredViewState = deferFulfillment(viewModel.context.$viewState, keyPath: \.isBackPaginating, transitionValues: [false, true, false])
|
||||||
|
|
||||||
|
viewModel.context.send(viewAction: .loadMore)
|
||||||
|
|
||||||
|
try await deferredViewState.fulfill()
|
||||||
|
|
||||||
|
XCTAssertEqual(viewModel.context.viewState.pollTimelineItems.count, 3)
|
||||||
|
XCTAssert(viewModel.context.viewState.canBackPaginate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBackPaginateTwice() async throws {
|
||||||
|
timelineController.backPaginationResponses = [
|
||||||
|
[PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: true)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: false))],
|
||||||
|
[PollRoomTimelineItem.mock(poll: .endedDisclosed)]
|
||||||
|
]
|
||||||
|
let deferredViewState = deferFulfillment(viewModel.context.$viewState, keyPath: \.isBackPaginating, transitionValues: [false, true, false])
|
||||||
|
|
||||||
|
viewModel.context.send(viewAction: .loadMore)
|
||||||
|
viewModel.context.send(viewAction: .loadMore)
|
||||||
|
|
||||||
|
try await deferredViewState.fulfill()
|
||||||
|
|
||||||
|
XCTAssertEqual(viewModel.context.viewState.pollTimelineItems.count, 3)
|
||||||
|
XCTAssert(viewModel.context.viewState.canBackPaginate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFilters() async throws {
|
||||||
|
timelineController.backPaginationResponses = [
|
||||||
|
[PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: true)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: false)),
|
||||||
|
PollRoomTimelineItem.mock(poll: .endedDisclosed)],
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
|
||||||
|
let deferredViewState = deferFulfillment(viewModel.context.$viewState) { value in
|
||||||
|
!value.pollTimelineItems.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.context.filter = .ongoing
|
||||||
|
viewModel.context.send(viewAction: .loadMore)
|
||||||
|
|
||||||
|
try await deferredViewState.fulfill()
|
||||||
|
|
||||||
|
XCTAssertEqual(viewModel.context.viewState.pollTimelineItems.count, 3)
|
||||||
|
|
||||||
|
viewModel.context.send(viewAction: .filter(.past))
|
||||||
|
XCTAssertEqual(viewModel.context.viewState.pollTimelineItems.count, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEndPoll() async throws {
|
||||||
|
let deferred = deferFulfillment(interactionHandler.publisher) { _ in true }
|
||||||
|
|
||||||
|
interactionHandler.endPollPollStartIDReturnValue = .success(())
|
||||||
|
viewModel.context.send(viewAction: .end(pollStartID: "somePollID"))
|
||||||
|
|
||||||
|
try await deferred.fulfill()
|
||||||
|
|
||||||
|
XCTAssert(interactionHandler.endPollPollStartIDCalled)
|
||||||
|
XCTAssertEqual(interactionHandler.endPollPollStartIDReceivedPollStartID, "somePollID")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEndPollFailure() async throws {
|
||||||
|
let deferred = deferFulfillment(viewModel.context.$viewState) { value in
|
||||||
|
value.bindings.alertInfo != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
interactionHandler.endPollPollStartIDReturnValue = .failure(TimelineProxyError.failedEndingPoll)
|
||||||
|
viewModel.context.send(viewAction: .end(pollStartID: "somePollID"))
|
||||||
|
|
||||||
|
try await deferred.fulfill()
|
||||||
|
|
||||||
|
XCTAssert(interactionHandler.endPollPollStartIDCalled)
|
||||||
|
XCTAssertEqual(interactionHandler.endPollPollStartIDReceivedPollStartID, "somePollID")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSendPollResponse() async throws {
|
||||||
|
let deferred = deferFulfillment(interactionHandler.publisher) { _ in true }
|
||||||
|
|
||||||
|
interactionHandler.sendPollResponsePollStartIDOptionIDReturnValue = .success(())
|
||||||
|
viewModel.context.send(viewAction: .sendPollResponse(pollStartID: "somePollID", optionID: "someOptionID"))
|
||||||
|
|
||||||
|
try await deferred.fulfill()
|
||||||
|
|
||||||
|
XCTAssert(interactionHandler.sendPollResponsePollStartIDOptionIDCalled)
|
||||||
|
XCTAssertEqual(interactionHandler.sendPollResponsePollStartIDOptionIDReceivedInvocations[0].pollStartID, "somePollID")
|
||||||
|
XCTAssertEqual(interactionHandler.sendPollResponsePollStartIDOptionIDReceivedInvocations[0].optionID, "someOptionID")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSendPollResponseFailure() async throws {
|
||||||
|
let deferred = deferFulfillment(viewModel.context.$viewState) { value in
|
||||||
|
value.bindings.alertInfo != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
interactionHandler.sendPollResponsePollStartIDOptionIDReturnValue = .failure(TimelineProxyError.failedSendingPollResponse)
|
||||||
|
viewModel.context.send(viewAction: .sendPollResponse(pollStartID: "somePollID", optionID: "someOptionID"))
|
||||||
|
|
||||||
|
try await deferred.fulfill()
|
||||||
|
|
||||||
|
XCTAssert(interactionHandler.sendPollResponsePollStartIDOptionIDCalled)
|
||||||
|
XCTAssertEqual(interactionHandler.sendPollResponsePollStartIDOptionIDReceivedInvocations[0].pollStartID, "somePollID")
|
||||||
|
XCTAssertEqual(interactionHandler.sendPollResponsePollStartIDOptionIDReceivedInvocations[0].optionID, "someOptionID")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEditPoll() async throws {
|
||||||
|
let expectedPoll: Poll = .emptyDisclosed
|
||||||
|
let expectedPollStartID = "someEventID"
|
||||||
|
|
||||||
|
let deferred = deferFulfillment(viewModel.actions) { action in
|
||||||
|
switch action {
|
||||||
|
case .editPoll(let pollStartID, let poll):
|
||||||
|
expectedPollStartID == pollStartID && expectedPoll == poll
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.context.send(viewAction: .edit(pollStartID: expectedPollStartID, poll: expectedPoll))
|
||||||
|
try await deferred.fulfill()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:6b0c5b464a748ad0862049a76bb4f187c679034cc28898447c5058c4931789ac
|
||||||
|
size 116006
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d3e3a08b89f04a344b1eeedd42100ea950063a5cd0bab3eb944fc12f9e19951a
|
||||||
|
size 115364
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:cda1d8f5b00bce67897298cfd4c8f13449c1a4925648845abea59f0b9ad95156
|
||||||
|
size 108965
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:72a22c525adf7ae1a33801dea692ce7774d285e8b1c4430167da71709e990c32
|
||||||
|
size 109045
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:72a22c525adf7ae1a33801dea692ce7774d285e8b1c4430167da71709e990c32
|
||||||
|
size 109045
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:5f8d5def15c593ab91d412d432957ca8fbc73c552dc45d8940d32b6f4d512b02
|
||||||
|
size 103783
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9e0f795c81b1de86d8fd339a4a41da77e1ba5708ff7f1d353a84cd72872b85ae
|
oid sha256:3385ad85711489e26d8a7bc8d4951595fbb860f78b894bbdede811b33da4e875
|
||||||
size 170145
|
size 169187
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:71a9439c43fa9d524757b86286c97364fb36862f7a5baaf85195d3f6c838e9f4
|
oid sha256:df5bf3bdc2a327abc5acff85eacf22da2daea56cd87edb20d166bf63ea6c65c5
|
||||||
size 174322
|
size 173146
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:485b9d96a003d14cfcc81a607e1cf22277b7a6daabe14cfaf3ab817dd9ff2040
|
oid sha256:1d62c100d777596fbec7d9f7d6ad03983f7963bdab029ed231667bdca5db767e
|
||||||
size 105327
|
size 112041
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:283f397347f3307f448ca2a271ef6e7ec8a71e697c4929e5b8c3d3464e02cf40
|
||||||
|
size 93617
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:cf0718060176eba8372ec98d6d2ceddd12a0f25e25bebda7fec9fa0ea904b482
|
||||||
|
size 201120
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
The poll history can be viewed in the room details.
|
||||||
Reference in New Issue
Block a user