RoomTimeline… refactor (drop the Room). (#3728)

* Add the timeline controller factory to the timeline view model.

In preparation for building a timeline to swipe through media in QuickLook.

* Refactor RoomTimelineControllerFactory.

* Refactor RoomTimelineController.

* Refactor RoomTimelineProvider.
This commit is contained in:
Doug 2025-02-03 14:14:01 +00:00 committed by GitHub
parent 9df5a8fddb
commit d195e603c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
53 changed files with 688 additions and 631 deletions

View File

@ -66,7 +66,6 @@
095D3906CF2F940C2D2D17CC /* RoomFlowCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FCB2126C091EEF2454B4D56 /* RoomFlowCoordinatorTests.swift */; }; 095D3906CF2F940C2D2D17CC /* RoomFlowCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FCB2126C091EEF2454B4D56 /* RoomFlowCoordinatorTests.swift */; };
09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */; }; 09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */; };
09AAF04B27732046C755D914 /* SoftLogoutViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */; }; 09AAF04B27732046C755D914 /* SoftLogoutViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */; };
09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */; };
09D3D7D115318CAD131B4FE7 /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57084488B03BDB33C7B7CA0E /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift */; }; 09D3D7D115318CAD131B4FE7 /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57084488B03BDB33C7B7CA0E /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift */; };
0A0625A271EE5B06D2AAA069 /* HomeScreenSlidingSyncMigrationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4691B8DE1D51DE152680098A /* HomeScreenSlidingSyncMigrationBanner.swift */; }; 0A0625A271EE5B06D2AAA069 /* HomeScreenSlidingSyncMigrationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4691B8DE1D51DE152680098A /* HomeScreenSlidingSyncMigrationBanner.swift */; };
0A194F5E70B5A628C1BF4476 /* AdvancedSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4999B5FD50AED7CB0F590FF8 /* AdvancedSettingsScreenModels.swift */; }; 0A194F5E70B5A628C1BF4476 /* AdvancedSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4999B5FD50AED7CB0F590FF8 /* AdvancedSettingsScreenModels.swift */; };
@ -221,7 +220,6 @@
2A864BB12A8501B47805D828 /* AuthenticationFlowCoordinatorUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */; }; 2A864BB12A8501B47805D828 /* AuthenticationFlowCoordinatorUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295E28C3B9EAADF519BF2F44 /* AuthenticationFlowCoordinatorUITests.swift */; };
2AAB2A77F1762A2648078A30 /* InteractiveQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */; }; 2AAB2A77F1762A2648078A30 /* InteractiveQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */; };
2AB9D4146C8748CF1D007B67 /* test_pdf.pdf in Resources */ = {isa = PBXBuildFile; fileRef = BE98688578F8B0541D853695 /* test_pdf.pdf */; }; 2AB9D4146C8748CF1D007B67 /* test_pdf.pdf in Resources */ = {isa = PBXBuildFile; fileRef = BE98688578F8B0541D853695 /* test_pdf.pdf */; };
2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */; };
2AED12987603157C32C2114D /* TimelineBubbleLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */; }; 2AED12987603157C32C2114D /* TimelineBubbleLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */; };
2B97BCE72D86645F1485C976 /* RoomDirectorySearchMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894EE8F5B399A165BA2A6634 /* RoomDirectorySearchMock.swift */; }; 2B97BCE72D86645F1485C976 /* RoomDirectorySearchMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894EE8F5B399A165BA2A6634 /* RoomDirectorySearchMock.swift */; };
2BA59D0AEFB4B82A2EC2A326 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; }; 2BA59D0AEFB4B82A2EC2A326 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
@ -230,6 +228,7 @@
2BBC0EB1E07963810A5D7423 /* ReadMarkerRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */; }; 2BBC0EB1E07963810A5D7423 /* ReadMarkerRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */; };
2BBE320EE426A347AAE5C7DA /* IdentityConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */; }; 2BBE320EE426A347AAE5C7DA /* IdentityConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */; };
2BC579CB5CE90CFE07CA0955 /* EditRoomAddressScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41656BC6267D55C56A2AAC08 /* EditRoomAddressScreenCoordinator.swift */; }; 2BC579CB5CE90CFE07CA0955 /* EditRoomAddressScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41656BC6267D55C56A2AAC08 /* EditRoomAddressScreenCoordinator.swift */; };
2BFA4C6D5B3D327B02C66AB0 /* TimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4216C12C0369A8AB059EDE9 /* TimelineController.swift */; };
2C4C750D0039AFABDF24236C /* TemplateScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */; }; 2C4C750D0039AFABDF24236C /* TemplateScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */; };
2C5E832434EE94E21AB3B238 /* EmojiPickerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */; }; 2C5E832434EE94E21AB3B238 /* EmojiPickerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EAE3E9D5EF4A6D5D9C6CFD /* EmojiPickerScreenViewModel.swift */; };
2CA61BB208CD82EBDB58CD13 /* VideoRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */; }; 2CA61BB208CD82EBDB58CD13 /* VideoRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */; };
@ -287,7 +286,6 @@
384D6B9A7DFD7260139D6852 /* UITestsNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */; }; 384D6B9A7DFD7260139D6852 /* UITestsNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBEB8D9F4940E161B18FE4BC /* UITestsNotificationCenter.swift */; };
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; }; 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; };
386720B603F87D156DB01FB2 /* VoiceMessageMediaManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40076C770A5FB83325252973 /* VoiceMessageMediaManager.swift */; }; 386720B603F87D156DB01FB2 /* VoiceMessageMediaManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40076C770A5FB83325252973 /* VoiceMessageMediaManager.swift */; };
38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */; };
388D39ED9FE1122EA6D76BF2 /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BC84BA0AF11C2128D58ABD /* Common.swift */; }; 388D39ED9FE1122EA6D76BF2 /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BC84BA0AF11C2128D58ABD /* Common.swift */; };
3895969759E68FAB90C63EF7 /* ElementCallServiceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */; }; 3895969759E68FAB90C63EF7 /* ElementCallServiceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */; };
38CC67C7673FA97C21CCD5B5 /* WebRegistrationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B065EC39C99C1303A101C1C /* WebRegistrationScreen.swift */; }; 38CC67C7673FA97C21CCD5B5 /* WebRegistrationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B065EC39C99C1303A101C1C /* WebRegistrationScreen.swift */; };
@ -399,6 +397,7 @@
4E0D9E09B52CEC4C0E6211A8 /* MediaPickerScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F49FB9EE2913234F06CE68 /* MediaPickerScreenCoordinator.swift */; }; 4E0D9E09B52CEC4C0E6211A8 /* MediaPickerScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F49FB9EE2913234F06CE68 /* MediaPickerScreenCoordinator.swift */; };
4E22086585CB3B35FEEFBBB9 /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA991289149D31F4286747 /* UserPreference.swift */; }; 4E22086585CB3B35FEEFBBB9 /* UserPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA991289149D31F4286747 /* UserPreference.swift */; };
4E36A66E0EDA74BF3A036FD0 /* RoomChangeRolesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */; }; 4E36A66E0EDA74BF3A036FD0 /* RoomChangeRolesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */; };
4E4EF97B9F9CEFAC726BA72F /* TimelineProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62EACAFB3F3E017060F9F1C5 /* TimelineProviderMock.swift */; };
4E8A2A2CFEB212F14E49E1A1 /* AppLockSetupSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */; }; 4E8A2A2CFEB212F14E49E1A1 /* AppLockSetupSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5484457C81B325660901B161 /* AppLockSetupSettingsScreen.swift */; };
4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */; }; 4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B2A8426404EF66F00CFDB /* RoomTimelineItemFactory.swift */; };
4EA1CE0E88EA68E862FF0EA2 /* NotificationSettingsEditScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B564D748B67A156F413CD97 /* NotificationSettingsEditScreenModels.swift */; }; 4EA1CE0E88EA68E862FF0EA2 /* NotificationSettingsEditScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B564D748B67A156F413CD97 /* NotificationSettingsEditScreenModels.swift */; };
@ -418,6 +417,7 @@
51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */; }; 51B3B19FA5F91B455C807BA7 /* RoomPollsHistoryScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E964AF2DFEB31E2B799999F /* RoomPollsHistoryScreenModels.swift */; };
523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */; }; 523C6800ED85D5810CF18C19 /* OIDCAccountSettingsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D737F4672021D0A7D218CD /* OIDCAccountSettingsPresenter.swift */; };
52473A4D7B1FBD4CD1E770C8 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; }; 52473A4D7B1FBD4CD1E770C8 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
530C2238E40F71223327FC95 /* MockTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BA8082E26C77A2C587B34B3 /* MockTimelineController.swift */; };
5341D48F833E3E30F16FA2A3 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2910422CB628D3B2BBE47449 /* SeparatorRoomTimelineView.swift */; }; 5341D48F833E3E30F16FA2A3 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2910422CB628D3B2BBE47449 /* SeparatorRoomTimelineView.swift */; };
5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; }; 5375902175B2FEA2949D7D74 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */; };
53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */; }; 53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */; };
@ -470,6 +470,7 @@
5DB4334CBBA142376FF5FFEC /* preview_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 200626E8353AB2729444F991 /* preview_image.jpg */; }; 5DB4334CBBA142376FF5FFEC /* preview_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 200626E8353AB2729444F991 /* preview_image.jpg */; };
5DD0EF30070DC0A82C5CCD33 /* RoomMembersListManageMemberSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC853F9B4FBE039D2C16EC6B /* RoomMembersListManageMemberSheet.swift */; }; 5DD0EF30070DC0A82C5CCD33 /* RoomMembersListManageMemberSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC853F9B4FBE039D2C16EC6B /* RoomMembersListManageMemberSheet.swift */; };
5DD85A0FE3D85AEC3C7EFE36 /* DeveloperOptionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */; }; 5DD85A0FE3D85AEC3C7EFE36 /* DeveloperOptionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */; };
5EC046E41755C095DAB1C3FF /* TimelineProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8C9BBB729C941BEE0E2A63 /* TimelineProviderProtocol.swift */; };
5EDBDE802761B5ECB54E6787 /* LogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2711E5996016ABD6EAAEB58A /* LogLevel.swift */; }; 5EDBDE802761B5ECB54E6787 /* LogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2711E5996016ABD6EAAEB58A /* LogLevel.swift */; };
5EE1D4E316D66943E97FDCF2 /* BloomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BEB970F500BFB248443FA1 /* BloomView.swift */; }; 5EE1D4E316D66943E97FDCF2 /* BloomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BEB970F500BFB248443FA1 /* BloomView.swift */; };
5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; }; 5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; };
@ -497,6 +498,7 @@
6386EA3C898AD1A4BC1DC8A5 /* TimelineMediaPreviewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FD40B92FCF20165658296AD /* TimelineMediaPreviewModifier.swift */; }; 6386EA3C898AD1A4BC1DC8A5 /* TimelineMediaPreviewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FD40B92FCF20165658296AD /* TimelineMediaPreviewModifier.swift */; };
63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */; }; 63CDC201A5980F304F6D0A1C /* WaveformInteractionModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEE91FB8ABB5F5884B6D940 /* WaveformInteractionModifier.swift */; };
63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */; }; 63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */; };
63FD7DBE7BBA149B4B8B99D7 /* TimelineControllerFactoryMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F5CC38803B8382D2C63222 /* TimelineControllerFactoryMock.swift */; };
642DF13C49ED4121C148230E /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E227F34BE43B08E098796E /* TestablePreview.swift */; }; 642DF13C49ED4121C148230E /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E227F34BE43B08E098796E /* TestablePreview.swift */; };
6448F8D1D3CA4CD27BB4CADD /* RoomMemberProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */; }; 6448F8D1D3CA4CD27BB4CADD /* RoomMemberProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */; };
64AB99285DC4437C0DDE9585 /* MenuSheetLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49ABAB186CF00B15C5521D04 /* MenuSheetLabelStyle.swift */; }; 64AB99285DC4437C0DDE9585 /* MenuSheetLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49ABAB186CF00B15C5521D04 /* MenuSheetLabelStyle.swift */; };
@ -600,7 +602,6 @@
77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */; }; 77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */; };
77BB228AEA861E50FFD6A228 /* HomeScreenEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */; }; 77BB228AEA861E50FFD6A228 /* HomeScreenEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0FEA560929DD73FFEF8C3DF /* HomeScreenEmptyStateView.swift */; };
77C1A2F49CD90D3EFDF376E5 /* MapTilerURLBuildersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */; }; 77C1A2F49CD90D3EFDF376E5 /* MapTilerURLBuildersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */; };
77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */; };
77E33FF0E4A50B555BF3A8AA /* AudioFileEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC9044BE0E4A66F5B963E834 /* AudioFileEventsTimelineView.swift */; }; 77E33FF0E4A50B555BF3A8AA /* AudioFileEventsTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC9044BE0E4A66F5B963E834 /* AudioFileEventsTimelineView.swift */; };
77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */; }; 77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */; };
77FB08C303F4C74C0E8577E2 /* TimelineMediaPreviewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2BB38DF61F5100B8723112 /* TimelineMediaPreviewModels.swift */; }; 77FB08C303F4C74C0E8577E2 /* TimelineMediaPreviewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2BB38DF61F5100B8723112 /* TimelineMediaPreviewModels.swift */; };
@ -638,10 +639,10 @@
7D261B5119E78CC8E771CA15 /* GlobalSearchScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */; }; 7D261B5119E78CC8E771CA15 /* GlobalSearchScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74653BE903970C0E36867D46 /* GlobalSearchScreenCoordinator.swift */; };
7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */; }; 7D58B4F46CAA9A7C3E4C6A30 /* UserDetailsEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88410BD213FDF9B28E8B671F /* UserDetailsEditScreen.swift */; };
7D6DC832DE7A3DE874E2E9BC /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = BB111AE9D390233CDD2C7FD5 /* MatrixRustSDK */; }; 7D6DC832DE7A3DE874E2E9BC /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = BB111AE9D390233CDD2C7FD5 /* MatrixRustSDK */; };
7DCFC31B49BDD2BC32184E58 /* TimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C0D5AE752AF87DA0A920812 /* TimelineControllerFactory.swift */; };
7E2BB42805C59DB57E95610F /* PillView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7773CBFDBD458E0B7E270507 /* PillView.swift */; }; 7E2BB42805C59DB57E95610F /* PillView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7773CBFDBD458E0B7E270507 /* PillView.swift */; };
7E43FBB918AAC136034F2758 /* test_image.png in Resources */ = {isa = PBXBuildFile; fileRef = 810133CF215075C285FC6F3A /* test_image.png */; }; 7E43FBB918AAC136034F2758 /* test_image.png in Resources */ = {isa = PBXBuildFile; fileRef = 810133CF215075C285FC6F3A /* test_image.png */; };
7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; }; 7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; };
7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */; };
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; }; 7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; };
7F7EA51A9A43125A8CB6AC90 /* NotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */; }; 7F7EA51A9A43125A8CB6AC90 /* NotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */; };
7F825CBD857D65DC986087BA /* NoticeRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F54FA7C5CB7B342EF9B9B2F /* NoticeRoomTimelineView.swift */; }; 7F825CBD857D65DC986087BA /* NoticeRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F54FA7C5CB7B342EF9B9B2F /* NoticeRoomTimelineView.swift */; };
@ -788,7 +789,6 @@
9B356742E035D90A8BB5CABE /* ProposedViewSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DFE0E493FB55E5A62E7852A /* ProposedViewSize.swift */; }; 9B356742E035D90A8BB5CABE /* ProposedViewSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DFE0E493FB55E5A62E7852A /* ProposedViewSize.swift */; };
9B872FF37DBE6BE054903831 /* MediaUploadPreviewScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */; }; 9B872FF37DBE6BE054903831 /* MediaUploadPreviewScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54E12B98252F6C527E31FEE /* MediaUploadPreviewScreenViewModelProtocol.swift */; };
9BB91CABB10D8FE90C491BCD /* StaticLocationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */; }; 9BB91CABB10D8FE90C491BCD /* StaticLocationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C833673B334A0651AB46F30B /* StaticLocationScreenViewModelTests.swift */; };
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */; }; 9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */; };
9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */; }; 9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */; };
9C63171267E22FEB288EC860 /* RoomHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1627F2D56477BD331F6D732C /* RoomHeaderView.swift */; }; 9C63171267E22FEB288EC860 /* RoomHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1627F2D56477BD331F6D732C /* RoomHeaderView.swift */; };
@ -896,13 +896,12 @@
B20484642B41C2D76238BAAA /* test_animated_image.gif in Resources */ = {isa = PBXBuildFile; fileRef = 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */; }; B20484642B41C2D76238BAAA /* test_animated_image.gif in Resources */ = {isa = PBXBuildFile; fileRef = 53FD6D3D38F556CEAA280C58 /* test_animated_image.gif */; };
B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */; }; B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */; };
B245583C63F8F90357B87FAE /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = A2AE110B053B55E38F8D10C7 /* KZFileWatchers */; }; B245583C63F8F90357B87FAE /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = A2AE110B053B55E38F8D10C7 /* KZFileWatchers */; };
B272E5D1DE8BDA87A6B7A696 /* RoomTimelineProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */; };
B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */; }; B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */; };
B2FDF69AC0C316F12142F91A /* RoomMembershipDetailsProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12B09A94C519227264A41208 /* RoomMembershipDetailsProxy.swift */; }; B2FDF69AC0C316F12142F91A /* RoomMembershipDetailsProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12B09A94C519227264A41208 /* RoomMembershipDetailsProxy.swift */; };
B31E5493C99381D4E204438B /* RoomTimelineControllerFactoryMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D479DF730528153665E5782E /* RoomTimelineControllerFactoryMock.swift */; };
B3D652AA1654270742072FB3 /* DeveloperOptionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86A6F283BC574FDB96ABBB07 /* DeveloperOptionsScreenViewModel.swift */; }; B3D652AA1654270742072FB3 /* DeveloperOptionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86A6F283BC574FDB96ABBB07 /* DeveloperOptionsScreenViewModel.swift */; };
B402708F8728DD0DB7C324E2 /* StartChatScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */; }; B402708F8728DD0DB7C324E2 /* StartChatScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78910787F967CBC6042A101E /* StartChatScreenViewModelProtocol.swift */; };
B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; }; B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; };
B47213F07A67CE3A8D49CEC9 /* TimelineControllerFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC1E3FE9B59EA094867863E /* TimelineControllerFactoryProtocol.swift */; };
B4A0C69370E6008A971463E7 /* BugReportScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */; }; B4A0C69370E6008A971463E7 /* BugReportScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */; };
B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; }; B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; };
B5321A1F5B26A0F3EC54909E /* CollapsibleFlowLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC5F5209279A752D98AAC4B2 /* CollapsibleFlowLayoutTests.swift */; }; B5321A1F5B26A0F3EC54909E /* CollapsibleFlowLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC5F5209279A752D98AAC4B2 /* CollapsibleFlowLayoutTests.swift */; };
@ -1078,6 +1077,7 @@
D97C782FE0005995C36FA04A /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */; }; D97C782FE0005995C36FA04A /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */; };
D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; }; D98B5EE8C4F5A2CE84687AE8 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; };
D9F80CE61BF8FF627FDB0543 /* LoadableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352359663A0E52BA20761EE /* LoadableImage.swift */; }; D9F80CE61BF8FF627FDB0543 /* LoadableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352359663A0E52BA20761EE /* LoadableImage.swift */; };
DA03B4F28C4D248EECE3429F /* TimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B248460BD1A3F20318137 /* TimelineProvider.swift */; };
DA10C99BA43A0F1E732F6274 /* LogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2711E5996016ABD6EAAEB58A /* LogLevel.swift */; }; DA10C99BA43A0F1E732F6274 /* LogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2711E5996016ABD6EAAEB58A /* LogLevel.swift */; };
DA7E867F5EAFF8E20B2EE3B6 /* SecureBackupScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3D16709ADD4F4BCC710B1E /* SecureBackupScreenModels.swift */; }; DA7E867F5EAFF8E20B2EE3B6 /* SecureBackupScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3D16709ADD4F4BCC710B1E /* SecureBackupScreenModels.swift */; };
DAF63A9CF9932CA8F6830F11 /* ShareExtensionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */; }; DAF63A9CF9932CA8F6830F11 /* ShareExtensionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */; };
@ -1140,7 +1140,6 @@
E79D79CDAFE8BEBCC3AECA54 /* AppLockScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */; }; E79D79CDAFE8BEBCC3AECA54 /* AppLockScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */; };
E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E543072DE58E751F028998 /* TimelineProxy.swift */; }; E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E543072DE58E751F028998 /* TimelineProxy.swift */; };
E84ADFE9696936C18C2424B5 /* SecureBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */; }; E84ADFE9696936C18C2424B5 /* SecureBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */; };
E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */; };
E8B290CBB7E5FF5E3C1B6124 /* KnockRequestsListEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 627A8B5E798CC778C363655E /* KnockRequestsListEmptyStateView.swift */; }; E8B290CBB7E5FF5E3C1B6124 /* KnockRequestsListEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 627A8B5E798CC778C363655E /* KnockRequestsListEmptyStateView.swift */; };
E8C65C19F7C40EE545172DD6 /* RoomScreenFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4137900E28201C314C835C11 /* RoomScreenFooterView.swift */; }; E8C65C19F7C40EE545172DD6 /* RoomScreenFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4137900E28201C314C835C11 /* RoomScreenFooterView.swift */; };
E9347F56CF0683208F4D9249 /* RoomNotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A9B5225D0881CEFA2CF7C9 /* RoomNotificationSettingsScreenViewModel.swift */; }; E9347F56CF0683208F4D9249 /* RoomNotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A9B5225D0881CEFA2CF7C9 /* RoomNotificationSettingsScreenViewModel.swift */; };
@ -1234,6 +1233,7 @@
F99FB21EFC6D99D247FE7CBE /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = DE8DC9B3FBA402117DC4C49F /* Kingfisher */; }; F99FB21EFC6D99D247FE7CBE /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = DE8DC9B3FBA402117DC4C49F /* Kingfisher */; };
F9EA79092C18A8CFE4922DD2 /* PollFormScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */; }; F9EA79092C18A8CFE4922DD2 /* PollFormScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */; };
FA2BBAE9FC5E2E9F960C0980 /* NavigationCoordinators.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F28602AC7AC881AED37EBA /* NavigationCoordinators.swift */; }; FA2BBAE9FC5E2E9F960C0980 /* NavigationCoordinators.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F28602AC7AC881AED37EBA /* NavigationCoordinators.swift */; };
FA53FA227FFBE469AFF32F71 /* TimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6C585CE1F721A2770C70D47 /* TimelineControllerProtocol.swift */; };
FA5A7E32B1920FCB4EEDC1BA /* RoomDetailsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */; }; FA5A7E32B1920FCB4EEDC1BA /* RoomDetailsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6493AC9979CEB1410302BFE3 /* RoomDetailsScreenCoordinator.swift */; };
FA71CD334F2D2289BEF0D749 /* SecureBackupRecoveryKeyScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2FCA3D0F239B9E911B966B /* SecureBackupRecoveryKeyScreen.swift */; }; FA71CD334F2D2289BEF0D749 /* SecureBackupRecoveryKeyScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2FCA3D0F239B9E911B966B /* SecureBackupRecoveryKeyScreen.swift */; };
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; }; FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; };
@ -1388,7 +1388,6 @@
0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsFlowCoordinator.swift; sourceTree = "<group>"; }; 0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomRolesAndPermissionsFlowCoordinator.swift; sourceTree = "<group>"; };
086B997409328F091EBA43CE /* RoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenUITests.swift; sourceTree = "<group>"; }; 086B997409328F091EBA43CE /* RoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenUITests.swift; sourceTree = "<group>"; };
086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentViewModelTests.swift; sourceTree = "<group>"; }; 086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentViewModelTests.swift; sourceTree = "<group>"; };
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = "<group>"; };
099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = "<group>"; }; 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderTests.swift; sourceTree = "<group>"; };
0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; }; 0A3E77399BD262D301451BF2 /* RoomDetailsEditScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenCoordinator.swift; sourceTree = "<group>"; };
0A459AE4B6566B2FA99E86B2 /* TimelineItemBubbledStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbledStylerView.swift; sourceTree = "<group>"; }; 0A459AE4B6566B2FA99E86B2 /* TimelineItemBubbledStylerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemBubbledStylerView.swift; sourceTree = "<group>"; };
@ -1452,7 +1451,6 @@
18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenModels.swift; sourceTree = "<group>"; }; 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenModels.swift; sourceTree = "<group>"; };
184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; }; 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; };
18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; }; 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; };
18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryProtocol.swift; sourceTree = "<group>"; };
190EC7285D3CFEF0D3011BCF /* GeoURI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURI.swift; sourceTree = "<group>"; }; 190EC7285D3CFEF0D3011BCF /* GeoURI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoURI.swift; sourceTree = "<group>"; };
196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenTrackerViewModifier.swift; sourceTree = "<group>"; }; 196004E7695FBA292A7944AF /* ScreenTrackerViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenTrackerViewModifier.swift; sourceTree = "<group>"; };
1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLoaderProtocol.swift; sourceTree = "<group>"; }; 1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLoaderProtocol.swift; sourceTree = "<group>"; };
@ -1470,6 +1468,7 @@
1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxyProtocol.swift; sourceTree = "<group>"; }; 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxyProtocol.swift; sourceTree = "<group>"; };
1B9D191A81FFB0C72CE73E77 /* RoomSelectionScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreenModels.swift; sourceTree = "<group>"; }; 1B9D191A81FFB0C72CE73E77 /* RoomSelectionScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreenModels.swift; sourceTree = "<group>"; };
1BA5A62DA4B543827FF82354 /* LAContextMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LAContextMock.swift; sourceTree = "<group>"; }; 1BA5A62DA4B543827FF82354 /* LAContextMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LAContextMock.swift; sourceTree = "<group>"; };
1BA8082E26C77A2C587B34B3 /* MockTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTimelineController.swift; sourceTree = "<group>"; };
1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupControllerProtocol.swift; sourceTree = "<group>"; }; 1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupControllerProtocol.swift; sourceTree = "<group>"; };
1C25B6EBEB414431187D73B7 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = "<group>"; }; 1C25B6EBEB414431187D73B7 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = "<group>"; };
1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlankFormCoordinator.swift; sourceTree = "<group>"; }; 1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlankFormCoordinator.swift; sourceTree = "<group>"; };
@ -1563,7 +1562,6 @@
2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenModels.swift; sourceTree = "<group>"; }; 2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenModels.swift; sourceTree = "<group>"; };
2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerState.swift; sourceTree = "<group>"; }; 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerState.swift; sourceTree = "<group>"; };
2BFDCA5A09EE70BC17F2EFA7 /* URLComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponents.swift; sourceTree = "<group>"; }; 2BFDCA5A09EE70BC17F2EFA7 /* URLComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponents.swift; sourceTree = "<group>"; };
2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerProtocol.swift; sourceTree = "<group>"; };
2C39D91A31409775B0F4268F /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 2C39D91A31409775B0F4268F /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/InfoPlist.strings; sourceTree = "<group>"; };
2CEBCB9676FCD1D0F13188DD /* StringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = "<group>"; }; 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = "<group>"; };
2CF9FE7E0CF9F40D1509E63A /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = bg; path = bg.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 2CF9FE7E0CF9F40D1509E63A /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = bg; path = bg.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
@ -1608,6 +1606,7 @@
35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = "<group>"; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = "<group>"; };
36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = "<group>"; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = "<group>"; };
371B248460BD1A3F20318137 /* TimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProvider.swift; sourceTree = "<group>"; };
376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = "<group>"; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = "<group>"; };
37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = "<group>"; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = "<group>"; };
37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringTests.swift; sourceTree = "<group>"; }; 37CA26F55123E36B50DB0B3A /* AttributedStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringTests.swift; sourceTree = "<group>"; };
@ -1748,7 +1747,6 @@
5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = "<group>"; }; 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = "<group>"; };
5281C5CDC4A712265A0B5FBF /* PollRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollRoomTimelineItem.swift; sourceTree = "<group>"; }; 5281C5CDC4A712265A0B5FBF /* PollRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollRoomTimelineItem.swift; sourceTree = "<group>"; };
52BD6ED18E2EB61E28C340AD /* AttributedString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedString.swift; sourceTree = "<group>"; }; 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedString.swift; sourceTree = "<group>"; };
52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = "<group>"; };
52F5EE5DE3B55D59299DB5BC /* AppLockSetupBiometricsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModelTests.swift; sourceTree = "<group>"; }; 52F5EE5DE3B55D59299DB5BC /* AppLockSetupBiometricsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupBiometricsScreenViewModelTests.swift; sourceTree = "<group>"; };
53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = "<group>"; }; 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = "<group>"; };
5351EBD7A0B9610548E4B7B2 /* EncryptedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedRoomTimelineItem.swift; sourceTree = "<group>"; }; 5351EBD7A0B9610548E4B7B2 /* EncryptedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedRoomTimelineItem.swift; sourceTree = "<group>"; };
@ -1813,6 +1811,7 @@
627A8B5E798CC778C363655E /* KnockRequestsListEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListEmptyStateView.swift; sourceTree = "<group>"; }; 627A8B5E798CC778C363655E /* KnockRequestsListEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListEmptyStateView.swift; sourceTree = "<group>"; };
62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderTests.swift; sourceTree = "<group>"; }; 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderTests.swift; sourceTree = "<group>"; };
62B07B296D7A9D2F09120853 /* OrderedSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSet.swift; sourceTree = "<group>"; }; 62B07B296D7A9D2F09120853 /* OrderedSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderedSet.swift; sourceTree = "<group>"; };
62EACAFB3F3E017060F9F1C5 /* TimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProviderMock.swift; sourceTree = "<group>"; };
638790D3F915F0909315C47A /* PollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollView.swift; sourceTree = "<group>"; }; 638790D3F915F0909315C47A /* PollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollView.swift; sourceTree = "<group>"; };
638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveQuickLook.swift; sourceTree = "<group>"; }; 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveQuickLook.swift; sourceTree = "<group>"; };
63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 63E8A1E8EE094F570573B6E8 /* RoomDetailsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
@ -1832,7 +1831,6 @@
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>"; };
66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPropertiesExt.swift; sourceTree = "<group>"; }; 66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPropertiesExt.swift; sourceTree = "<group>"; };
66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = test_audio.mp3; sourceTree = "<group>"; }; 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = test_audio.mp3; sourceTree = "<group>"; };
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
66F91544AC136BF6477BDAB8 /* TimelineDeliveryStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineDeliveryStatusView.swift; sourceTree = "<group>"; }; 66F91544AC136BF6477BDAB8 /* TimelineDeliveryStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineDeliveryStatusView.swift; sourceTree = "<group>"; };
671C338B7259DC5774816885 /* AuthenticationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceTests.swift; sourceTree = "<group>"; }; 671C338B7259DC5774816885 /* AuthenticationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceTests.swift; sourceTree = "<group>"; };
6722709BD6178E10B70C9641 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/SAS.strings; sourceTree = "<group>"; }; 6722709BD6178E10B70C9641 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/SAS.strings; sourceTree = "<group>"; };
@ -1907,6 +1905,7 @@
7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenCoordinator.swift; sourceTree = "<group>"; }; 7A03E073077D92AA19C43DCF /* IdentityConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreenCoordinator.swift; sourceTree = "<group>"; };
7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 7AAD8C633AA57948B34EDCF7 /* RoomChangeRolesScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModelProtocol.swift; sourceTree = "<group>"; };
7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientBuilderHook.swift; sourceTree = "<group>"; }; 7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientBuilderHook.swift; sourceTree = "<group>"; };
7AC1E3FE9B59EA094867863E /* TimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineControllerFactoryProtocol.swift; sourceTree = "<group>"; };
7AE094FCB6387D268C436161 /* SecureBackupScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenViewModel.swift; sourceTree = "<group>"; }; 7AE094FCB6387D268C436161 /* SecureBackupScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenViewModel.swift; sourceTree = "<group>"; };
7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModel.swift; sourceTree = "<group>"; }; 7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModel.swift; sourceTree = "<group>"; };
7AFD012C3A9F5EF276DDD4AA /* AnalyticsPromptScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 7AFD012C3A9F5EF276DDD4AA /* AnalyticsPromptScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModelProtocol.swift; sourceTree = "<group>"; };
@ -2001,6 +2000,7 @@
8BCCE3D12B0A9C6E559B5B5A /* EmojiProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderProtocol.swift; sourceTree = "<group>"; }; 8BCCE3D12B0A9C6E559B5B5A /* EmojiProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProviderProtocol.swift; sourceTree = "<group>"; };
8BD9C9A31D9AB3B6D8128E69 /* KnockRequestsListScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreenModels.swift; sourceTree = "<group>"; }; 8BD9C9A31D9AB3B6D8128E69 /* KnockRequestsListScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestsListScreenModels.swift; sourceTree = "<group>"; };
8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSharingScreenModels.swift; sourceTree = "<group>"; }; 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSharingScreenModels.swift; sourceTree = "<group>"; };
8C0D5AE752AF87DA0A920812 /* TimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineControllerFactory.swift; sourceTree = "<group>"; };
8C44BBC892499BE45B074F89 /* AppLockScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenCoordinator.swift; sourceTree = "<group>"; }; 8C44BBC892499BE45B074F89 /* AppLockScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenCoordinator.swift; sourceTree = "<group>"; };
8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItemContent.swift; sourceTree = "<group>"; }; 8C8616254EE40CA8BA5E9BC2 /* VideoRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItemContent.swift; sourceTree = "<group>"; };
8CC23C63849452BC86EA2852 /* ButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonStyle.swift; sourceTree = "<group>"; }; 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonStyle.swift; sourceTree = "<group>"; };
@ -2088,7 +2088,6 @@
9ECF11669EF253E98AA2977A /* CompletionSuggestionServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionServiceProtocol.swift; sourceTree = "<group>"; }; 9ECF11669EF253E98AA2977A /* CompletionSuggestionServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionServiceProtocol.swift; sourceTree = "<group>"; };
9F1DF3FFFE5ED2B8133F43A7 /* MessageComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposer.swift; sourceTree = "<group>"; }; 9F1DF3FFFE5ED2B8133F43A7 /* MessageComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposer.swift; sourceTree = "<group>"; };
9F40FB0A43DAECEC27C73722 /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/SAS.strings; sourceTree = "<group>"; }; 9F40FB0A43DAECEC27C73722 /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/SAS.strings; sourceTree = "<group>"; };
9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = "<group>"; };
9FD40B92FCF20165658296AD /* TimelineMediaPreviewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewModifier.swift; sourceTree = "<group>"; }; 9FD40B92FCF20165658296AD /* TimelineMediaPreviewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaPreviewModifier.swift; sourceTree = "<group>"; };
A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; }; A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; };
A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModel.swift; sourceTree = "<group>"; }; A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModel.swift; sourceTree = "<group>"; };
@ -2109,6 +2108,7 @@
A3FBD9C2B9A5479526920399 /* BugReportScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenCoordinator.swift; sourceTree = "<group>"; }; A3FBD9C2B9A5479526920399 /* BugReportScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenCoordinator.swift; sourceTree = "<group>"; };
A40C19719687984FD9478FBE /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; }; A40C19719687984FD9478FBE /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; };
A40F1985065500F0E7F61A27 /* PollFormScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModelProtocol.swift; sourceTree = "<group>"; }; A40F1985065500F0E7F61A27 /* PollFormScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModelProtocol.swift; sourceTree = "<group>"; };
A4216C12C0369A8AB059EDE9 /* TimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineController.swift; sourceTree = "<group>"; };
A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreen.swift; sourceTree = "<group>"; }; A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreen.swift; sourceTree = "<group>"; };
A436057DBEA1A23CA8CB1FD7 /* UIFont+AttributedStringBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+AttributedStringBuilder.h"; sourceTree = "<group>"; }; A436057DBEA1A23CA8CB1FD7 /* UIFont+AttributedStringBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+AttributedStringBuilder.h"; sourceTree = "<group>"; };
A443FAE2EE820A5790C35C8D /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = "<group>"; }; A443FAE2EE820A5790C35C8D /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -2174,6 +2174,7 @@
B0618820D26F9871A4BBB40E /* ComposerToolbarViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarViewModelProtocol.swift; sourceTree = "<group>"; }; B0618820D26F9871A4BBB40E /* ComposerToolbarViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarViewModelProtocol.swift; sourceTree = "<group>"; };
B0A307A44F952CD73E63AE31 /* RoomEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomEventStringBuilder.swift; sourceTree = "<group>"; }; B0A307A44F952CD73E63AE31 /* RoomEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomEventStringBuilder.swift; sourceTree = "<group>"; };
B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSettingsScreenViewModelTests.swift; sourceTree = "<group>"; }; B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
B0F5CC38803B8382D2C63222 /* TimelineControllerFactoryMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineControllerFactoryMock.swift; sourceTree = "<group>"; };
B14B1DE3E2D5D26732C49036 /* RoomChangeRolesScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModel.swift; sourceTree = "<group>"; }; B14B1DE3E2D5D26732C49036 /* RoomChangeRolesScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreenViewModel.swift; sourceTree = "<group>"; };
B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineItem.swift; sourceTree = "<group>"; }; B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineItem.swift; sourceTree = "<group>"; };
B172057567E049007A5C4D92 /* Strings+SAS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+SAS.swift"; sourceTree = "<group>"; }; B172057567E049007A5C4D92 /* Strings+SAS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+SAS.swift"; sourceTree = "<group>"; };
@ -2204,6 +2205,7 @@
B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = "<group>"; }; B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = "<group>"; };
B655A536341D2695158C6664 /* AuthenticationClientBuilderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilderFactory.swift; sourceTree = "<group>"; }; B655A536341D2695158C6664 /* AuthenticationClientBuilderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationClientBuilderFactory.swift; sourceTree = "<group>"; };
B6A293D06BAB2B7A17D9314B /* VoiceMessageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineView.swift; sourceTree = "<group>"; }; B6A293D06BAB2B7A17D9314B /* VoiceMessageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineView.swift; sourceTree = "<group>"; };
B6C585CE1F721A2770C70D47 /* TimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineControllerProtocol.swift; sourceTree = "<group>"; };
B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppHooks.swift; sourceTree = "<group>"; }; B6E4AB573FAEBB7B853DD04C /* AppHooks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppHooks.swift; sourceTree = "<group>"; };
B6E89E530A8E92EC44301CA1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; }; B6E89E530A8E92EC44301CA1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; };
B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomTests.swift; sourceTree = "<group>"; }; B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomTests.swift; sourceTree = "<group>"; };
@ -2345,7 +2347,6 @@
D3F219838588C62198E726E3 /* LABiometryType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LABiometryType.swift; sourceTree = "<group>"; }; D3F219838588C62198E726E3 /* LABiometryType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LABiometryType.swift; sourceTree = "<group>"; };
D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreen.swift; sourceTree = "<group>"; }; D3F275432954C8C6B1B7D966 /* AppLockSetupPINScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreen.swift; sourceTree = "<group>"; };
D45C9EAA86423D7D3126DE4F /* VoiceMessageRecorderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorderProtocol.swift; sourceTree = "<group>"; }; D45C9EAA86423D7D3126DE4F /* VoiceMessageRecorderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorderProtocol.swift; sourceTree = "<group>"; };
D479DF730528153665E5782E /* RoomTimelineControllerFactoryMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryMock.swift; sourceTree = "<group>"; };
D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceProxy.swift; sourceTree = "<group>"; }; D49B9785E3AD7D1C15A29F2F /* MediaSourceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceProxy.swift; sourceTree = "<group>"; };
D4DA544B2520BFA65D6DB4BB /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; }; D4DA544B2520BFA65D6DB4BB /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
D529B976F8B2AA654D923422 /* VoiceMessageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineItem.swift; sourceTree = "<group>"; }; D529B976F8B2AA654D923422 /* VoiceMessageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRoomTimelineItem.swift; sourceTree = "<group>"; };
@ -2383,6 +2384,7 @@
DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = "<group>"; }; DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = "<group>"; };
DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionModels.swift; sourceTree = "<group>"; }; DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionModels.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>"; };
DD8C9BBB729C941BEE0E2A63 /* TimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProviderProtocol.swift; sourceTree = "<group>"; };
DD955A0380C287C418F1A74D /* PhotoLibraryManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryManagerMock.swift; sourceTree = "<group>"; }; DD955A0380C287C418F1A74D /* PhotoLibraryManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryManagerMock.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>"; };
DE5127D6EA05B2E45D0A7D59 /* JoinRoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenViewModelTests.swift; sourceTree = "<group>"; }; DE5127D6EA05B2E45D0A7D59 /* JoinRoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenViewModelTests.swift; sourceTree = "<group>"; };
@ -2430,7 +2432,6 @@
E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenCoordinator.swift; sourceTree = "<group>"; }; E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenCoordinator.swift; sourceTree = "<group>"; };
E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineItem.swift; sourceTree = "<group>"; }; E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineItem.swift; sourceTree = "<group>"; };
E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxy.swift; sourceTree = "<group>"; }; E6F5D66F158A6662F953733E /* NotificationSettingsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsProxy.swift; sourceTree = "<group>"; };
E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactory.swift; sourceTree = "<group>"; };
E7495E1119753B06FF2C2279 /* PhotoLibraryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryManager.swift; sourceTree = "<group>"; }; E7495E1119753B06FF2C2279 /* PhotoLibraryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryManager.swift; sourceTree = "<group>"; };
E76A706B3EEA32B882DA5E2D /* BlockedUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModelProtocol.swift; sourceTree = "<group>"; }; E76A706B3EEA32B882DA5E2D /* BlockedUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModelProtocol.swift; sourceTree = "<group>"; };
E78FC546F28E045A560F2963 /* EncryptionKeyProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionKeyProviderProtocol.swift; sourceTree = "<group>"; }; E78FC546F28E045A560F2963 /* EncryptionKeyProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionKeyProviderProtocol.swift; sourceTree = "<group>"; };
@ -2509,7 +2510,6 @@
F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = "<group>"; }; F64A8582F65567AC38C2976A /* PollFormScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenViewModel.swift; sourceTree = "<group>"; };
F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = "<group>"; }; F72EFC8C634469F9262659C7 /* NSItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSItemProvider.swift; sourceTree = "<group>"; };
F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = "<group>"; }; F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = "<group>"; };
F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderMock.swift; sourceTree = "<group>"; };
F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreen.swift; sourceTree = "<group>"; }; F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreen.swift; sourceTree = "<group>"; };
F7C161B06F417CA5D1F1E088 /* WebRegistrationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRegistrationScreenModels.swift; sourceTree = "<group>"; }; F7C161B06F417CA5D1F1E088 /* WebRegistrationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRegistrationScreenModels.swift; sourceTree = "<group>"; };
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = "<group>"; }; F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = "<group>"; };
@ -3137,11 +3137,11 @@
2F2FED77226A43559F009463 /* TimelineController */ = { 2F2FED77226A43559F009463 /* TimelineController */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */, 1BA8082E26C77A2C587B34B3 /* MockTimelineController.swift */,
9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */, A4216C12C0369A8AB059EDE9 /* TimelineController.swift */,
E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */, 8C0D5AE752AF87DA0A920812 /* TimelineControllerFactory.swift */,
18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */, 7AC1E3FE9B59EA094867863E /* TimelineControllerFactoryProtocol.swift */,
2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */, B6C585CE1F721A2770C70D47 /* TimelineControllerProtocol.swift */,
); );
path = TimelineController; path = TimelineController;
sourceTree = "<group>"; sourceTree = "<group>";
@ -3205,10 +3205,10 @@
F5D1BAA90F3A073D91B4F16B /* RoomNotificationSettingsProxyMock.swift */, F5D1BAA90F3A073D91B4F16B /* RoomNotificationSettingsProxyMock.swift */,
6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */, 6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */,
FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */, FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */,
D479DF730528153665E5782E /* RoomTimelineControllerFactoryMock.swift */,
F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */,
4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */, 4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */,
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */, 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */,
B0F5CC38803B8382D2C63222 /* TimelineControllerFactoryMock.swift */,
62EACAFB3F3E017060F9F1C5 /* TimelineProviderMock.swift */,
17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */, 17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */,
7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */, 7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */,
AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */, AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */,
@ -5936,11 +5936,11 @@
children = ( children = (
190EC7285D3CFEF0D3011BCF /* GeoURI.swift */, 190EC7285D3CFEF0D3011BCF /* GeoURI.swift */,
0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */, 0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */,
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */,
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */,
E48C91C8BE55CAE1A3DBC3BC /* TimelineItemIdentifier.swift */, E48C91C8BE55CAE1A3DBC3BC /* TimelineItemIdentifier.swift */,
2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */, 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */,
55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */, 55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */,
371B248460BD1A3F20318137 /* TimelineProvider.swift */,
DD8C9BBB729C941BEE0E2A63 /* TimelineProviderProtocol.swift */,
F9E543072DE58E751F028998 /* TimelineProxy.swift */, F9E543072DE58E751F028998 /* TimelineProxy.swift */,
B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */, B50F03079F6B5EF9CA005F14 /* TimelineProxyProtocol.swift */,
3EA31CC7012EA2A5653DAFC9 /* Fixtures */, 3EA31CC7012EA2A5653DAFC9 /* Fixtures */,
@ -7192,8 +7192,8 @@
F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */, F54E2D6CAD96E1AC15BC526F /* MessageForwardingScreenViewModel.swift in Sources */,
C13128AAA787A4C2CBE4EE82 /* MessageForwardingScreenViewModelProtocol.swift in Sources */, C13128AAA787A4C2CBE4EE82 /* MessageForwardingScreenViewModelProtocol.swift in Sources */,
C97325EFDCCEE457432A9E82 /* MessageText.swift in Sources */, C97325EFDCCEE457432A9E82 /* MessageText.swift in Sources */,
09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */,
AF2ABA2794E376B64104C964 /* MockSoftLogoutScreenState.swift in Sources */, AF2ABA2794E376B64104C964 /* MockSoftLogoutScreenState.swift in Sources */,
530C2238E40F71223327FC95 /* MockTimelineController.swift in Sources */,
F9842667B68DC6FA1F9ECCBB /* NSItemProvider.swift in Sources */, F9842667B68DC6FA1F9ECCBB /* NSItemProvider.swift in Sources */,
EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */, EA01A06EEDFEF4AE7652E5F3 /* NSRegularExpresion.swift in Sources */,
FA2BBAE9FC5E2E9F960C0980 /* NavigationCoordinators.swift in Sources */, FA2BBAE9FC5E2E9F960C0980 /* NavigationCoordinators.swift in Sources */,
@ -7419,11 +7419,6 @@
983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */, 983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */,
B5899F18AD6C56CE08FE532B /* RoomSummaryProviderMock.swift in Sources */, B5899F18AD6C56CE08FE532B /* RoomSummaryProviderMock.swift in Sources */,
AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */, AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */,
2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */,
38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */,
B31E5493C99381D4E204438B /* RoomTimelineControllerFactoryMock.swift in Sources */,
7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */,
E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */,
4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */, 4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */,
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */, 13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */,
70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */, 70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */,
@ -7431,9 +7426,6 @@
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */, 1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */,
AD55E245FE686D7DB4C86406 /* RoomTimelineItemView.swift in Sources */, AD55E245FE686D7DB4C86406 /* RoomTimelineItemView.swift in Sources */,
41CE5E1289C8768FC5B6490C /* RoomTimelineItemViewState.swift in Sources */, 41CE5E1289C8768FC5B6490C /* RoomTimelineItemViewState.swift in Sources */,
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */,
B272E5D1DE8BDA87A6B7A696 /* RoomTimelineProviderMock.swift in Sources */,
77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */,
B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */, B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */,
D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */, D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */,
88CBF1595E39CE697928DE48 /* SFNumberedListView.swift in Sources */, 88CBF1595E39CE697928DE48 /* SFNumberedListView.swift in Sources */,
@ -7548,6 +7540,11 @@
D8CFA0EE46376F9FF04EEE45 /* TextRoomTimelineView.swift in Sources */, D8CFA0EE46376F9FF04EEE45 /* TextRoomTimelineView.swift in Sources */,
71643093F87153F633A1B025 /* ThreadDecorator.swift in Sources */, 71643093F87153F633A1B025 /* ThreadDecorator.swift in Sources */,
2AED12987603157C32C2114D /* TimelineBubbleLayout.swift in Sources */, 2AED12987603157C32C2114D /* TimelineBubbleLayout.swift in Sources */,
2BFA4C6D5B3D327B02C66AB0 /* TimelineController.swift in Sources */,
7DCFC31B49BDD2BC32184E58 /* TimelineControllerFactory.swift in Sources */,
63FD7DBE7BBA149B4B8B99D7 /* TimelineControllerFactoryMock.swift in Sources */,
B47213F07A67CE3A8D49CEC9 /* TimelineControllerFactoryProtocol.swift in Sources */,
FA53FA227FFBE469AFF32F71 /* TimelineControllerProtocol.swift in Sources */,
798BF3072137833FBD3F4C96 /* TimelineDeliveryStatusView.swift in Sources */, 798BF3072137833FBD3F4C96 /* TimelineDeliveryStatusView.swift in Sources */,
109AEB7D33C4497727AFB87F /* TimelineInteractionHandler.swift in Sources */, 109AEB7D33C4497727AFB87F /* TimelineInteractionHandler.swift in Sources */,
E6FA87F773424B27614B23E9 /* TimelineItemAccessibilityModifier.swift in Sources */, E6FA87F773424B27614B23E9 /* TimelineItemAccessibilityModifier.swift in Sources */,
@ -7574,6 +7571,9 @@
A32384E3D85CA65342D3A908 /* TimelineMediaPreviewRedactConfirmationView.swift in Sources */, A32384E3D85CA65342D3A908 /* TimelineMediaPreviewRedactConfirmationView.swift in Sources */,
86769B62BAE17601B3AE1B60 /* TimelineMediaPreviewViewModel.swift in Sources */, 86769B62BAE17601B3AE1B60 /* TimelineMediaPreviewViewModel.swift in Sources */,
B818580464CFB5400A3EF6AE /* TimelineModels.swift in Sources */, B818580464CFB5400A3EF6AE /* TimelineModels.swift in Sources */,
DA03B4F28C4D248EECE3429F /* TimelineProvider.swift in Sources */,
4E4EF97B9F9CEFAC726BA72F /* TimelineProviderMock.swift in Sources */,
5EC046E41755C095DAB1C3FF /* TimelineProviderProtocol.swift in Sources */,
E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */, E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */,
16A1F6C703305FCAF4E14EC6 /* TimelineProxyMock.swift in Sources */, 16A1F6C703305FCAF4E14EC6 /* TimelineProxyMock.swift in Sources */,
2FEC6652055984389CE1BBEC /* TimelineProxyProtocol.swift in Sources */, 2FEC6652055984389CE1BBEC /* TimelineProxyProtocol.swift in Sources */,

View File

@ -534,7 +534,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
appLockService: appLockFlowCoordinator.appLockService, appLockService: appLockFlowCoordinator.appLockService,
bugReportService: ServiceLocator.shared.bugReportService, bugReportService: ServiceLocator.shared.bugReportService,
elementCallService: elementCallService, elementCallService: elementCallService,
roomTimelineControllerFactory: RoomTimelineControllerFactory(), timelineControllerFactory: TimelineControllerFactory(),
appMediator: appMediator, appMediator: appMediator,
appSettings: appSettings, appSettings: appSettings,
appHooks: appHooks, appHooks: appHooks,

View File

@ -16,7 +16,7 @@ enum MediaEventsTimelineFlowCoordinatorAction {
class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol { class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
private let navigationStackCoordinator: NavigationStackCoordinator private let navigationStackCoordinator: NavigationStackCoordinator
private let userSession: UserSessionProtocol private let userSession: UserSessionProtocol
private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol private let timelineControllerFactory: TimelineControllerFactoryProtocol
private let roomProxy: JoinedRoomProxyProtocol private let roomProxy: JoinedRoomProxyProtocol
private let userIndicatorController: UserIndicatorControllerProtocol private let userIndicatorController: UserIndicatorControllerProtocol
private let appMediator: AppMediatorProtocol private let appMediator: AppMediatorProtocol
@ -31,14 +31,14 @@ class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
init(navigationStackCoordinator: NavigationStackCoordinator, init(navigationStackCoordinator: NavigationStackCoordinator,
userSession: UserSessionProtocol, userSession: UserSessionProtocol,
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol, timelineControllerFactory: TimelineControllerFactoryProtocol,
roomProxy: JoinedRoomProxyProtocol, roomProxy: JoinedRoomProxyProtocol,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
appMediator: AppMediatorProtocol, appMediator: AppMediatorProtocol,
emojiProvider: EmojiProviderProtocol) { emojiProvider: EmojiProviderProtocol) {
self.navigationStackCoordinator = navigationStackCoordinator self.navigationStackCoordinator = navigationStackCoordinator
self.userSession = userSession self.userSession = userSession
self.roomTimelineControllerFactory = roomTimelineControllerFactory self.timelineControllerFactory = timelineControllerFactory
self.roomProxy = roomProxy self.roomProxy = roomProxy
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.appMediator = appMediator self.appMediator = appMediator
@ -64,18 +64,20 @@ class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userSession.clientProxy.userID)) stateEventStringBuilder: RoomStateEventStringBuilder(userID: userSession.clientProxy.userID))
guard case let .success(mediaTimelineController) = await roomTimelineControllerFactory.buildMessageFilteredRoomTimelineController(allowedMessageTypes: [.image, .video], guard case let .success(mediaTimelineController) = await timelineControllerFactory.buildMessageFilteredTimelineController(allowedMessageTypes: [.image, .video],
roomProxy: roomProxy, presentation: .mediaFilesScreen,
timelineItemFactory: timelineItemFactory, roomProxy: roomProxy,
mediaProvider: userSession.mediaProvider) else { timelineItemFactory: timelineItemFactory,
mediaProvider: userSession.mediaProvider) else {
MXLog.error("Failed presenting media timeline") MXLog.error("Failed presenting media timeline")
return return
} }
guard case let .success(filesTimelineController) = await roomTimelineControllerFactory.buildMessageFilteredRoomTimelineController(allowedMessageTypes: [.file, .audio], guard case let .success(filesTimelineController) = await timelineControllerFactory.buildMessageFilteredTimelineController(allowedMessageTypes: [.file, .audio],
roomProxy: roomProxy, presentation: .mediaFilesScreen,
timelineItemFactory: timelineItemFactory, roomProxy: roomProxy,
mediaProvider: userSession.mediaProvider) else { timelineItemFactory: timelineItemFactory,
mediaProvider: userSession.mediaProvider) else {
MXLog.error("Failed presenting media timeline") MXLog.error("Failed presenting media timeline")
return return
} }
@ -88,7 +90,8 @@ class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
voiceMessageMediaManager: userSession.voiceMessageMediaManager, voiceMessageMediaManager: userSession.voiceMessageMediaManager,
appMediator: appMediator, appMediator: appMediator,
emojiProvider: emojiProvider, emojiProvider: emojiProvider,
userIndicatorController: userIndicatorController) userIndicatorController: userIndicatorController,
timelineControllerFactory: timelineControllerFactory)
let coordinator = MediaEventsTimelineScreenCoordinator(parameters: parameters) let coordinator = MediaEventsTimelineScreenCoordinator(parameters: parameters)

View File

@ -18,7 +18,7 @@ enum PinnedEventsTimelineFlowCoordinatorAction {
class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol { class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
private let navigationStackCoordinator: NavigationStackCoordinator private let navigationStackCoordinator: NavigationStackCoordinator
private let userSession: UserSessionProtocol private let userSession: UserSessionProtocol
private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol private let timelineControllerFactory: TimelineControllerFactoryProtocol
private let roomProxy: JoinedRoomProxyProtocol private let roomProxy: JoinedRoomProxyProtocol
private let userIndicatorController: UserIndicatorControllerProtocol private let userIndicatorController: UserIndicatorControllerProtocol
private let appMediator: AppMediatorProtocol private let appMediator: AppMediatorProtocol
@ -33,14 +33,14 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
init(navigationStackCoordinator: NavigationStackCoordinator, init(navigationStackCoordinator: NavigationStackCoordinator,
userSession: UserSessionProtocol, userSession: UserSessionProtocol,
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol, timelineControllerFactory: TimelineControllerFactoryProtocol,
roomProxy: JoinedRoomProxyProtocol, roomProxy: JoinedRoomProxyProtocol,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
appMediator: AppMediatorProtocol, appMediator: AppMediatorProtocol,
emojiProvider: EmojiProviderProtocol) { emojiProvider: EmojiProviderProtocol) {
self.navigationStackCoordinator = navigationStackCoordinator self.navigationStackCoordinator = navigationStackCoordinator
self.userSession = userSession self.userSession = userSession
self.roomTimelineControllerFactory = roomTimelineControllerFactory self.timelineControllerFactory = timelineControllerFactory
self.roomProxy = roomProxy self.roomProxy = roomProxy
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.appMediator = appMediator self.appMediator = appMediator
@ -65,9 +65,9 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
guard let timelineController = await roomTimelineControllerFactory.buildPinnedEventsRoomTimelineController(roomProxy: roomProxy, guard let timelineController = await timelineControllerFactory.buildPinnedEventsTimelineController(roomProxy: roomProxy,
timelineItemFactory: timelineItemFactory, timelineItemFactory: timelineItemFactory,
mediaProvider: userSession.mediaProvider) else { mediaProvider: userSession.mediaProvider) else {
fatalError("This can never fail because we allow this view to be presented only when the timeline is fully loaded and not nil") fatalError("This can never fail because we allow this view to be presented only when the timeline is fully loaded and not nil")
} }
@ -77,7 +77,8 @@ class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
mediaPlayerProvider: MediaPlayerProvider(), mediaPlayerProvider: MediaPlayerProvider(),
voiceMessageMediaManager: userSession.voiceMessageMediaManager, voiceMessageMediaManager: userSession.voiceMessageMediaManager,
appMediator: appMediator, appMediator: appMediator,
emojiProvider: emojiProvider)) emojiProvider: emojiProvider,
timelineControllerFactory: timelineControllerFactory))
coordinator.actions coordinator.actions
.sink { [weak self] action in .sink { [weak self] action in

View File

@ -78,7 +78,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
private let roomID: String private let roomID: String
private let userSession: UserSessionProtocol private let userSession: UserSessionProtocol
private let isChildFlow: Bool private let isChildFlow: Bool
private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol private let timelineControllerFactory: TimelineControllerFactoryProtocol
private let navigationStackCoordinator: NavigationStackCoordinator private let navigationStackCoordinator: NavigationStackCoordinator
private let emojiProvider: EmojiProviderProtocol private let emojiProvider: EmojiProviderProtocol
private let ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never> private let ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never>
@ -110,12 +110,12 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
actionsSubject.eraseToAnyPublisher() actionsSubject.eraseToAnyPublisher()
} }
private var timelineController: RoomTimelineControllerProtocol? private var timelineController: TimelineControllerProtocol?
init(roomID: String, init(roomID: String,
userSession: UserSessionProtocol, userSession: UserSessionProtocol,
isChildFlow: Bool, isChildFlow: Bool,
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol, timelineControllerFactory: TimelineControllerFactoryProtocol,
navigationStackCoordinator: NavigationStackCoordinator, navigationStackCoordinator: NavigationStackCoordinator,
emojiProvider: EmojiProviderProtocol, emojiProvider: EmojiProviderProtocol,
ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never>, ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never>,
@ -126,7 +126,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
self.roomID = roomID self.roomID = roomID
self.userSession = userSession self.userSession = userSession
self.isChildFlow = isChildFlow self.isChildFlow = isChildFlow
self.roomTimelineControllerFactory = roomTimelineControllerFactory self.timelineControllerFactory = timelineControllerFactory
self.navigationStackCoordinator = navigationStackCoordinator self.navigationStackCoordinator = navigationStackCoordinator
self.emojiProvider = emojiProvider self.emojiProvider = emojiProvider
self.ongoingCallRoomIDPublisher = ongoingCallRoomIDPublisher self.ongoingCallRoomIDPublisher = ongoingCallRoomIDPublisher
@ -685,10 +685,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
let timelineItemFactory = RoomTimelineItemFactory(userID: userID, let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy, let timelineController = timelineControllerFactory.buildTimelineController(roomProxy: roomProxy,
initialFocussedEventID: presentationAction?.focusedEvent?.eventID, initialFocussedEventID: presentationAction?.focusedEvent?.eventID,
timelineItemFactory: timelineItemFactory, timelineItemFactory: timelineItemFactory,
mediaProvider: userSession.mediaProvider) mediaProvider: userSession.mediaProvider)
self.timelineController = timelineController self.timelineController = timelineController
let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy) let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy)
@ -707,7 +707,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher, ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher,
appMediator: appMediator, appMediator: appMediator,
appSettings: appSettings, appSettings: appSettings,
composerDraftService: composerDraftService) composerDraftService: composerDraftService,
timelineControllerFactory: timelineControllerFactory)
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
coordinator.actions coordinator.actions
@ -1202,13 +1203,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID)) stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
let roomTimelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy, let timelineController = timelineControllerFactory.buildTimelineController(roomProxy: roomProxy,
initialFocussedEventID: nil, initialFocussedEventID: nil,
timelineItemFactory: timelineItemFactory, timelineItemFactory: timelineItemFactory,
mediaProvider: userSession.mediaProvider) mediaProvider: userSession.mediaProvider)
let parameters = RoomPollsHistoryScreenCoordinatorParameters(pollInteractionHandler: PollInteractionHandler(analyticsService: analytics, roomProxy: roomProxy), let parameters = RoomPollsHistoryScreenCoordinatorParameters(pollInteractionHandler: PollInteractionHandler(analyticsService: analytics, roomProxy: roomProxy),
roomTimelineController: roomTimelineController) timelineController: timelineController)
let coordinator = RoomPollsHistoryScreenCoordinator(parameters: parameters) let coordinator = RoomPollsHistoryScreenCoordinator(parameters: parameters)
coordinator.actions coordinator.actions
.sink { [weak self] action in .sink { [weak self] action in
@ -1513,7 +1514,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
let coordinator = await RoomFlowCoordinator(roomID: roomID, let coordinator = await RoomFlowCoordinator(roomID: roomID,
userSession: userSession, userSession: userSession,
isChildFlow: true, isChildFlow: true,
roomTimelineControllerFactory: roomTimelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
navigationStackCoordinator: navigationStackCoordinator, navigationStackCoordinator: navigationStackCoordinator,
emojiProvider: emojiProvider, emojiProvider: emojiProvider,
ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher, ongoingCallRoomIDPublisher: ongoingCallRoomIDPublisher,
@ -1551,7 +1552,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
let flowCoordinator = PinnedEventsTimelineFlowCoordinator(navigationStackCoordinator: stackCoordinator, let flowCoordinator = PinnedEventsTimelineFlowCoordinator(navigationStackCoordinator: stackCoordinator,
userSession: userSession, userSession: userSession,
roomTimelineControllerFactory: roomTimelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
roomProxy: roomProxy, roomProxy: roomProxy,
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: appMediator, appMediator: appMediator,
@ -1590,7 +1591,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
private func startMediaEventsTimelineFlow() async { private func startMediaEventsTimelineFlow() async {
let flowCoordinator = MediaEventsTimelineFlowCoordinator(navigationStackCoordinator: navigationStackCoordinator, let flowCoordinator = MediaEventsTimelineFlowCoordinator(navigationStackCoordinator: navigationStackCoordinator,
userSession: userSession, userSession: userSession,
roomTimelineControllerFactory: roomTimelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
roomProxy: roomProxy, roomProxy: roomProxy,
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: appMediator, appMediator: appMediator,

View File

@ -34,7 +34,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
// periphery:ignore - retaining purpose // periphery:ignore - retaining purpose
private var roomFlowCoordinator: RoomFlowCoordinator? private var roomFlowCoordinator: RoomFlowCoordinator?
private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol private let timelineControllerFactory: TimelineControllerFactoryProtocol
private let settingsFlowCoordinator: SettingsFlowCoordinator private let settingsFlowCoordinator: SettingsFlowCoordinator
@ -69,7 +69,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
appLockService: AppLockServiceProtocol, appLockService: AppLockServiceProtocol,
bugReportService: BugReportServiceProtocol, bugReportService: BugReportServiceProtocol,
elementCallService: ElementCallServiceProtocol, elementCallService: ElementCallServiceProtocol,
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol, timelineControllerFactory: TimelineControllerFactoryProtocol,
appMediator: AppMediatorProtocol, appMediator: AppMediatorProtocol,
appSettings: AppSettings, appSettings: AppSettings,
appHooks: AppHooks, appHooks: AppHooks,
@ -81,7 +81,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
self.navigationRootCoordinator = navigationRootCoordinator self.navigationRootCoordinator = navigationRootCoordinator
self.bugReportService = bugReportService self.bugReportService = bugReportService
self.elementCallService = elementCallService self.elementCallService = elementCallService
self.roomTimelineControllerFactory = roomTimelineControllerFactory self.timelineControllerFactory = timelineControllerFactory
self.appMediator = appMediator self.appMediator = appMediator
self.appSettings = appSettings self.appSettings = appSettings
self.appHooks = appHooks self.appHooks = appHooks
@ -574,7 +574,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
let coordinator = await RoomFlowCoordinator(roomID: roomID, let coordinator = await RoomFlowCoordinator(roomID: roomID,
userSession: userSession, userSession: userSession,
isChildFlow: false, isChildFlow: false,
roomTimelineControllerFactory: roomTimelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
navigationStackCoordinator: detailNavigationStackCoordinator, navigationStackCoordinator: detailNavigationStackCoordinator,
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(appSettings: appSettings),
ongoingCallRoomIDPublisher: elementCallService.ongoingCallRoomIDPublisher, ongoingCallRoomIDPublisher: elementCallService.ongoingCallRoomIDPublisher,

View File

@ -6228,15 +6228,15 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
} }
//MARK: - messageFilteredTimeline //MARK: - messageFilteredTimeline
var messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount = 0 var messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingCallsCount = 0
var messageFilteredTimelineAllowedMessageTypesCallsCount: Int { var messageFilteredTimelineAllowedMessageTypesPresentationCallsCount: Int {
get { get {
if Thread.isMainThread { if Thread.isMainThread {
return messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount return messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingCallsCount
} else { } else {
var returnValue: Int? = nil var returnValue: Int? = nil
DispatchQueue.main.sync { DispatchQueue.main.sync {
returnValue = messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount returnValue = messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingCallsCount
} }
return returnValue! return returnValue!
@ -6244,29 +6244,29 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
} }
set { set {
if Thread.isMainThread { if Thread.isMainThread {
messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount = newValue messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingCallsCount = newValue
} else { } else {
DispatchQueue.main.sync { DispatchQueue.main.sync {
messageFilteredTimelineAllowedMessageTypesUnderlyingCallsCount = newValue messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingCallsCount = newValue
} }
} }
} }
} }
var messageFilteredTimelineAllowedMessageTypesCalled: Bool { var messageFilteredTimelineAllowedMessageTypesPresentationCalled: Bool {
return messageFilteredTimelineAllowedMessageTypesCallsCount > 0 return messageFilteredTimelineAllowedMessageTypesPresentationCallsCount > 0
} }
var messageFilteredTimelineAllowedMessageTypesReceivedAllowedMessageTypes: [RoomMessageEventMessageType]? var messageFilteredTimelineAllowedMessageTypesPresentationReceivedArguments: (allowedMessageTypes: [RoomMessageEventMessageType], presentation: TimelineKind.MediaPresentation)?
var messageFilteredTimelineAllowedMessageTypesReceivedInvocations: [[RoomMessageEventMessageType]] = [] var messageFilteredTimelineAllowedMessageTypesPresentationReceivedInvocations: [(allowedMessageTypes: [RoomMessageEventMessageType], presentation: TimelineKind.MediaPresentation)] = []
var messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue: Result<TimelineProxyProtocol, RoomProxyError>! var messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingReturnValue: Result<TimelineProxyProtocol, RoomProxyError>!
var messageFilteredTimelineAllowedMessageTypesReturnValue: Result<TimelineProxyProtocol, RoomProxyError>! { var messageFilteredTimelineAllowedMessageTypesPresentationReturnValue: Result<TimelineProxyProtocol, RoomProxyError>! {
get { get {
if Thread.isMainThread { if Thread.isMainThread {
return messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue return messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingReturnValue
} else { } else {
var returnValue: Result<TimelineProxyProtocol, RoomProxyError>? = nil var returnValue: Result<TimelineProxyProtocol, RoomProxyError>? = nil
DispatchQueue.main.sync { DispatchQueue.main.sync {
returnValue = messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue returnValue = messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingReturnValue
} }
return returnValue! return returnValue!
@ -6274,26 +6274,26 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
} }
set { set {
if Thread.isMainThread { if Thread.isMainThread {
messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue = newValue messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingReturnValue = newValue
} else { } else {
DispatchQueue.main.sync { DispatchQueue.main.sync {
messageFilteredTimelineAllowedMessageTypesUnderlyingReturnValue = newValue messageFilteredTimelineAllowedMessageTypesPresentationUnderlyingReturnValue = newValue
} }
} }
} }
} }
var messageFilteredTimelineAllowedMessageTypesClosure: (([RoomMessageEventMessageType]) async -> Result<TimelineProxyProtocol, RoomProxyError>)? var messageFilteredTimelineAllowedMessageTypesPresentationClosure: (([RoomMessageEventMessageType], TimelineKind.MediaPresentation) async -> Result<TimelineProxyProtocol, RoomProxyError>)?
func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType]) async -> Result<TimelineProxyProtocol, RoomProxyError> { func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType], presentation: TimelineKind.MediaPresentation) async -> Result<TimelineProxyProtocol, RoomProxyError> {
messageFilteredTimelineAllowedMessageTypesCallsCount += 1 messageFilteredTimelineAllowedMessageTypesPresentationCallsCount += 1
messageFilteredTimelineAllowedMessageTypesReceivedAllowedMessageTypes = allowedMessageTypes messageFilteredTimelineAllowedMessageTypesPresentationReceivedArguments = (allowedMessageTypes: allowedMessageTypes, presentation: presentation)
DispatchQueue.main.async { DispatchQueue.main.async {
self.messageFilteredTimelineAllowedMessageTypesReceivedInvocations.append(allowedMessageTypes) self.messageFilteredTimelineAllowedMessageTypesPresentationReceivedInvocations.append((allowedMessageTypes: allowedMessageTypes, presentation: presentation))
} }
if let messageFilteredTimelineAllowedMessageTypesClosure = messageFilteredTimelineAllowedMessageTypesClosure { if let messageFilteredTimelineAllowedMessageTypesPresentationClosure = messageFilteredTimelineAllowedMessageTypesPresentationClosure {
return await messageFilteredTimelineAllowedMessageTypesClosure(allowedMessageTypes) return await messageFilteredTimelineAllowedMessageTypesPresentationClosure(allowedMessageTypes, presentation)
} else { } else {
return messageFilteredTimelineAllowedMessageTypesReturnValue return messageFilteredTimelineAllowedMessageTypesPresentationReturnValue
} }
} }
//MARK: - enableEncryption //MARK: - enableEncryption
@ -13613,243 +13613,6 @@ class RoomSummaryProviderMock: RoomSummaryProviderProtocol, @unchecked Sendable
setFilterClosure?(filter) setFilterClosure?(filter)
} }
} }
class RoomTimelineControllerFactoryMock: RoomTimelineControllerFactoryProtocol, @unchecked Sendable {
//MARK: - buildRoomTimelineController
var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0
var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount: Int {
get {
if Thread.isMainThread {
return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
}
}
}
}
var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCalled: Bool {
return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount > 0
}
var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)?
var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = []
var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue: RoomTimelineControllerProtocol!
var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue: RoomTimelineControllerProtocol! {
get {
if Thread.isMainThread {
return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue
} else {
var returnValue: RoomTimelineControllerProtocol? = nil
DispatchQueue.main.sync {
returnValue = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
}
}
}
}
var buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, String?, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) -> RoomTimelineControllerProtocol)?
func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol {
buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount += 1
buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)
DispatchQueue.main.async {
self.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedInvocations.append((roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider))
}
if let buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure = buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure {
return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure(roomProxy, initialFocussedEventID, timelineItemFactory, mediaProvider)
} else {
return buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue
}
}
//MARK: - buildPinnedEventsRoomTimelineController
var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0
var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount: Int {
get {
if Thread.isMainThread {
return buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
}
}
}
}
var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCalled: Bool {
return buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount > 0
}
var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)?
var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = []
var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: RoomTimelineControllerProtocol?
var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue: RoomTimelineControllerProtocol? {
get {
if Thread.isMainThread {
return buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
} else {
var returnValue: RoomTimelineControllerProtocol?? = nil
DispatchQueue.main.sync {
returnValue = buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
}
}
}
}
var buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> RoomTimelineControllerProtocol?)?
func buildPinnedEventsRoomTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? {
buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1
buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)
DispatchQueue.main.async {
self.buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations.append((roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider))
}
if let buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure = buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure {
return await buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure(roomProxy, timelineItemFactory, mediaProvider)
} else {
return buildPinnedEventsRoomTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue
}
}
//MARK: - buildMessageFilteredRoomTimelineController
var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0
var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderCallsCount: Int {
get {
if Thread.isMainThread {
return buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
}
}
}
}
var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderCalled: Bool {
return buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderCallsCount > 0
}
var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (allowedMessageTypes: [RoomMessageEventMessageType], roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)?
var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(allowedMessageTypes: [RoomMessageEventMessageType], roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = []
var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: Result<RoomTimelineControllerProtocol, RoomTimelineFactoryControllerError>!
var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReturnValue: Result<RoomTimelineControllerProtocol, RoomTimelineFactoryControllerError>! {
get {
if Thread.isMainThread {
return buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
} else {
var returnValue: Result<RoomTimelineControllerProtocol, RoomTimelineFactoryControllerError>? = nil
DispatchQueue.main.sync {
returnValue = buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
}
}
}
}
var buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderClosure: (([RoomMessageEventMessageType], JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> Result<RoomTimelineControllerProtocol, RoomTimelineFactoryControllerError>)?
func buildMessageFilteredRoomTimelineController(allowedMessageTypes: [RoomMessageEventMessageType], roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> Result<RoomTimelineControllerProtocol, RoomTimelineFactoryControllerError> {
buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1
buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (allowedMessageTypes: allowedMessageTypes, roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)
DispatchQueue.main.async {
self.buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations.append((allowedMessageTypes: allowedMessageTypes, roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider))
}
if let buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderClosure = buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderClosure {
return await buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderClosure(allowedMessageTypes, roomProxy, timelineItemFactory, mediaProvider)
} else {
return buildMessageFilteredRoomTimelineControllerAllowedMessageTypesRoomProxyTimelineItemFactoryMediaProviderReturnValue
}
}
}
class RoomTimelineProviderMock: RoomTimelineProviderProtocol, @unchecked Sendable {
var updatePublisher: AnyPublisher<([TimelineItemProxy], PaginationState), Never> {
get { return underlyingUpdatePublisher }
set(value) { underlyingUpdatePublisher = value }
}
var underlyingUpdatePublisher: AnyPublisher<([TimelineItemProxy], PaginationState), Never>!
var itemProxies: [TimelineItemProxy] = []
var paginationState: PaginationState {
get { return underlyingPaginationState }
set(value) { underlyingPaginationState = value }
}
var underlyingPaginationState: PaginationState!
var kind: TimelineKind {
get { return underlyingKind }
set(value) { underlyingKind = value }
}
var underlyingKind: TimelineKind!
var membershipChangePublisher: AnyPublisher<Void, Never> {
get { return underlyingMembershipChangePublisher }
set(value) { underlyingMembershipChangePublisher = value }
}
var underlyingMembershipChangePublisher: AnyPublisher<Void, Never>!
}
class SecureBackupControllerMock: SecureBackupControllerProtocol, @unchecked Sendable { class SecureBackupControllerMock: SecureBackupControllerProtocol, @unchecked Sendable {
var recoveryState: CurrentValuePublisher<SecureBackupRecoveryState, Never> { var recoveryState: CurrentValuePublisher<SecureBackupRecoveryState, Never> {
get { return underlyingRecoveryState } get { return underlyingRecoveryState }
@ -14651,12 +14414,249 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
} }
} }
} }
class TimelineControllerFactoryMock: TimelineControllerFactoryProtocol, @unchecked Sendable {
//MARK: - buildTimelineController
var buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0
var buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount: Int {
get {
if Thread.isMainThread {
return buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
}
}
}
}
var buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCalled: Bool {
return buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount > 0
}
var buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)?
var buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = []
var buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue: TimelineControllerProtocol!
var buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue: TimelineControllerProtocol! {
get {
if Thread.isMainThread {
return buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue
} else {
var returnValue: TimelineControllerProtocol? = nil
DispatchQueue.main.sync {
returnValue = buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
}
}
}
}
var buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, String?, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) -> TimelineControllerProtocol)?
func buildTimelineController(roomProxy: JoinedRoomProxyProtocol, initialFocussedEventID: String?, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) -> TimelineControllerProtocol {
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount += 1
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)
DispatchQueue.main.async {
self.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedInvocations.append((roomProxy: roomProxy, initialFocussedEventID: initialFocussedEventID, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider))
}
if let buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure = buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure {
return buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure(roomProxy, initialFocussedEventID, timelineItemFactory, mediaProvider)
} else {
return buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue
}
}
//MARK: - buildPinnedEventsTimelineController
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount: Int {
get {
if Thread.isMainThread {
return buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
}
}
}
}
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCalled: Bool {
return buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount > 0
}
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)?
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = []
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: TimelineControllerProtocol?
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue: TimelineControllerProtocol? {
get {
if Thread.isMainThread {
return buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
} else {
var returnValue: TimelineControllerProtocol?? = nil
DispatchQueue.main.sync {
returnValue = buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
}
}
}
}
var buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure: ((JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> TimelineControllerProtocol?)?
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> TimelineControllerProtocol? {
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1
buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)
DispatchQueue.main.async {
self.buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations.append((roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider))
}
if let buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure = buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure {
return await buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderClosure(roomProxy, timelineItemFactory, mediaProvider)
} else {
return buildPinnedEventsTimelineControllerRoomProxyTimelineItemFactoryMediaProviderReturnValue
}
}
//MARK: - buildMessageFilteredTimelineController
var buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = 0
var buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderCallsCount: Int {
get {
if Thread.isMainThread {
return buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingCallsCount = newValue
}
}
}
}
var buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderCalled: Bool {
return buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderCallsCount > 0
}
var buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderReceivedArguments: (allowedMessageTypes: [RoomMessageEventMessageType], presentation: TimelineKind.MediaPresentation, roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)?
var buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations: [(allowedMessageTypes: [RoomMessageEventMessageType], presentation: TimelineKind.MediaPresentation, roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol)] = []
var buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue: Result<TimelineControllerProtocol, TimelineFactoryControllerError>!
var buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderReturnValue: Result<TimelineControllerProtocol, TimelineFactoryControllerError>! {
get {
if Thread.isMainThread {
return buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
} else {
var returnValue: Result<TimelineControllerProtocol, TimelineFactoryControllerError>? = nil
DispatchQueue.main.sync {
returnValue = buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue
}
return returnValue!
}
}
set {
if Thread.isMainThread {
buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderUnderlyingReturnValue = newValue
}
}
}
}
var buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderClosure: (([RoomMessageEventMessageType], TimelineKind.MediaPresentation, JoinedRoomProxyProtocol, RoomTimelineItemFactoryProtocol, MediaProviderProtocol) async -> Result<TimelineControllerProtocol, TimelineFactoryControllerError>)?
func buildMessageFilteredTimelineController(allowedMessageTypes: [RoomMessageEventMessageType], presentation: TimelineKind.MediaPresentation, roomProxy: JoinedRoomProxyProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol, mediaProvider: MediaProviderProtocol) async -> Result<TimelineControllerProtocol, TimelineFactoryControllerError> {
buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderCallsCount += 1
buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderReceivedArguments = (allowedMessageTypes: allowedMessageTypes, presentation: presentation, roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider)
DispatchQueue.main.async {
self.buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderReceivedInvocations.append((allowedMessageTypes: allowedMessageTypes, presentation: presentation, roomProxy: roomProxy, timelineItemFactory: timelineItemFactory, mediaProvider: mediaProvider))
}
if let buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderClosure = buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderClosure {
return await buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderClosure(allowedMessageTypes, presentation, roomProxy, timelineItemFactory, mediaProvider)
} else {
return buildMessageFilteredTimelineControllerAllowedMessageTypesPresentationRoomProxyTimelineItemFactoryMediaProviderReturnValue
}
}
}
class TimelineProviderMock: TimelineProviderProtocol, @unchecked Sendable {
var updatePublisher: AnyPublisher<([TimelineItemProxy], PaginationState), Never> {
get { return underlyingUpdatePublisher }
set(value) { underlyingUpdatePublisher = value }
}
var underlyingUpdatePublisher: AnyPublisher<([TimelineItemProxy], PaginationState), Never>!
var itemProxies: [TimelineItemProxy] = []
var paginationState: PaginationState {
get { return underlyingPaginationState }
set(value) { underlyingPaginationState = value }
}
var underlyingPaginationState: PaginationState!
var kind: TimelineKind {
get { return underlyingKind }
set(value) { underlyingKind = value }
}
var underlyingKind: TimelineKind!
var membershipChangePublisher: AnyPublisher<Void, Never> {
get { return underlyingMembershipChangePublisher }
set(value) { underlyingMembershipChangePublisher = value }
}
var underlyingMembershipChangePublisher: AnyPublisher<Void, Never>!
}
class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable { class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
var timelineProvider: RoomTimelineProviderProtocol { var timelineProvider: TimelineProviderProtocol {
get { return underlyingTimelineProvider } get { return underlyingTimelineProvider }
set(value) { underlyingTimelineProvider = value } set(value) { underlyingTimelineProvider = value }
} }
var underlyingTimelineProvider: RoomTimelineProviderProtocol! var underlyingTimelineProvider: TimelineProviderProtocol!
//MARK: - subscribeForUpdates //MARK: - subscribeForUpdates

View File

@ -1,24 +0,0 @@
//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
struct RoomTimelineControllerFactoryMockConfiguration {
var timelineController: RoomTimelineControllerProtocol?
}
extension RoomTimelineControllerFactoryMock {
convenience init(configuration: RoomTimelineControllerFactoryMockConfiguration) {
self.init()
buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue = configuration.timelineController ?? {
let timelineController = MockRoomTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
return timelineController
}()
}
}

View File

@ -0,0 +1,24 @@
//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
extension TimelineControllerFactoryMock {
struct Configuration {
var timelineController: TimelineControllerProtocol?
}
convenience init(_ configuration: Configuration) {
self.init()
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue = configuration.timelineController ?? {
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
return timelineController
}()
}
}

View File

@ -10,7 +10,7 @@ import Foundation
import MatrixRustSDK import MatrixRustSDK
@MainActor @MainActor
class AutoUpdatingRoomTimelineProviderMock: RoomTimelineProvider { class AutoUpdatingTimelineProviderMock: TimelineProvider {
static var timelineListener: TimelineListener? static var timelineListener: TimelineListener?
private let innerPaginationStatePublisher: PassthroughSubject<PaginationState, Never> private let innerPaginationStatePublisher: PassthroughSubject<PaginationState, Never>

View File

@ -24,9 +24,9 @@ extension TimelineProxyMock {
sendReadReceiptForTypeReturnValue = .success(()) sendReadReceiptForTypeReturnValue = .success(())
if configuration.isAutoUpdating { if configuration.isAutoUpdating {
underlyingTimelineProvider = AutoUpdatingRoomTimelineProviderMock() underlyingTimelineProvider = AutoUpdatingTimelineProviderMock()
} else { } else {
let timelineProvider = RoomTimelineProviderMock() let timelineProvider = TimelineProviderMock()
timelineProvider.paginationState = .init(backward: configuration.timelineStartReached ? .timelineEndReached : .idle, forward: .timelineEndReached) timelineProvider.paginationState = .init(backward: configuration.timelineStartReached ? .timelineEndReached : .idle, forward: .timelineEndReached)
timelineProvider.underlyingMembershipChangePublisher = PassthroughSubject().eraseToAnyPublisher() timelineProvider.underlyingMembershipChangePublisher = PassthroughSubject().eraseToAnyPublisher()
underlyingTimelineProvider = timelineProvider underlyingTimelineProvider = timelineProvider

View File

@ -163,7 +163,7 @@ struct TimelineMediaPreviewModifier_Previews: PreviewProvider {
thumbnailSource: nil, thumbnailSource: nil,
contentType: .pdf)) contentType: .pdf))
let timelineController = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen)) let timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen))
timelineController.timelineItems = [item] timelineController.timelineItems = [item]
let mediaProvider = MediaProviderMock(configuration: .init()) let mediaProvider = MediaProviderMock(configuration: .init())

View File

@ -223,7 +223,7 @@ struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePrevie
contentType: contentType)) contentType: contentType))
let timelineKind = TimelineKind.media(isPresentedOnRoomScreen ? .roomScreen : .mediaFilesScreen) let timelineKind = TimelineKind.media(isPresentedOnRoomScreen ? .roomScreen : .mediaFilesScreen)
let timelineController = MockRoomTimelineController(timelineKind: timelineKind) let timelineController = MockTimelineController(timelineKind: timelineKind)
timelineController.timelineItems = [item] timelineController.timelineItems = [item]
let viewModel = TimelineMediaPreviewViewModel(initialItem: item, let viewModel = TimelineMediaPreviewViewModel(initialItem: item,

View File

@ -144,7 +144,7 @@ struct TimelineMediaPreviewRedactConfirmationView_Previews: PreviewProvider, Tes
thumbnailInfo: .mockThumbnail, thumbnailInfo: .mockThumbnail,
contentType: contentType)) contentType: contentType))
let timelineController = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen)) let timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen))
timelineController.timelineItems = [item] timelineController.timelineItems = [item]
return TimelineMediaPreviewViewModel(initialItem: item, return TimelineMediaPreviewViewModel(initialItem: item,
timelineViewModel: TimelineViewModel.mock(timelineKind: timelineController.timelineKind, timelineViewModel: TimelineViewModel.mock(timelineKind: timelineController.timelineKind,

View File

@ -10,14 +10,15 @@ import SwiftUI
struct MediaEventsTimelineScreenCoordinatorParameters { struct MediaEventsTimelineScreenCoordinatorParameters {
let roomProxy: JoinedRoomProxyProtocol let roomProxy: JoinedRoomProxyProtocol
let mediaTimelineController: RoomTimelineControllerProtocol let mediaTimelineController: TimelineControllerProtocol
let filesTimelineController: RoomTimelineControllerProtocol let filesTimelineController: TimelineControllerProtocol
let mediaProvider: MediaProviderProtocol let mediaProvider: MediaProviderProtocol
let mediaPlayerProvider: MediaPlayerProviderProtocol let mediaPlayerProvider: MediaPlayerProviderProtocol
let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol
let appMediator: AppMediatorProtocol let appMediator: AppMediatorProtocol
let emojiProvider: EmojiProviderProtocol let emojiProvider: EmojiProviderProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
let timelineControllerFactory: TimelineControllerFactoryProtocol
} }
enum MediaEventsTimelineScreenCoordinatorAction { enum MediaEventsTimelineScreenCoordinatorAction {
@ -47,7 +48,8 @@ final class MediaEventsTimelineScreenCoordinator: CoordinatorProtocol {
appMediator: parameters.appMediator, appMediator: parameters.appMediator,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: parameters.emojiProvider) emojiProvider: parameters.emojiProvider,
timelineControllerFactory: parameters.timelineControllerFactory)
let filesTimelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy, let filesTimelineViewModel = TimelineViewModel(roomProxy: parameters.roomProxy,
timelineController: parameters.filesTimelineController, timelineController: parameters.filesTimelineController,
@ -58,7 +60,8 @@ final class MediaEventsTimelineScreenCoordinator: CoordinatorProtocol {
appMediator: parameters.appMediator, appMediator: parameters.appMediator,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: parameters.emojiProvider) emojiProvider: parameters.emojiProvider,
timelineControllerFactory: parameters.timelineControllerFactory)
viewModel = MediaEventsTimelineScreenViewModel(mediaTimelineViewModel: mediaTimelineViewModel, viewModel = MediaEventsTimelineScreenViewModel(mediaTimelineViewModel: mediaTimelineViewModel,
filesTimelineViewModel: filesTimelineViewModel, filesTimelineViewModel: filesTimelineViewModel,

View File

@ -259,9 +259,9 @@ struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
private static func makeTimelineViewModel(empty: Bool) -> TimelineViewModel { private static func makeTimelineViewModel(empty: Bool) -> TimelineViewModel {
let timelineController = if empty { let timelineController = if empty {
MockRoomTimelineController.emptyMediaGallery MockTimelineController.emptyMediaGallery
} else { } else {
MockRoomTimelineController.mediaGallery MockTimelineController.mediaGallery
} }
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
@ -273,6 +273,7 @@ struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
} }

View File

@ -10,12 +10,13 @@ import SwiftUI
struct PinnedEventsTimelineScreenCoordinatorParameters { struct PinnedEventsTimelineScreenCoordinatorParameters {
let roomProxy: JoinedRoomProxyProtocol let roomProxy: JoinedRoomProxyProtocol
let timelineController: RoomTimelineControllerProtocol let timelineController: TimelineControllerProtocol
let mediaProvider: MediaProviderProtocol let mediaProvider: MediaProviderProtocol
let mediaPlayerProvider: MediaPlayerProviderProtocol let mediaPlayerProvider: MediaPlayerProviderProtocol
let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol
let appMediator: AppMediatorProtocol let appMediator: AppMediatorProtocol
let emojiProvider: EmojiProviderProtocol let emojiProvider: EmojiProviderProtocol
let timelineControllerFactory: TimelineControllerFactoryProtocol
} }
enum PinnedEventsTimelineScreenCoordinatorAction { enum PinnedEventsTimelineScreenCoordinatorAction {
@ -51,7 +52,8 @@ final class PinnedEventsTimelineScreenCoordinator: CoordinatorProtocol {
appMediator: parameters.appMediator, appMediator: parameters.appMediator,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: parameters.emojiProvider) emojiProvider: parameters.emojiProvider,
timelineControllerFactory: parameters.timelineControllerFactory)
} }
func start() { func start() {

View File

@ -87,7 +87,7 @@ struct PinnedEventsTimelineScreen: View {
struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview { struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = PinnedEventsTimelineScreenViewModel(analyticsService: ServiceLocator.shared.analytics) static let viewModel = PinnedEventsTimelineScreenViewModel(analyticsService: ServiceLocator.shared.analytics)
static let emptyTimelineViewModel: TimelineViewModel = { static let emptyTimelineViewModel: TimelineViewModel = {
let timelineController = MockRoomTimelineController(timelineKind: .pinned) let timelineController = MockTimelineController(timelineKind: .pinned)
timelineController.timelineItems = [] timelineController.timelineItems = []
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
timelineController: timelineController, timelineController: timelineController,
@ -98,7 +98,8 @@ struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}() }()
static var previews: some View { static var previews: some View {

View File

@ -21,7 +21,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
private let appSettings: AppSettings private let appSettings: AppSettings
private var dmRecipient: RoomMemberProxyProtocol? private var dmRecipient: RoomMemberProxyProtocol?
private var pinnedEventsTimelineProvider: RoomTimelineProviderProtocol? { private var pinnedEventsTimelineProvider: TimelineProviderProtocol? {
didSet { didSet {
guard let pinnedEventsTimelineProvider else { guard let pinnedEventsTimelineProvider else {
return return

View File

@ -10,7 +10,7 @@ import SwiftUI
struct RoomPollsHistoryScreenCoordinatorParameters { struct RoomPollsHistoryScreenCoordinatorParameters {
let pollInteractionHandler: PollInteractionHandlerProtocol let pollInteractionHandler: PollInteractionHandlerProtocol
let roomTimelineController: RoomTimelineControllerProtocol let timelineController: TimelineControllerProtocol
} }
enum RoomPollsHistoryScreenCoordinatorAction { enum RoomPollsHistoryScreenCoordinatorAction {
@ -28,7 +28,7 @@ final class RoomPollsHistoryScreenCoordinator: CoordinatorProtocol {
init(parameters: RoomPollsHistoryScreenCoordinatorParameters) { init(parameters: RoomPollsHistoryScreenCoordinatorParameters) {
viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: parameters.pollInteractionHandler, viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: parameters.pollInteractionHandler,
roomTimelineController: parameters.roomTimelineController, timelineController: parameters.timelineController,
userIndicatorController: ServiceLocator.shared.userIndicatorController) userIndicatorController: ServiceLocator.shared.userIndicatorController)
} }

View File

@ -18,7 +18,7 @@ class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, Room
} }
private let pollInteractionHandler: PollInteractionHandlerProtocol private let pollInteractionHandler: PollInteractionHandlerProtocol
private let roomTimelineController: RoomTimelineControllerProtocol private let timelineController: TimelineControllerProtocol
private let userIndicatorController: UserIndicatorControllerProtocol private let userIndicatorController: UserIndicatorControllerProtocol
private var paginateBackwardsTask: Task<Void, Never>? private var paginateBackwardsTask: Task<Void, Never>?
@ -31,10 +31,10 @@ class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, Room
} }
init(pollInteractionHandler: PollInteractionHandlerProtocol, init(pollInteractionHandler: PollInteractionHandlerProtocol,
roomTimelineController: RoomTimelineControllerProtocol, timelineController: TimelineControllerProtocol,
userIndicatorController: UserIndicatorControllerProtocol) { userIndicatorController: UserIndicatorControllerProtocol) {
self.pollInteractionHandler = pollInteractionHandler self.pollInteractionHandler = pollInteractionHandler
self.roomTimelineController = roomTimelineController self.timelineController = timelineController
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
super.init(initialViewState: RoomPollsHistoryScreenViewState(title: L10n.screenPollsHistoryTitle, super.init(initialViewState: RoomPollsHistoryScreenViewState(title: L10n.screenPollsHistoryTitle,
@ -65,7 +65,7 @@ class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, Room
// MARK: - Private // MARK: - Private
private func setupSubscriptions() { private func setupSubscriptions() {
roomTimelineController.callbacks timelineController.callbacks
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] callback in .sink { [weak self] callback in
guard let self else { return } guard let self else { return }
@ -132,7 +132,7 @@ class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, Room
private func updatePollsList(filter: RoomPollsHistoryFilter) { private func updatePollsList(filter: RoomPollsHistoryFilter) {
// Get the poll timeline items to display // Get the poll timeline items to display
var items: [PollRoomTimelineItem] = [] var items: [PollRoomTimelineItem] = []
for timelineItem in roomTimelineController.timelineItems { for timelineItem in timelineController.timelineItems {
if let pollRoomTimelineItem = timelineItem as? PollRoomTimelineItem { if let pollRoomTimelineItem = timelineItem as? PollRoomTimelineItem {
// Apply the filter // Apply the filter
switch filter { switch filter {
@ -148,7 +148,7 @@ class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, Room
// Map into RoomPollsHistoryPollDetails to have both the event timestamp and the timeline item // Map into RoomPollsHistoryPollDetails to have both the event timestamp and the timeline item
state.pollTimelineItems = items.map { item in state.pollTimelineItems = items.map { item in
guard let timestamp = roomTimelineController.eventTimestamp(for: item.id) else { guard let timestamp = timelineController.eventTimestamp(for: item.id) else {
return nil return nil
} }
return RoomPollsHistoryPollDetails(timestamp: timestamp, item: item) return RoomPollsHistoryPollDetails(timestamp: timestamp, item: item)
@ -167,7 +167,7 @@ class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, Room
return return
} }
state.isBackPaginating = true state.isBackPaginating = true
switch await roomTimelineController.paginateBackwards(requestSize: Constants.backPaginationEventLimit) { switch await timelineController.paginateBackwards(requestSize: Constants.backPaginationEventLimit) {
case .failure(let error): case .failure(let error):
MXLog.error("failed to back paginate. \(error)") MXLog.error("failed to back paginate. \(error)")
default: default:

View File

@ -114,33 +114,33 @@ private extension DateFormatter {
struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview { struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview {
static let viewModelEmpty: RoomPollsHistoryScreenViewModel = { static let viewModelEmpty: RoomPollsHistoryScreenViewModel = {
let roomTimelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
roomTimelineController.timelineItems = [] timelineController.timelineItems = []
let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls") let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls")
let viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(), let viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(),
roomTimelineController: roomTimelineController, timelineController: timelineController,
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
return viewModel return viewModel
}() }()
static let viewModel: RoomPollsHistoryScreenViewModel = { static let viewModel: RoomPollsHistoryScreenViewModel = {
let roomTimelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
let polls = [PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: false)), let polls = [PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: false)),
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: true)), PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: true)),
PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true)] PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true)]
roomTimelineController.timelineItems = polls timelineController.timelineItems = polls
for i in 0..<polls.count { for i in 0..<polls.count {
let item = polls[i] let item = polls[i]
let date: Date! = DateComponents(calendar: .current, timeZone: .gmt, year: 2023, month: 12, day: 1 + i, hour: 12).date let date: Date! = DateComponents(calendar: .current, timeZone: .gmt, year: 2023, month: 12, day: 1 + i, hour: 12).date
roomTimelineController.timelineItemsTimestamp[item.id] = date timelineController.timelineItemsTimestamp[item.id] = date
} }
let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls", timelineStartReached: true) let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls", timelineStartReached: true)
let viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(), let viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(),
roomTimelineController: roomTimelineController, timelineController: timelineController,
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
return viewModel return viewModel

View File

@ -16,7 +16,7 @@ struct RoomScreenCoordinatorParameters {
let roomProxy: JoinedRoomProxyProtocol let roomProxy: JoinedRoomProxyProtocol
var focussedEvent: FocusEvent? var focussedEvent: FocusEvent?
var sharedText: String? var sharedText: String?
let timelineController: RoomTimelineControllerProtocol let timelineController: TimelineControllerProtocol
let mediaProvider: MediaProviderProtocol let mediaProvider: MediaProviderProtocol
let mediaPlayerProvider: MediaPlayerProviderProtocol let mediaPlayerProvider: MediaPlayerProviderProtocol
let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol
@ -26,6 +26,7 @@ struct RoomScreenCoordinatorParameters {
let appMediator: AppMediatorProtocol let appMediator: AppMediatorProtocol
let appSettings: AppSettings let appSettings: AppSettings
let composerDraftService: ComposerDraftServiceProtocol let composerDraftService: ComposerDraftServiceProtocol
let timelineControllerFactory: TimelineControllerFactoryProtocol
} }
enum RoomScreenCoordinatorAction { enum RoomScreenCoordinatorAction {
@ -84,7 +85,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
appMediator: parameters.appMediator, appMediator: parameters.appMediator,
appSettings: parameters.appSettings, appSettings: parameters.appSettings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: parameters.emojiProvider) emojiProvider: parameters.emojiProvider,
timelineControllerFactory: parameters.timelineControllerFactory)
wysiwygViewModel = WysiwygComposerViewModel(minHeight: ComposerConstant.minHeight, wysiwygViewModel = WysiwygComposerViewModel(minHeight: ComposerConstant.minHeight,
maxCompressedHeight: ComposerConstant.maxHeight, maxCompressedHeight: ComposerConstant.maxHeight,

View File

@ -32,7 +32,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
actionsSubject.eraseToAnyPublisher() actionsSubject.eraseToAnyPublisher()
} }
private var pinnedEventsTimelineProvider: RoomTimelineProviderProtocol? { private var pinnedEventsTimelineProvider: TimelineProviderProtocol? {
didSet { didSet {
guard let pinnedEventsTimelineProvider else { guard let pinnedEventsTimelineProvider else {
return return

View File

@ -256,7 +256,7 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview {
hasOngoingCall: true)) hasOngoingCall: true))
static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock) static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock)
static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock, static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -264,7 +264,8 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
static var previews: some View { static var previews: some View {
NavigationStack { NavigationStack {

View File

@ -29,7 +29,7 @@ enum TimelineInteractionHandlerAction {
@MainActor @MainActor
class TimelineInteractionHandler { class TimelineInteractionHandler {
private let roomProxy: JoinedRoomProxyProtocol private let roomProxy: JoinedRoomProxyProtocol
private let timelineController: RoomTimelineControllerProtocol private let timelineController: TimelineControllerProtocol
private let mediaProvider: MediaProviderProtocol private let mediaProvider: MediaProviderProtocol
private let mediaPlayerProvider: MediaPlayerProviderProtocol private let mediaPlayerProvider: MediaPlayerProviderProtocol
private let voiceMessageRecorder: VoiceMessageRecorderProtocol private let voiceMessageRecorder: VoiceMessageRecorderProtocol
@ -38,6 +38,8 @@ class TimelineInteractionHandler {
private let appMediator: AppMediatorProtocol private let appMediator: AppMediatorProtocol
private let appSettings: AppSettings private let appSettings: AppSettings
private let analyticsService: AnalyticsService private let analyticsService: AnalyticsService
private let emojiProvider: EmojiProviderProtocol
private let timelineControllerFactory: TimelineControllerFactoryProtocol
private let pollInteractionHandler: PollInteractionHandlerProtocol private let pollInteractionHandler: PollInteractionHandlerProtocol
private let actionsSubject: PassthroughSubject<TimelineInteractionHandlerAction, Never> = .init() private let actionsSubject: PassthroughSubject<TimelineInteractionHandlerAction, Never> = .init()
@ -54,7 +56,7 @@ class TimelineInteractionHandler {
private var resumeVoiceMessagePlaybackAfterScrubbing = false private var resumeVoiceMessagePlaybackAfterScrubbing = false
init(roomProxy: JoinedRoomProxyProtocol, init(roomProxy: JoinedRoomProxyProtocol,
timelineController: RoomTimelineControllerProtocol, timelineController: TimelineControllerProtocol,
mediaProvider: MediaProviderProtocol, mediaProvider: MediaProviderProtocol,
mediaPlayerProvider: MediaPlayerProviderProtocol, mediaPlayerProvider: MediaPlayerProviderProtocol,
voiceMessageMediaManager: VoiceMessageMediaManagerProtocol, voiceMessageMediaManager: VoiceMessageMediaManagerProtocol,
@ -62,7 +64,9 @@ class TimelineInteractionHandler {
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
appMediator: AppMediatorProtocol, appMediator: AppMediatorProtocol,
appSettings: AppSettings, appSettings: AppSettings,
analyticsService: AnalyticsService) { analyticsService: AnalyticsService,
emojiProvider: EmojiProviderProtocol,
timelineControllerFactory: TimelineControllerFactoryProtocol) {
self.roomProxy = roomProxy self.roomProxy = roomProxy
self.timelineController = timelineController self.timelineController = timelineController
self.mediaProvider = mediaProvider self.mediaProvider = mediaProvider
@ -73,6 +77,8 @@ class TimelineInteractionHandler {
self.appMediator = appMediator self.appMediator = appMediator
self.appSettings = appSettings self.appSettings = appSettings
self.analyticsService = analyticsService self.analyticsService = analyticsService
self.emojiProvider = emojiProvider
self.timelineControllerFactory = timelineControllerFactory
pollInteractionHandler = PollInteractionHandler(analyticsService: analyticsService, roomProxy: roomProxy) pollInteractionHandler = PollInteractionHandler(analyticsService: analyticsService, roomProxy: roomProxy)
} }
@ -495,7 +501,7 @@ class TimelineInteractionHandler {
actionsSubject.send(.displayEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis)) actionsSubject.send(.displayEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis))
} }
func processItemTap(_ itemID: TimelineItemIdentifier) async -> RoomTimelineControllerAction { func processItemTap(_ itemID: TimelineItemIdentifier) async -> TimelineControllerAction {
guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else { guard let timelineItem = timelineController.timelineItems.firstUsingStableID(itemID) else {
return .none return .none
} }
@ -522,7 +528,7 @@ class TimelineInteractionHandler {
} }
} }
private func displayMediaActionIfPossible(timelineItem: RoomTimelineItemProtocol) async -> RoomTimelineControllerAction { private func displayMediaActionIfPossible(timelineItem: RoomTimelineItemProtocol) async -> TimelineControllerAction {
var source: MediaSourceProxy? var source: MediaSourceProxy?
var filename: String var filename: String
var caption: String? var caption: String?

View File

@ -22,13 +22,14 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
} }
private let roomProxy: JoinedRoomProxyProtocol private let roomProxy: JoinedRoomProxyProtocol
private let timelineController: RoomTimelineControllerProtocol private let timelineController: TimelineControllerProtocol
private let mediaPlayerProvider: MediaPlayerProviderProtocol private let mediaPlayerProvider: MediaPlayerProviderProtocol
private let userIndicatorController: UserIndicatorControllerProtocol private let userIndicatorController: UserIndicatorControllerProtocol
private let appMediator: AppMediatorProtocol private let appMediator: AppMediatorProtocol
private let appSettings: AppSettings private let appSettings: AppSettings
private let analyticsService: AnalyticsService private let analyticsService: AnalyticsService
private let emojiProvider: EmojiProviderProtocol private let emojiProvider: EmojiProviderProtocol
private let timelineControllerFactory: TimelineControllerFactoryProtocol
private let timelineInteractionHandler: TimelineInteractionHandler private let timelineInteractionHandler: TimelineInteractionHandler
@ -44,7 +45,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
init(roomProxy: JoinedRoomProxyProtocol, init(roomProxy: JoinedRoomProxyProtocol,
focussedEventID: String? = nil, focussedEventID: String? = nil,
timelineController: RoomTimelineControllerProtocol, timelineController: TimelineControllerProtocol,
mediaProvider: MediaProviderProtocol, mediaProvider: MediaProviderProtocol,
mediaPlayerProvider: MediaPlayerProviderProtocol, mediaPlayerProvider: MediaPlayerProviderProtocol,
voiceMessageMediaManager: VoiceMessageMediaManagerProtocol, voiceMessageMediaManager: VoiceMessageMediaManagerProtocol,
@ -52,7 +53,8 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
appMediator: AppMediatorProtocol, appMediator: AppMediatorProtocol,
appSettings: AppSettings, appSettings: AppSettings,
analyticsService: AnalyticsService, analyticsService: AnalyticsService,
emojiProvider: EmojiProviderProtocol) { emojiProvider: EmojiProviderProtocol,
timelineControllerFactory: TimelineControllerFactoryProtocol) {
self.timelineController = timelineController self.timelineController = timelineController
self.mediaPlayerProvider = mediaPlayerProvider self.mediaPlayerProvider = mediaPlayerProvider
self.roomProxy = roomProxy self.roomProxy = roomProxy
@ -61,6 +63,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.appMediator = appMediator self.appMediator = appMediator
self.emojiProvider = emojiProvider self.emojiProvider = emojiProvider
self.timelineControllerFactory = timelineControllerFactory
let voiceMessageRecorder = VoiceMessageRecorder(audioRecorder: AudioRecorder(), mediaPlayerProvider: mediaPlayerProvider) let voiceMessageRecorder = VoiceMessageRecorder(audioRecorder: AudioRecorder(), mediaPlayerProvider: mediaPlayerProvider)
@ -73,7 +76,9 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: appMediator, appMediator: appMediator,
appSettings: appSettings, appSettings: appSettings,
analyticsService: analyticsService) analyticsService: analyticsService,
emojiProvider: emojiProvider,
timelineControllerFactory: timelineControllerFactory)
super.init(initialViewState: TimelineViewState(timelineKind: timelineController.timelineKind, super.init(initialViewState: TimelineViewState(timelineKind: timelineController.timelineKind,
roomID: roomProxy.id, roomID: roomProxy.id,
@ -865,10 +870,10 @@ private extension RoomInfoProxy {
extension TimelineViewModel { extension TimelineViewModel {
static let mock = mock(timelineKind: .live) static let mock = mock(timelineKind: .live)
static func mock(timelineKind: TimelineKind = .live, timelineController: MockRoomTimelineController? = nil) -> TimelineViewModel { static func mock(timelineKind: TimelineKind = .live, timelineController: MockTimelineController? = nil) -> TimelineViewModel {
TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
focussedEventID: nil, focussedEventID: nil,
timelineController: timelineController ?? MockRoomTimelineController(timelineKind: timelineKind), timelineController: timelineController ?? MockTimelineController(timelineKind: timelineKind),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -876,7 +881,8 @@ extension TimelineViewModel {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
} }

View File

@ -44,7 +44,7 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
] ]
let roomProxyMock = JoinedRoomProxyMock(.init(name: "Room", members: members)) let roomProxyMock = JoinedRoomProxyMock(.init(name: "Room", members: members))
let mock = TimelineViewModel(roomProxy: roomProxyMock, let mock = TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -52,7 +52,8 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
return mock return mock
}() }()

View File

@ -330,7 +330,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: ["pinned"])) let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: ["pinned"]))
return TimelineViewModel(roomProxy: roomProxy, return TimelineViewModel(roomProxy: roomProxy,
focussedEventID: nil, focussedEventID: nil,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -338,7 +338,8 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}() }()
static var previews: some View { static var previews: some View {

View File

@ -79,7 +79,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
] ]
static let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Test", members: members)), static let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Test", members: members)),
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -87,7 +87,8 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
static let singleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now")] static let singleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now")]
static let doubleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"), static let doubleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"),

View File

@ -89,7 +89,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
static let focussedEventID = "RoomTimelineItemFixtures.default.5" static let focussedEventID = "RoomTimelineItemFixtures.default.5"
static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock, static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock,
focussedEventID: focussedEventID, focussedEventID: focussedEventID,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -97,7 +97,8 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
static var previews: some View { static var previews: some View {
NavigationStack { NavigationStack {

View File

@ -82,7 +82,7 @@ struct TimelineView_Previews: PreviewProvider, TestablePreview {
name: "Preview room")) name: "Preview room"))
static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock) static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock)
static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock, static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -90,7 +90,8 @@ struct TimelineView_Previews: PreviewProvider, TestablePreview {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
static var previews: some View { static var previews: some View {
NavigationStack { NavigationStack {

View File

@ -182,14 +182,15 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
} }
} }
func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType]) async -> Result<any TimelineProxyProtocol, RoomProxyError> { func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType],
presentation: TimelineKind.MediaPresentation) async -> Result<any TimelineProxyProtocol, RoomProxyError> {
do { do {
let sdkTimeline = try await room.timelineWithConfiguration(configuration: .init(focus: .live, let sdkTimeline = try await room.timelineWithConfiguration(configuration: .init(focus: .live,
allowedMessageTypes: .only(types: allowedMessageTypes), allowedMessageTypes: .only(types: allowedMessageTypes),
internalIdPrefix: nil, internalIdPrefix: nil,
dateDividerMode: .monthly)) dateDividerMode: .monthly))
let timeline = TimelineProxy(timeline: sdkTimeline, kind: .media(.mediaFilesScreen)) let timeline = TimelineProxy(timeline: sdkTimeline, kind: .media(presentation))
await timeline.subscribeForUpdates() await timeline.subscribeForUpdates()
return .success(timeline) return .success(timeline)

View File

@ -78,7 +78,8 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
func timelineFocusedOnEvent(eventID: String, numberOfEvents: UInt16) async -> Result<TimelineProxyProtocol, RoomProxyError> func timelineFocusedOnEvent(eventID: String, numberOfEvents: UInt16) async -> Result<TimelineProxyProtocol, RoomProxyError>
func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType]) async -> Result<TimelineProxyProtocol, RoomProxyError> func messageFilteredTimeline(allowedMessageTypes: [RoomMessageEventMessageType],
presentation: TimelineKind.MediaPresentation) async -> Result<TimelineProxyProtocol, RoomProxyError>
func enableEncryption() async -> Result<Void, RoomProxyError> func enableEncryption() async -> Result<Void, RoomProxyError>

View File

@ -11,7 +11,7 @@ import Combine
import Foundation import Foundation
import MatrixRustSDK import MatrixRustSDK
class MockRoomTimelineController: RoomTimelineControllerProtocol { class MockTimelineController: TimelineControllerProtocol {
/// An array of timeline item arrays that will be inserted in order for each back pagination request. /// An array of timeline item arrays that will be inserted in order for each back pagination request.
var backPaginationResponses: [[RoomTimelineItemProtocol]] = [] var backPaginationResponses: [[RoomTimelineItemProtocol]] = []
/// An array of timeline items that will be appended in order when ``simulateIncomingItems()`` is called. /// An array of timeline items that will be appended in order when ``simulateIncomingItems()`` is called.
@ -21,7 +21,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
var roomID: String { roomProxy?.id ?? "MockRoomIdentifier" } var roomID: String { roomProxy?.id ?? "MockRoomIdentifier" }
var timelineKind: TimelineKind var timelineKind: TimelineKind
let callbacks = PassthroughSubject<RoomTimelineControllerCallback, Never>() let callbacks = PassthroughSubject<TimelineControllerCallback, Never>()
var paginationState: PaginationState = .initial { var paginationState: PaginationState = .initial {
didSet { didSet {
@ -34,14 +34,14 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
private var client: UITestsSignalling.Client? private var client: UITestsSignalling.Client?
static var mediaGallery: MockRoomTimelineController { static var mediaGallery: MockTimelineController {
MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: (0..<5).reduce([]) { partialResult, _ in MockTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: (0..<5).reduce([]) { partialResult, _ in
partialResult + [RoomTimelineItemFixtures.separator] + RoomTimelineItemFixtures.mediaChunk partialResult + [RoomTimelineItemFixtures.separator] + RoomTimelineItemFixtures.mediaChunk
}) })
} }
static var emptyMediaGallery: MockRoomTimelineController { static var emptyMediaGallery: MockTimelineController {
let mock = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen)) let mock = MockTimelineController(timelineKind: .media(.mediaFilesScreen))
mock.paginationState = PaginationState(backward: .timelineEndReached, forward: .timelineEndReached) mock.paginationState = PaginationState(backward: .timelineEndReached, forward: .timelineEndReached)
return mock return mock
} }
@ -63,7 +63,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
} }
private(set) var focusOnEventCallCount = 0 private(set) var focusOnEventCallCount = 0
func focusOnEvent(_ eventID: String, timelineSize: UInt16) async -> Result<Void, RoomTimelineControllerError> { func focusOnEvent(_ eventID: String, timelineSize: UInt16) async -> Result<Void, TimelineControllerError> {
focusOnEventCallCount += 1 focusOnEventCallCount += 1
callbacks.send(.isLive(false)) callbacks.send(.isLive(false))
return .success(()) return .success(())
@ -75,7 +75,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
callbacks.send(.isLive(true)) callbacks.send(.isLive(true))
} }
func paginateBackwards(requestSize: UInt16) async -> Result<Void, RoomTimelineControllerError> { func paginateBackwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError> {
paginationState = PaginationState(backward: .paginating, forward: .timelineEndReached) paginationState = PaginationState(backward: .paginating, forward: .timelineEndReached)
if client == nil { if client == nil {
@ -85,7 +85,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
return .success(()) return .success(())
} }
func paginateForwards(requestSize: UInt16) async -> Result<Void, RoomTimelineControllerError> { func paginateForwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError> {
// try? await simulateForwardPagination() // try? await simulateForwardPagination()
.success(()) .success(())
} }

View File

@ -1,55 +0,0 @@
//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
import MatrixRustSDK
struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol {
func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol,
initialFocussedEventID: String?,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol {
RoomTimelineController(roomProxy: roomProxy,
timelineProxy: roomProxy.timeline,
initialFocussedEventID: initialFocussedEventID,
timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider,
appSettings: ServiceLocator.shared.settings)
}
func buildPinnedEventsRoomTimelineController(roomProxy: JoinedRoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol? {
guard let pinnedEventsTimeline = await roomProxy.pinnedEventsTimeline else {
return nil
}
return RoomTimelineController(roomProxy: roomProxy,
timelineProxy: pinnedEventsTimeline,
initialFocussedEventID: nil,
timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider,
appSettings: ServiceLocator.shared.settings)
}
func buildMessageFilteredRoomTimelineController(allowedMessageTypes: [RoomMessageEventMessageType],
roomProxy: JoinedRoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) async -> Result<RoomTimelineControllerProtocol, RoomTimelineFactoryControllerError> {
switch await roomProxy.messageFilteredTimeline(allowedMessageTypes: allowedMessageTypes) {
case .success(let timelineProxy):
return .success(RoomTimelineController(roomProxy: roomProxy,
timelineProxy: timelineProxy,
initialFocussedEventID: nil,
timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider,
appSettings: ServiceLocator.shared.settings))
case .failure(let error):
return .failure(.roomProxyError(error))
}
}
}

View File

@ -1,33 +0,0 @@
//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
import MatrixRustSDK
enum RoomTimelineFactoryControllerError: Error {
case roomProxyError(RoomProxyError)
}
@MainActor
protocol RoomTimelineControllerFactoryProtocol {
func buildRoomTimelineController(roomProxy: JoinedRoomProxyProtocol,
initialFocussedEventID: String?,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol
func buildPinnedEventsRoomTimelineController(roomProxy: JoinedRoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) async -> RoomTimelineControllerProtocol?
func buildMessageFilteredRoomTimelineController(allowedMessageTypes: [RoomMessageEventMessageType],
roomProxy: JoinedRoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) async -> Result<RoomTimelineControllerProtocol, RoomTimelineFactoryControllerError>
}
// sourcery: AutoMockable
extension RoomTimelineControllerFactoryProtocol { }

View File

@ -11,19 +11,19 @@ import IntentsUI
import MatrixRustSDK import MatrixRustSDK
import UIKit import UIKit
class RoomTimelineController: RoomTimelineControllerProtocol { class TimelineController: TimelineControllerProtocol {
private let roomProxy: JoinedRoomProxyProtocol private let roomProxy: JoinedRoomProxyProtocol
private let liveTimelineProvider: RoomTimelineProviderProtocol private let liveTimelineProvider: TimelineProviderProtocol
private let timelineItemFactory: RoomTimelineItemFactoryProtocol private let timelineItemFactory: RoomTimelineItemFactoryProtocol
private let mediaProvider: MediaProviderProtocol private let mediaProvider: MediaProviderProtocol
private let appSettings: AppSettings private let appSettings: AppSettings
private let serialDispatchQueue: DispatchQueue private let serialDispatchQueue: DispatchQueue
let callbacks = PassthroughSubject<RoomTimelineControllerCallback, Never>() let callbacks = PassthroughSubject<TimelineControllerCallback, Never>()
private var activeTimeline: TimelineProxyProtocol private var activeTimeline: TimelineProxyProtocol
private var activeTimelineProvider: RoomTimelineProviderProtocol { private var activeTimelineProvider: TimelineProviderProtocol {
didSet { didSet {
configureActiveTimelineProvider() configureActiveTimelineProvider()
} }
@ -57,7 +57,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
self.mediaProvider = mediaProvider self.mediaProvider = mediaProvider
self.appSettings = appSettings self.appSettings = appSettings
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomtimelineprovider", qos: .utility) serialDispatchQueue = DispatchQueue(label: "io.element.elementx.timelineprovider", qos: .utility)
activeTimeline = timelineProxy activeTimeline = timelineProxy
activeTimelineProvider = liveTimelineProvider activeTimelineProvider = liveTimelineProvider
@ -82,7 +82,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
} }
} }
func focusOnEvent(_ eventID: String, timelineSize: UInt16) async -> Result<Void, RoomTimelineControllerError> { func focusOnEvent(_ eventID: String, timelineSize: UInt16) async -> Result<Void, TimelineControllerError> {
switch await roomProxy.timelineFocusedOnEvent(eventID: eventID, numberOfEvents: timelineSize) { switch await roomProxy.timelineFocusedOnEvent(eventID: eventID, numberOfEvents: timelineSize) {
case .success(let timeline): case .success(let timeline):
await timeline.subscribeForUpdates() await timeline.subscribeForUpdates()
@ -103,7 +103,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
activeTimelineProvider = liveTimelineProvider activeTimelineProvider = liveTimelineProvider
} }
func paginateBackwards(requestSize: UInt16) async -> Result<Void, RoomTimelineControllerError> { func paginateBackwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError> {
MXLog.info("Started back pagination request") MXLog.info("Started back pagination request")
switch await activeTimeline.paginateBackwards(requestSize: requestSize) { switch await activeTimeline.paginateBackwards(requestSize: requestSize) {
case .success: case .success:
@ -115,7 +115,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
} }
} }
func paginateForwards(requestSize: UInt16) async -> Result<Void, RoomTimelineControllerError> { func paginateForwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError> {
MXLog.info("Started forward pagination request") MXLog.info("Started forward pagination request")
switch await activeTimeline.paginateForwards(requestSize: requestSize) { switch await activeTimeline.paginateForwards(requestSize: requestSize) {
case .success: case .success:

View File

@ -0,0 +1,56 @@
//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
import MatrixRustSDK
struct TimelineControllerFactory: TimelineControllerFactoryProtocol {
func buildTimelineController(roomProxy: JoinedRoomProxyProtocol,
initialFocussedEventID: String?,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> TimelineControllerProtocol {
TimelineController(roomProxy: roomProxy,
timelineProxy: roomProxy.timeline,
initialFocussedEventID: initialFocussedEventID,
timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider,
appSettings: ServiceLocator.shared.settings)
}
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) async -> TimelineControllerProtocol? {
guard let pinnedEventsTimeline = await roomProxy.pinnedEventsTimeline else {
return nil
}
return TimelineController(roomProxy: roomProxy,
timelineProxy: pinnedEventsTimeline,
initialFocussedEventID: nil,
timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider,
appSettings: ServiceLocator.shared.settings)
}
func buildMessageFilteredTimelineController(allowedMessageTypes: [RoomMessageEventMessageType],
presentation: TimelineKind.MediaPresentation,
roomProxy: JoinedRoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) async -> Result<TimelineControllerProtocol, TimelineFactoryControllerError> {
switch await roomProxy.messageFilteredTimeline(allowedMessageTypes: allowedMessageTypes, presentation: presentation) {
case .success(let timelineProxy):
return .success(TimelineController(roomProxy: roomProxy,
timelineProxy: timelineProxy,
initialFocussedEventID: nil,
timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider,
appSettings: ServiceLocator.shared.settings))
case .failure(let error):
return .failure(.roomProxyError(error))
}
}
}

View File

@ -0,0 +1,34 @@
//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
import MatrixRustSDK
enum TimelineFactoryControllerError: Error {
case roomProxyError(RoomProxyError)
}
@MainActor
protocol TimelineControllerFactoryProtocol {
func buildTimelineController(roomProxy: JoinedRoomProxyProtocol,
initialFocussedEventID: String?,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> TimelineControllerProtocol
func buildPinnedEventsTimelineController(roomProxy: JoinedRoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) async -> TimelineControllerProtocol?
func buildMessageFilteredTimelineController(allowedMessageTypes: [RoomMessageEventMessageType],
presentation: TimelineKind.MediaPresentation,
roomProxy: JoinedRoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) async -> Result<TimelineControllerProtocol, TimelineFactoryControllerError>
}
// sourcery: AutoMockable
extension TimelineControllerFactoryProtocol { }

View File

@ -9,25 +9,25 @@ import Combine
import MatrixRustSDK import MatrixRustSDK
import SwiftUI import SwiftUI
enum RoomTimelineControllerCallback { enum TimelineControllerCallback {
case updatedTimelineItems(timelineItems: [RoomTimelineItemProtocol], isSwitchingTimelines: Bool) case updatedTimelineItems(timelineItems: [RoomTimelineItemProtocol], isSwitchingTimelines: Bool)
case paginationState(PaginationState) case paginationState(PaginationState)
case isLive(Bool) case isLive(Bool)
} }
enum RoomTimelineControllerAction { enum TimelineControllerAction {
case displayMediaFile(file: MediaFileHandleProxy, title: String?) case displayMediaFile(file: MediaFileHandleProxy, title: String?)
case displayLocation(body: String, geoURI: GeoURI, description: String?) case displayLocation(body: String, geoURI: GeoURI, description: String?)
case none case none
} }
enum RoomTimelineControllerError: Error { enum TimelineControllerError: Error {
case generic case generic
case eventNotFound case eventNotFound
} }
@MainActor @MainActor
protocol RoomTimelineControllerProtocol { protocol TimelineControllerProtocol {
var roomID: String { get } var roomID: String { get }
var timelineKind: TimelineKind { get } var timelineKind: TimelineKind { get }
@ -37,17 +37,17 @@ protocol RoomTimelineControllerProtocol {
/// The current pagination state, use only for setting up the intial state /// The current pagination state, use only for setting up the intial state
var paginationState: PaginationState { get } var paginationState: PaginationState { get }
var callbacks: PassthroughSubject<RoomTimelineControllerCallback, Never> { get } var callbacks: PassthroughSubject<TimelineControllerCallback, Never> { get }
func processItemAppearance(_ itemID: TimelineItemIdentifier) async func processItemAppearance(_ itemID: TimelineItemIdentifier) async
func processItemDisappearance(_ itemID: TimelineItemIdentifier) async func processItemDisappearance(_ itemID: TimelineItemIdentifier) async
func focusOnEvent(_ eventID: String, timelineSize: UInt16) async -> Result<Void, RoomTimelineControllerError> func focusOnEvent(_ eventID: String, timelineSize: UInt16) async -> Result<Void, TimelineControllerError>
func focusLive() func focusLive()
func paginateBackwards(requestSize: UInt16) async -> Result<Void, RoomTimelineControllerError> func paginateBackwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError>
func paginateForwards(requestSize: UInt16) async -> Result<Void, RoomTimelineControllerError> func paginateForwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError>
func sendReadReceipt(for itemID: TimelineItemIdentifier) async func sendReadReceipt(for itemID: TimelineItemIdentifier) async

View File

@ -9,7 +9,7 @@ import Combine
import Foundation import Foundation
import MatrixRustSDK import MatrixRustSDK
class RoomTimelineProvider: RoomTimelineProviderProtocol { class TimelineProvider: TimelineProviderProtocol {
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
private let serialDispatchQueue: DispatchQueue private let serialDispatchQueue: DispatchQueue
@ -46,7 +46,7 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
} }
init(timeline: Timeline, kind: TimelineKind, paginationStatePublisher: AnyPublisher<PaginationState, Never>) { init(timeline: Timeline, kind: TimelineKind, paginationStatePublisher: AnyPublisher<PaginationState, Never>) {
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomtimelineprovider", qos: .utility) serialDispatchQueue = DispatchQueue(label: "io.element.elementx.timelineprovider", qos: .utility)
itemProxiesSubject = CurrentValueSubject<[TimelineItemProxy], Never>([]) itemProxiesSubject = CurrentValueSubject<[TimelineItemProxy], Never>([])
self.kind = kind self.kind = kind

View File

@ -29,7 +29,7 @@ struct PaginationState: Equatable {
@MainActor @MainActor
// sourcery: AutoMockable // sourcery: AutoMockable
protocol RoomTimelineProviderProtocol { protocol TimelineProviderProtocol {
/// A publisher that signals when ``itemProxies`` or ``paginationState`` are changed. /// A publisher that signals when ``itemProxies`` or ``paginationState`` are changed.
var updatePublisher: AnyPublisher<([TimelineItemProxy], PaginationState), Never> { get } var updatePublisher: AnyPublisher<([TimelineItemProxy], PaginationState), Never> { get }
/// The current set of items in the timeline. /// The current set of items in the timeline.

View File

@ -20,8 +20,8 @@ final class TimelineProxy: TimelineProxyProtocol {
private let kind: TimelineKind private let kind: TimelineKind
private var innerTimelineProvider: RoomTimelineProviderProtocol! private var innerTimelineProvider: TimelineProviderProtocol!
var timelineProvider: RoomTimelineProviderProtocol { var timelineProvider: TimelineProviderProtocol {
innerTimelineProvider innerTimelineProvider
} }
@ -47,7 +47,7 @@ final class TimelineProxy: TimelineProxyProtocol {
await subscribeToPagination() await subscribeToPagination()
let provider = await RoomTimelineProvider(timeline: timeline, kind: kind, paginationStatePublisher: paginationStatePublisher) let provider = await TimelineProvider(timeline: timeline, kind: kind, paginationStatePublisher: paginationStatePublisher)
// Make sure the existing items are built so that we have content in the timeline before // Make sure the existing items are built so that we have content in the timeline before
// determining whether or not the timeline should paginate to load more items. // determining whether or not the timeline should paginate to load more items.
await provider.waitForInitialItems() await provider.waitForInitialItems()

View File

@ -27,7 +27,7 @@ enum TimelineProxyError: Error {
// sourcery: AutoMockable // sourcery: AutoMockable
protocol TimelineProxyProtocol { protocol TimelineProxyProtocol {
var timelineProvider: RoomTimelineProviderProtocol { get } var timelineProvider: TimelineProviderProtocol { get }
func subscribeForUpdates() async func subscribeForUpdates() async

View File

@ -235,7 +235,7 @@ class MockScreen: Identifiable {
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
roomProxy: JoinedRoomProxyMock(.init(name: "Some room name", avatarURL: nil)), roomProxy: JoinedRoomProxyMock(.init(name: "Some room name", avatarURL: nil)),
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -244,13 +244,14 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator return navigationStackCoordinator
case .roomSmallTimeline: case .roomSmallTimeline:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
@ -263,13 +264,14 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator return navigationStackCoordinator
case .roomSmallTimelineWithReactions: case .roomSmallTimelineWithReactions:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.default timelineController.timelineItems = RoomTimelineItemFixtures.default
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
@ -282,13 +284,14 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator return navigationStackCoordinator
case .roomSmallTimelineWithReadReceipts: case .roomSmallTimelineWithReadReceipts:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunkWithReadReceipts timelineController.timelineItems = RoomTimelineItemFixtures.smallChunkWithReadReceipts
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
@ -301,14 +304,15 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator return navigationStackCoordinator
case .roomSmallTimelineIncomingAndSmallPagination: case .roomSmallTimelineIncomingAndSmallPagination:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController(listenForSignals: true) let timelineController = MockTimelineController(listenForSignals: true)
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
timelineController.backPaginationResponses = [RoomTimelineItemFixtures.singleMessageChunk] timelineController.backPaginationResponses = [RoomTimelineItemFixtures.singleMessageChunk]
timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage]
@ -323,7 +327,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -331,7 +336,7 @@ class MockScreen: Identifiable {
case .roomSmallTimelineLargePagination: case .roomSmallTimelineLargePagination:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController(listenForSignals: true) let timelineController = MockTimelineController(listenForSignals: true)
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk]
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
@ -345,7 +350,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -353,7 +359,7 @@ class MockScreen: Identifiable {
case .roomLayoutTop: case .roomLayoutTop:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController(listenForSignals: true) let timelineController = MockTimelineController(listenForSignals: true)
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk]
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
@ -367,7 +373,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -375,7 +382,7 @@ class MockScreen: Identifiable {
case .roomLayoutMiddle: case .roomLayoutMiddle:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController(listenForSignals: true) let timelineController = MockTimelineController(listenForSignals: true)
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk]
timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage]
@ -390,7 +397,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -398,7 +406,7 @@ class MockScreen: Identifiable {
case .roomLayoutBottom: case .roomLayoutBottom:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController(listenForSignals: true) let timelineController = MockTimelineController(listenForSignals: true)
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage] timelineController.incomingItems = [RoomTimelineItemFixtures.incomingMessage]
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
@ -412,7 +420,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -420,7 +429,7 @@ class MockScreen: Identifiable {
case .roomLayoutHighlight: case .roomLayoutHighlight:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.permalinkChunk timelineController.timelineItems = RoomTimelineItemFixtures.permalinkChunk
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: .mockMXCAvatar)), roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: .mockMXCAvatar)),
@ -433,7 +442,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -454,7 +464,7 @@ class MockScreen: Identifiable {
case .roomWithDisclosedPolls: case .roomWithDisclosedPolls:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.disclosedPolls timelineController.timelineItems = RoomTimelineItemFixtures.disclosedPolls
timelineController.incomingItems = [] timelineController.incomingItems = []
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
@ -468,7 +478,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -476,7 +487,7 @@ class MockScreen: Identifiable {
case .roomWithUndisclosedPolls: case .roomWithUndisclosedPolls:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.undisclosedPolls timelineController.timelineItems = RoomTimelineItemFixtures.undisclosedPolls
timelineController.incomingItems = [] timelineController.incomingItems = []
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
@ -490,7 +501,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -498,7 +510,7 @@ class MockScreen: Identifiable {
case .roomWithOutgoingPolls: case .roomWithOutgoingPolls:
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.outgoingPolls timelineController.timelineItems = RoomTimelineItemFixtures.outgoingPolls
timelineController.incomingItems = [] timelineController.incomingItems = []
let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(), let parameters = RoomScreenCoordinatorParameters(clientProxy: ClientProxyMock(),
@ -512,7 +524,8 @@ class MockScreen: Identifiable {
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
composerDraftService: ComposerDraftServiceMock(.init())) composerDraftService: ComposerDraftServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let coordinator = RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
@ -540,7 +553,7 @@ class MockScreen: Identifiable {
appSettings: ServiceLocator.shared.settings), appSettings: ServiceLocator.shared.settings),
bugReportService: BugReportServiceMock(), bugReportService: BugReportServiceMock(),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
roomTimelineControllerFactory: RoomTimelineControllerFactoryMock(configuration: .init()), timelineControllerFactory: TimelineControllerFactoryMock(.init()),
appMediator: appMediator, appMediator: appMediator,
appSettings: appSettings, appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
@ -678,14 +691,14 @@ class MockScreen: Identifiable {
clientProxy.roomForIdentifierReturnValue = .joined(roomProxy) clientProxy.roomForIdentifierReturnValue = .joined(roomProxy)
let timelineController = RoomTimelineController(roomProxy: roomProxy, let timelineController = TimelineController(roomProxy: roomProxy,
timelineProxy: roomProxy.timeline, timelineProxy: roomProxy.timeline,
initialFocussedEventID: nil, initialFocussedEventID: nil,
timelineItemFactory: RoomTimelineItemFactory(userID: "@alice:matrix.org", timelineItemFactory: RoomTimelineItemFactory(userID: "@alice:matrix.org",
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")), stateEventStringBuilder: RoomStateEventStringBuilder(userID: "@alice:matrix.org")),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
appSettings: ServiceLocator.shared.settings) appSettings: ServiceLocator.shared.settings)
let flowCoordinator = UserSessionFlowCoordinator(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let flowCoordinator = UserSessionFlowCoordinator(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
navigationRootCoordinator: navigationRootCoordinator, navigationRootCoordinator: navigationRootCoordinator,
@ -693,7 +706,7 @@ class MockScreen: Identifiable {
appSettings: ServiceLocator.shared.settings), appSettings: ServiceLocator.shared.settings),
bugReportService: BugReportServiceMock(), bugReportService: BugReportServiceMock(),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
roomTimelineControllerFactory: RoomTimelineControllerFactoryMock(configuration: .init(timelineController: timelineController)), timelineControllerFactory: TimelineControllerFactoryMock(.init(timelineController: timelineController)),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: appSettings, appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),

View File

@ -18,7 +18,7 @@ class PillContextTests: XCTestCase {
let subject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([]) let subject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([])
proxyMock.membersPublisher = subject.asCurrentValuePublisher() proxyMock.membersPublisher = subject.asCurrentValuePublisher()
let mock = TimelineViewModel(roomProxy: proxyMock, let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -26,7 +26,8 @@ class PillContextTests: XCTestCase {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
XCTAssertFalse(context.viewState.isOwnMention) XCTAssertFalse(context.viewState.isOwnMention)
@ -47,7 +48,7 @@ class PillContextTests: XCTestCase {
let subject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([]) let subject = CurrentValueSubject<[RoomMemberProxyProtocol], Never>([])
proxyMock.membersPublisher = subject.asCurrentValuePublisher() proxyMock.membersPublisher = subject.asCurrentValuePublisher()
let mock = TimelineViewModel(roomProxy: proxyMock, let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -55,7 +56,8 @@ class PillContextTests: XCTestCase {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
XCTAssertTrue(context.viewState.isOwnMention) XCTAssertTrue(context.viewState.isOwnMention)
@ -66,7 +68,7 @@ class PillContextTests: XCTestCase {
let id = "test_room" let id = "test_room"
let displayName = "Test" let displayName = "Test"
let proxyMock = JoinedRoomProxyMock(.init(id: id, name: displayName, avatarURL: avatarURL)) let proxyMock = JoinedRoomProxyMock(.init(id: id, name: displayName, avatarURL: avatarURL))
let mockController = MockRoomTimelineController() let mockController = MockTimelineController()
mockController.roomProxy = proxyMock mockController.roomProxy = proxyMock
let mock = TimelineViewModel(roomProxy: proxyMock, let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: mockController, timelineController: mockController,
@ -77,7 +79,8 @@ class PillContextTests: XCTestCase {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body)))
XCTAssertTrue(context.viewState.isOwnMention) XCTAssertTrue(context.viewState.isOwnMention)

View File

@ -13,7 +13,7 @@ import Combine
@MainActor @MainActor
class RoomFlowCoordinatorTests: XCTestCase { class RoomFlowCoordinatorTests: XCTestCase {
var clientProxy: ClientProxyMock! var clientProxy: ClientProxyMock!
var timelineControllerFactory: RoomTimelineControllerFactoryMock! var timelineControllerFactory: TimelineControllerFactoryMock!
var roomFlowCoordinator: RoomFlowCoordinator! var roomFlowCoordinator: RoomFlowCoordinator!
var navigationStackCoordinator: NavigationStackCoordinator! var navigationStackCoordinator: NavigationStackCoordinator!
var cancellables = Set<AnyCancellable>() var cancellables = Set<AnyCancellable>()
@ -311,7 +311,7 @@ class RoomFlowCoordinatorTests: XCTestCase {
private func setupRoomFlowCoordinator(asChildFlow: Bool = false, roomType: RoomType? = nil) async { private func setupRoomFlowCoordinator(asChildFlow: Bool = false, roomType: RoomType? = nil) async {
cancellables.removeAll() cancellables.removeAll()
clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
timelineControllerFactory = RoomTimelineControllerFactoryMock(configuration: .init()) timelineControllerFactory = TimelineControllerFactoryMock(.init())
clientProxy.roomPreviewForIdentifierViaClosure = { [roomType] roomID, _ in clientProxy.roomPreviewForIdentifierViaClosure = { [roomType] roomID, _ in
switch roomType { switch roomType {
@ -336,7 +336,7 @@ class RoomFlowCoordinatorTests: XCTestCase {
roomFlowCoordinator = await RoomFlowCoordinator(roomID: roomID, roomFlowCoordinator = await RoomFlowCoordinator(roomID: roomID,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
isChildFlow: asChildFlow, isChildFlow: asChildFlow,
roomTimelineControllerFactory: timelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
navigationStackCoordinator: navigationStackCoordinator, navigationStackCoordinator: navigationStackCoordinator,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings), emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),

View File

@ -13,13 +13,13 @@ import XCTest
class RoomPollsHistoryScreenViewModelTests: XCTestCase { class RoomPollsHistoryScreenViewModelTests: XCTestCase {
var viewModel: RoomPollsHistoryScreenViewModelProtocol! var viewModel: RoomPollsHistoryScreenViewModelProtocol!
var interactionHandler: PollInteractionHandlerMock! var interactionHandler: PollInteractionHandlerMock!
var timelineController: MockRoomTimelineController! var timelineController: MockTimelineController!
override func setUpWithError() throws { override func setUpWithError() throws {
interactionHandler = PollInteractionHandlerMock() interactionHandler = PollInteractionHandlerMock()
timelineController = MockRoomTimelineController() timelineController = MockTimelineController()
viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: interactionHandler, viewModel = RoomPollsHistoryScreenViewModel(pollInteractionHandler: interactionHandler,
roomTimelineController: timelineController, timelineController: timelineController,
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }

View File

@ -66,7 +66,7 @@ class RoomScreenViewModelTests: XCTestCase {
// setup the loaded pinned events injection in the timeline // setup the loaded pinned events injection in the timeline
let pinnedTimelineMock = TimelineProxyMock() let pinnedTimelineMock = TimelineProxyMock()
let pinnedTimelineProviderMock = RoomTimelineProviderMock() let pinnedTimelineProviderMock = TimelineProviderMock()
let providerUpdateSubject = PassthroughSubject<([TimelineItemProxy], PaginationState), Never>() let providerUpdateSubject = PassthroughSubject<([TimelineItemProxy], PaginationState), Never>()
pinnedTimelineProviderMock.underlyingUpdatePublisher = providerUpdateSubject.eraseToAnyPublisher() pinnedTimelineProviderMock.underlyingUpdatePublisher = providerUpdateSubject.eraseToAnyPublisher()
pinnedTimelineMock.timelineProvider = pinnedTimelineProviderMock pinnedTimelineMock.timelineProvider = pinnedTimelineProviderMock
@ -107,7 +107,7 @@ class RoomScreenViewModelTests: XCTestCase {
let roomProxyMock = JoinedRoomProxyMock(.init()) let roomProxyMock = JoinedRoomProxyMock(.init())
// setup a way to inject the mock of the pinned events timeline // setup a way to inject the mock of the pinned events timeline
let pinnedTimelineMock = TimelineProxyMock() let pinnedTimelineMock = TimelineProxyMock()
let pinnedTimelineProviderMock = RoomTimelineProviderMock() let pinnedTimelineProviderMock = TimelineProviderMock()
pinnedTimelineMock.timelineProvider = pinnedTimelineProviderMock pinnedTimelineMock.timelineProvider = pinnedTimelineProviderMock
pinnedTimelineProviderMock.underlyingUpdatePublisher = Empty<([TimelineItemProxy], PaginationState), Never>().eraseToAnyPublisher() pinnedTimelineProviderMock.underlyingUpdatePublisher = Empty<([TimelineItemProxy], PaginationState), Never>().eraseToAnyPublisher()
pinnedTimelineProviderMock.itemProxies = [.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test1")), uniqueID: .init(id: "1"))), pinnedTimelineProviderMock.itemProxies = [.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test1")), uniqueID: .init(id: "1"))),

View File

@ -19,7 +19,7 @@ class TimelineMediaPreviewViewModelTests: XCTestCase {
var context: TimelineMediaPreviewViewModel.Context { viewModel.context } var context: TimelineMediaPreviewViewModel.Context { viewModel.context }
var mediaProvider: MediaProviderMock! var mediaProvider: MediaProviderMock!
var photoLibraryManager: PhotoLibraryManagerMock! var photoLibraryManager: PhotoLibraryManagerMock!
var timelineController: MockRoomTimelineController! var timelineController: MockTimelineController!
func testLoadingItem() async throws { func testLoadingItem() async throws {
// Given a fresh view model. // Given a fresh view model.
@ -274,7 +274,7 @@ class TimelineMediaPreviewViewModelTests: XCTestCase {
private func setupViewModel(initialItemIndex: Int = 0, photoLibraryAuthorizationDenied: Bool = false) { private func setupViewModel(initialItemIndex: Int = 0, photoLibraryAuthorizationDenied: Bool = false) {
let initialItems = makeItems() let initialItems = makeItems()
timelineController = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen)) timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen))
timelineController.timelineItems = initialItems timelineController.timelineItems = initialItems
mediaProvider = MediaProviderMock(configuration: .init()) mediaProvider = MediaProviderMock(configuration: .init())

View File

@ -40,7 +40,7 @@ class TimelineViewModelTests: XCTestCase {
] ]
// When showing them in a timeline. // When showing them in a timeline.
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = items timelineController.timelineItems = items
let viewModel = makeViewModel(timelineController: timelineController) let viewModel = makeViewModel(timelineController: timelineController)
@ -68,7 +68,7 @@ class TimelineViewModelTests: XCTestCase {
] ]
// When showing them in a timeline. // When showing them in a timeline.
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = items timelineController.timelineItems = items
let viewModel = makeViewModel(timelineController: timelineController) let viewModel = makeViewModel(timelineController: timelineController)
@ -94,7 +94,7 @@ class TimelineViewModelTests: XCTestCase {
] ]
// When showing them in a timeline. // When showing them in a timeline.
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = items timelineController.timelineItems = items
let viewModel = makeViewModel(timelineController: timelineController) let viewModel = makeViewModel(timelineController: timelineController)
@ -117,7 +117,7 @@ class TimelineViewModelTests: XCTestCase {
] ]
// When showing them in a timeline. // When showing them in a timeline.
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = items timelineController.timelineItems = items
let viewModel = makeViewModel(timelineController: timelineController) let viewModel = makeViewModel(timelineController: timelineController)
@ -140,7 +140,7 @@ class TimelineViewModelTests: XCTestCase {
] ]
// When showing them in a timeline. // When showing them in a timeline.
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = items timelineController.timelineItems = items
let viewModel = makeViewModel(timelineController: timelineController) let viewModel = makeViewModel(timelineController: timelineController)
@ -157,7 +157,7 @@ class TimelineViewModelTests: XCTestCase {
let items = [TextRoomTimelineItem(eventID: "t1"), let items = [TextRoomTimelineItem(eventID: "t1"),
TextRoomTimelineItem(eventID: "t2"), TextRoomTimelineItem(eventID: "t2"),
TextRoomTimelineItem(eventID: "t3")] TextRoomTimelineItem(eventID: "t3")]
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = items timelineController.timelineItems = items
let viewModel = makeViewModel(timelineController: timelineController) let viewModel = makeViewModel(timelineController: timelineController)
@ -181,7 +181,7 @@ class TimelineViewModelTests: XCTestCase {
let items = [TextRoomTimelineItem(eventID: "t1"), let items = [TextRoomTimelineItem(eventID: "t1"),
TextRoomTimelineItem(eventID: "t2"), TextRoomTimelineItem(eventID: "t2"),
TextRoomTimelineItem(eventID: "t3")] TextRoomTimelineItem(eventID: "t3")]
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = items timelineController.timelineItems = items
let viewModel = makeViewModel(timelineController: timelineController) let viewModel = makeViewModel(timelineController: timelineController)
@ -205,7 +205,7 @@ class TimelineViewModelTests: XCTestCase {
let items = [TextRoomTimelineItem(eventID: "t1"), let items = [TextRoomTimelineItem(eventID: "t1"),
TextRoomTimelineItem(eventID: "t2"), TextRoomTimelineItem(eventID: "t2"),
TextRoomTimelineItem(eventID: "t3")] TextRoomTimelineItem(eventID: "t3")]
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = items timelineController.timelineItems = items
let viewModel = makeViewModel(timelineController: timelineController) let viewModel = makeViewModel(timelineController: timelineController)
@ -230,7 +230,7 @@ class TimelineViewModelTests: XCTestCase {
} }
func testInitialFocusViewState() async throws { func testInitialFocusViewState() async throws {
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
let viewModel = makeViewModel(focussedEventID: "t10", timelineController: timelineController) let viewModel = makeViewModel(focussedEventID: "t10", timelineController: timelineController)
XCTAssertEqual(viewModel.context.viewState.timelineState.focussedEvent, .init(eventID: "t10", appearance: .immediate)) XCTAssertEqual(viewModel.context.viewState.timelineState.focussedEvent, .init(eventID: "t10", appearance: .immediate))
@ -289,13 +289,13 @@ class TimelineViewModelTests: XCTestCase {
private func readReceiptsConfiguration(with items: [RoomTimelineItemProtocol]) -> (TimelineViewModel, private func readReceiptsConfiguration(with items: [RoomTimelineItemProtocol]) -> (TimelineViewModel,
JoinedRoomProxyMock, JoinedRoomProxyMock,
TimelineProxyMock, TimelineProxyMock,
MockRoomTimelineController) { MockTimelineController) {
let roomProxy = JoinedRoomProxyMock(.init(name: "")) let roomProxy = JoinedRoomProxyMock(.init(name: ""))
let timelineProxy = TimelineProxyMock() let timelineProxy = TimelineProxyMock()
roomProxy.timeline = timelineProxy roomProxy.timeline = timelineProxy
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineProxy.sendReadReceiptForTypeReturnValue = .success(()) timelineProxy.sendReadReceiptForTypeReturnValue = .success(())
@ -311,7 +311,8 @@ class TimelineViewModelTests: XCTestCase {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
return (viewModel, roomProxy, timelineProxy, timelineController) return (viewModel, roomProxy, timelineProxy, timelineController)
} }
@ -325,7 +326,7 @@ class TimelineViewModelTests: XCTestCase {
let id = message.id let id = message.id
// When showing them in a timeline. // When showing them in a timeline.
let timelineController = MockRoomTimelineController() let timelineController = MockTimelineController()
timelineController.timelineItems = [message] timelineController.timelineItems = [message]
let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", members: [RoomMemberProxyMock.mockAlice, RoomMemberProxyMock.mockCharlie])), let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", members: [RoomMemberProxyMock.mockAlice, RoomMemberProxyMock.mockCharlie])),
timelineController: timelineController, timelineController: timelineController,
@ -336,7 +337,8 @@ class TimelineViewModelTests: XCTestCase {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let deferred = deferFulfillment(viewModel.context.$viewState) { value in let deferred = deferFulfillment(viewModel.context.$viewState) { value in
value.bindings.readReceiptsSummaryInfo?.orderedReceipts == receipts value.bindings.readReceiptsSummaryInfo?.orderedReceipts == receipts
@ -356,7 +358,7 @@ class TimelineViewModelTests: XCTestCase {
roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher() roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher()
let viewModel = TimelineViewModel(roomProxy: roomProxyMock, let viewModel = TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -364,7 +366,8 @@ class TimelineViewModelTests: XCTestCase {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
XCTAssertEqual(configuration.pinnedEventIDs, viewModel.context.viewState.pinnedEventIDs) XCTAssertEqual(configuration.pinnedEventIDs, viewModel.context.viewState.pinnedEventIDs)
configuration.pinnedEventIDs = ["test1", "test2"] configuration.pinnedEventIDs = ["test1", "test2"]
@ -382,7 +385,7 @@ class TimelineViewModelTests: XCTestCase {
roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher() roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher()
let viewModel = TimelineViewModel(roomProxy: roomProxyMock, let viewModel = TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockRoomTimelineController(), timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
@ -390,7 +393,8 @@ class TimelineViewModelTests: XCTestCase {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
var deferred = deferFulfillment(viewModel.context.$viewState) { value in var deferred = deferFulfillment(viewModel.context.$viewState) { value in
value.canCurrentUserPin value.canCurrentUserPin
@ -409,7 +413,7 @@ class TimelineViewModelTests: XCTestCase {
private func makeViewModel(roomProxy: JoinedRoomProxyProtocol? = nil, private func makeViewModel(roomProxy: JoinedRoomProxyProtocol? = nil,
focussedEventID: String? = nil, focussedEventID: String? = nil,
timelineController: RoomTimelineControllerProtocol) -> TimelineViewModel { timelineController: TimelineControllerProtocol) -> TimelineViewModel {
TimelineViewModel(roomProxy: roomProxy ?? JoinedRoomProxyMock(.init(name: "")), TimelineViewModel(roomProxy: roomProxy ?? JoinedRoomProxyMock(.init(name: "")),
focussedEventID: focussedEventID, focussedEventID: focussedEventID,
timelineController: timelineController, timelineController: timelineController,
@ -420,7 +424,8 @@ class TimelineViewModelTests: XCTestCase {
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics, analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings)) emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
} }

View File

@ -13,7 +13,7 @@ import Combine
@MainActor @MainActor
class UserSessionFlowCoordinatorTests: XCTestCase { class UserSessionFlowCoordinatorTests: XCTestCase {
var clientProxy: ClientProxyMock! var clientProxy: ClientProxyMock!
var timelineControllerFactory: RoomTimelineControllerFactoryMock! var timelineControllerFactory: TimelineControllerFactoryMock!
var userSessionFlowCoordinator: UserSessionFlowCoordinator! var userSessionFlowCoordinator: UserSessionFlowCoordinator!
var navigationRootCoordinator: NavigationRootCoordinator! var navigationRootCoordinator: NavigationRootCoordinator!
var notificationManager: NotificationManagerMock! var notificationManager: NotificationManagerMock!
@ -27,7 +27,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase {
override func setUp() async throws { override func setUp() async throws {
cancellables.removeAll() cancellables.removeAll()
clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
timelineControllerFactory = RoomTimelineControllerFactoryMock(configuration: .init()) timelineControllerFactory = TimelineControllerFactoryMock(.init())
navigationRootCoordinator = NavigationRootCoordinator() navigationRootCoordinator = NavigationRootCoordinator()
@ -38,7 +38,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase {
appLockService: AppLockServiceMock(), appLockService: AppLockServiceMock(),
bugReportService: BugReportServiceMock(), bugReportService: BugReportServiceMock(),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
roomTimelineControllerFactory: timelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings, appSettings: ServiceLocator.shared.settings,
appHooks: AppHooks(), appHooks: AppHooks(),
@ -211,8 +211,8 @@ class UserSessionFlowCoordinatorTests: XCTestCase {
XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator)
XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0)
XCTAssertNotNil(detailCoordinator) XCTAssertNotNil(detailCoordinator)
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 1) XCTAssertEqual(timelineControllerFactory.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 1)
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "1") XCTAssertEqual(timelineControllerFactory.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "1")
// A child event route should push a new room screen onto the stack and focus on the event. // A child event route should push a new room screen onto the stack and focus on the event.
userSessionFlowCoordinator.handleAppRoute(.childEvent(eventID: "2", roomID: "2", via: []), animated: true) userSessionFlowCoordinator.handleAppRoute(.childEvent(eventID: "2", roomID: "2", via: []), animated: true)
@ -221,24 +221,24 @@ class UserSessionFlowCoordinatorTests: XCTestCase {
XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 1) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 1)
XCTAssertTrue(detailNavigationStack?.stackCoordinators.first is RoomScreenCoordinator) XCTAssertTrue(detailNavigationStack?.stackCoordinators.first is RoomScreenCoordinator)
XCTAssertNotNil(detailCoordinator) XCTAssertNotNil(detailCoordinator)
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 2) XCTAssertEqual(timelineControllerFactory.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 2)
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "2") XCTAssertEqual(timelineControllerFactory.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "2")
// A subsequent regular event route should clear the stack and set the new room as the root of the stack. // A subsequent regular event route should clear the stack and set the new room as the root of the stack.
try await process(route: .event(eventID: "3", roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3")) try await process(route: .event(eventID: "3", roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3"))
XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator)
XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0)
XCTAssertNotNil(detailCoordinator) XCTAssertNotNil(detailCoordinator)
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 3) XCTAssertEqual(timelineControllerFactory.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 3)
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "3") XCTAssertEqual(timelineControllerFactory.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "3")
// A regular event route for the same room should set a new instance of the room as the root of the stack. // A regular event route for the same room should set a new instance of the room as the root of the stack.
try await process(route: .event(eventID: "4", roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3")) try await process(route: .event(eventID: "4", roomID: "3", via: []), expectedState: .roomList(selectedRoomID: "3"))
XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator) XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator)
XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0) XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0)
XCTAssertNotNil(detailCoordinator) XCTAssertNotNil(detailCoordinator)
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 4) XCTAssertEqual(timelineControllerFactory.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderCallsCount, 4)
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "4", XCTAssertEqual(timelineControllerFactory.buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReceivedArguments?.initialFocussedEventID, "4",
"A new timeline should be created for the same room ID, so that the screen isn't stale while loading.") "A new timeline should be created for the same room ID, so that the screen isn't stale while loading.")
} }