diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 561014914e..0d60d62c9d 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 56; objects = { /* Begin PBXAggregateTarget section */ @@ -731,6 +731,8 @@ A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */; }; A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; + A7580E042C622A5300A0991D /* PinnedEventsBannerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7580E032C622A5300A0991D /* PinnedEventsBannerStateTests.swift */; }; + A75B3BF22C61460B000CE956 /* NetworkMonitorMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A75B3BF12C61460B000CE956 /* NetworkMonitorMock.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; A851635B3255C6DC07034A12 /* RoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */; }; @@ -1174,13 +1176,13 @@ 033DB41C51865A2E83174E87 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 035177BCD8E8308B098AC3C2 /* WindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; 0376C429FAB1687C3D905F3E /* MockCoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCoder.swift; sourceTree = ""; }; - 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; + 0392E3FDE372C9B56FEEED8B /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; 03FABD73FD8086EFAB699F42 /* MediaUploadPreviewScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModelTests.swift; sourceTree = ""; }; 044E501B8331B339874D1B96 /* CompoundIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompoundIcon.swift; sourceTree = ""; }; 045253F9967A535EE5B16691 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; 046C0D3F53B0B5EF0A1F5BEA /* RoomSummaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryTests.swift; sourceTree = ""; }; - 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = ""; }; 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = ""; }; @@ -1240,7 +1242,7 @@ 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = ""; }; 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAttachmentPicker.swift; sourceTree = ""; }; 12F1E7F9C2BE8BB751037826 /* WaitlistScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistScreenCoordinator.swift; sourceTree = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; sourceTree = ""; }; 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = ""; }; 136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenModels.swift; sourceTree = ""; }; 13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -1331,7 +1333,7 @@ 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = ""; }; 25F8664F1FB95AF3C4202478 /* PollFormScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenCoordinator.swift; sourceTree = ""; }; 260004737C573A56FA01E86E /* Encodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encodable.swift; sourceTree = ""; }; - 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; 26B0A96B8FE4849227945067 /* VoiceMessageRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorder.swift; sourceTree = ""; }; 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockServiceProtocol.swift; sourceTree = ""; }; 2721D7B051F0159AA919DA05 /* RoomChangePermissionsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangePermissionsScreenViewModelProtocol.swift; sourceTree = ""; }; @@ -1396,7 +1398,7 @@ 3558A15CFB934F9229301527 /* RestorationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationToken.swift; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; 35FA991289149D31F4286747 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerURLBuildersTests.swift; sourceTree = ""; }; 37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiItem.swift; sourceTree = ""; }; @@ -1745,7 +1747,7 @@ 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateEventStringBuilder.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; 8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreen.swift; sourceTree = ""; }; 8F21ED7205048668BEB44A38 /* AppActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppActivityView.swift; sourceTree = ""; }; 8F6210134203BE1F2DD5C679 /* RoomDirectoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectoryCell.swift; sourceTree = ""; }; @@ -1840,6 +1842,8 @@ A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = ""; }; A6C11AD9813045E44F950410 /* ElementCallWidgetDriverProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallWidgetDriverProtocol.swift; sourceTree = ""; }; A73A07BAEDD74C48795A996A /* AsyncSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncSequence.swift; sourceTree = ""; }; + A7580E032C622A5300A0991D /* PinnedEventsBannerStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsBannerStateTests.swift; sourceTree = ""; }; + A75B3BF12C61460B000CE956 /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = ""; }; A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftServiceProtocol.swift; sourceTree = ""; }; @@ -1909,7 +1913,7 @@ B53AC78E49A297AC1D72A7CF /* AppMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMediator.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = ""; }; B63B69F9A2BC74DD40DC75C8 /* AdvancedSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModel.swift; sourceTree = ""; }; B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = ""; }; @@ -2022,7 +2026,7 @@ CE47A97726F0675DEE387BF9 /* TypingIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingIndicatorView.swift; sourceTree = ""; }; CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = ""; }; CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = ""; }; - CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = ""; }; D086854995173E897F993C26 /* AdvancedSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModelProtocol.swift; sourceTree = ""; }; D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = ""; }; @@ -2150,7 +2154,7 @@ ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; ED33988DA4FD4FC666800106 /* SessionVerificationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModel.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = ""; }; EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = ""; }; @@ -2173,7 +2177,7 @@ F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; - F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; + F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = ""; }; F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = ""; }; F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = ""; }; @@ -2773,6 +2777,7 @@ AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */, F4469F6AE311BDC439B3A5EC /* UserSessionMock.swift */, B23135B06B044CB811139D2F /* Generated */, + A75B3BF12C61460B000CE956 /* NetworkMonitorMock.swift */, ); path = Mocks; sourceTree = ""; @@ -3738,6 +3743,7 @@ 7583EAC171059A86B767209F /* MediaProvider */, 7DBC911559934065993A5FF4 /* NotificationManager */, 1C62F5382CC9D9F7DCEC344A /* UserDiscoveryService */, + A7580E032C622A5300A0991D /* PinnedEventsBannerStateTests.swift */, ); path = Sources; sourceTree = ""; @@ -5979,6 +5985,7 @@ 04F17DE71A50206336749BAC /* UserPreferenceTests.swift in Sources */, 73F547BEB41D3DAFAAF6E0AF /* UserProfileScreenViewModelTests.swift in Sources */, 627139A3D79F032BA81E3A53 /* UserSessionFlowCoordinatorTests.swift in Sources */, + A7580E042C622A5300A0991D /* PinnedEventsBannerStateTests.swift in Sources */, 81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */, 21AFEFB8CEFE56A3811A1F5B /* VoiceMessageCacheTests.swift in Sources */, 44BDD670FF9095ACE240A3A2 /* VoiceMessageMediaManagerTests.swift in Sources */, @@ -6005,6 +6012,7 @@ 34433A509DFEC93579B3B35B /* AdvancedSettingsScreen.swift in Sources */, 4557192F5B15A8D9BB920232 /* AdvancedSettingsScreenCoordinator.swift in Sources */, 0A194F5E70B5A628C1BF4476 /* AdvancedSettingsScreenModels.swift in Sources */, + A75B3BF22C61460B000CE956 /* NetworkMonitorMock.swift in Sources */, B879446FD8E65A711EF8F9F7 /* AdvancedSettingsScreenViewModel.swift in Sources */, 62910B515BCB4B455E24D7C1 /* AdvancedSettingsScreenViewModelProtocol.swift in Sources */, 53C1E7F6A7D6409D89F36ED7 /* AggregatedReactionMock.swift in Sources */, @@ -7016,9 +7024,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -7067,9 +7073,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7095,9 +7099,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_MAIN_APP", - ); + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -7342,9 +7344,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; - OTHER_SWIFT_FLAGS = ( - "-DIS_NSE", - ); + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -7561,7 +7561,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.31; + version = 1.0.32; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3d793291f8..fd74b811de 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "8e2b4049fb492dcf5b0c796784b7aa7a3c099943", - "version" : "1.0.31" + "revision" : "9a9d116e5f00b31ad4f727d0875fed13a230806b", + "version" : "1.0.32" } }, { diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index bc19676b60..fe2d2b9290 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -318,6 +318,7 @@ "screen_room_mentions_at_room_subtitle" = "Notify the whole room"; "screen_room_pinned_banner_indicator" = "%1$@ of %2$@"; "screen_room_pinned_banner_indicator_description" = "%1$@ Pinned messages"; +"screen_room_pinned_banner_loading_description" = "Loading messageā€¦"; "screen_room_pinned_banner_view_all_button_title" = "View All"; "screen_account_provider_change" = "Change account provider"; "screen_account_provider_form_hint" = "Homeserver address"; @@ -851,6 +852,12 @@ "state_event_room_name_removed_by_you" = "You removed the room name"; "state_event_room_none" = "%1$@ made no changes"; "state_event_room_none_by_you" = "You made no changes"; +"state_event_room_pinned_events_changed" = "%1$@ changed the pinned messages"; +"state_event_room_pinned_events_changed_by_you" = "You changed the pinned messages"; +"state_event_room_pinned_events_pinned" = "%1$@ pinned a message"; +"state_event_room_pinned_events_pinned_by_you" = "You pinned a message"; +"state_event_room_pinned_events_unpinned" = "%1$@ unpinned a message"; +"state_event_room_pinned_events_unpinned_by_you" = "You unpinned a message"; "state_event_room_reject" = "%1$@ rejected the invitation"; "state_event_room_reject_by_you" = "You rejected the invitation"; "state_event_room_remove" = "%1$@ removed %2$@"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 24b644e5a2..e798ad2619 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1675,6 +1675,8 @@ internal enum L10n { internal static func screenRoomPinnedBannerIndicatorDescription(_ p1: Any) -> String { return L10n.tr("Localizable", "screen_room_pinned_banner_indicator_description", String(describing: p1)) } + /// Loading messageā€¦ + internal static var screenRoomPinnedBannerLoadingDescription: String { return L10n.tr("Localizable", "screen_room_pinned_banner_loading_description") } /// View All internal static var screenRoomPinnedBannerViewAllButtonTitle: String { return L10n.tr("Localizable", "screen_room_pinned_banner_view_all_button_title") } /// Send again @@ -2111,6 +2113,24 @@ internal enum L10n { } /// You made no changes internal static var stateEventRoomNoneByYou: String { return L10n.tr("Localizable", "state_event_room_none_by_you") } + /// %1$@ changed the pinned messages + internal static func stateEventRoomPinnedEventsChanged(_ p1: Any) -> String { + return L10n.tr("Localizable", "state_event_room_pinned_events_changed", String(describing: p1)) + } + /// You changed the pinned messages + internal static var stateEventRoomPinnedEventsChangedByYou: String { return L10n.tr("Localizable", "state_event_room_pinned_events_changed_by_you") } + /// %1$@ pinned a message + internal static func stateEventRoomPinnedEventsPinned(_ p1: Any) -> String { + return L10n.tr("Localizable", "state_event_room_pinned_events_pinned", String(describing: p1)) + } + /// You pinned a message + internal static var stateEventRoomPinnedEventsPinnedByYou: String { return L10n.tr("Localizable", "state_event_room_pinned_events_pinned_by_you") } + /// %1$@ unpinned a message + internal static func stateEventRoomPinnedEventsUnpinned(_ p1: Any) -> String { + return L10n.tr("Localizable", "state_event_room_pinned_events_unpinned", String(describing: p1)) + } + /// You unpinned a message + internal static var stateEventRoomPinnedEventsUnpinnedByYou: String { return L10n.tr("Localizable", "state_event_room_pinned_events_unpinned_by_you") } /// %1$@ rejected the invitation internal static func stateEventRoomReject(_ p1: Any) -> String { return L10n.tr("Localizable", "state_event_room_reject", String(describing: p1)) diff --git a/ElementX/Sources/Mocks/NetworkMonitorMock.swift b/ElementX/Sources/Mocks/NetworkMonitorMock.swift new file mode 100644 index 0000000000..cb9cecf932 --- /dev/null +++ b/ElementX/Sources/Mocks/NetworkMonitorMock.swift @@ -0,0 +1,26 @@ +// +// Copyright 2024 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation + +extension NetworkMonitorMock { + static var `default`: NetworkMonitorMock { + let mock = NetworkMonitorMock() + mock.underlyingReachabilityPublisher = .init(.init(.reachable)) + return mock + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift index 1e4058e6e4..c02b6c27e2 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift @@ -67,6 +67,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol { mediaPlayerProvider: parameters.mediaPlayerProvider, voiceMessageMediaManager: parameters.voiceMessageMediaManager, userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: parameters.appMediator, appSettings: parameters.appSettings, analyticsService: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift index 9a52fde414..41e46be6f5 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift @@ -177,10 +177,10 @@ struct RoomScreenViewState: BindableState { // It's updated from the room info, so it's faster than using the timeline var pinnedEventIDs: Set = [] // This is used to control the banner - var pinnedEventsState = PinnedEventsState() + var pinnedEventsBannerState: PinnedEventsBannerState = .loading(numbersOfEvents: 0) var shouldShowPinnedEventsBanner: Bool { - isPinningEnabled && !pinnedEventsState.pinnedEventContents.isEmpty && lastScrollDirection != .top + isPinningEnabled && !pinnedEventsBannerState.isEmpty && lastScrollDirection != .top } var canJoinCall = false @@ -306,11 +306,12 @@ struct PinnedEventsState: Equatable { var pinnedEventContents: OrderedDictionary = [:] { didSet { if selectedPinEventID == nil, !pinnedEventContents.keys.isEmpty { + // The default selected event should always be the last one. selectedPinEventID = pinnedEventContents.keys.last } else if pinnedEventContents.isEmpty { selectedPinEventID = nil } else if let selectedPinEventID, !pinnedEventContents.keys.set.contains(selectedPinEventID) { - self.selectedPinEventID = pinnedEventContents.firstNonNil { $0.key } + self.selectedPinEventID = pinnedEventContents.keys.last } } } @@ -326,30 +327,112 @@ struct PinnedEventsState: Equatable { } var selectedPinContent: AttributedString { - guard let selectedPinEventID, - var content = pinnedEventContents[selectedPinEventID] else { - return AttributedString() + var content = AttributedString(" ") + if let selectedPinEventID, + var pinnedEventContent = pinnedEventContents[selectedPinEventID] { + content = pinnedEventContent } content.font = .compound.bodyMD return content } + mutating func nextPin() { + guard !pinnedEventContents.isEmpty else { + return + } + let currentIndex = selectedPinIndex + let nextIndex = (currentIndex + 1) % pinnedEventContents.count + selectedPinEventID = pinnedEventContents.keys[nextIndex] + } +} + +enum PinnedEventsBannerState: Equatable { + case loading(numbersOfEvents: Int) + case loaded(state: PinnedEventsState) + + var isEmpty: Bool { + switch self { + case .loaded(let state): + return state.pinnedEventContents.isEmpty + case .loading(let numberOfEvents): + return numberOfEvents == 0 + } + } + + var isLoading: Bool { + switch self { + case .loading: + return true + default: + return false + } + } + + var selectedPinEventID: String? { + switch self { + case .loaded(let state): + return state.selectedPinEventID + default: + return nil + } + } + + var count: Int { + switch self { + case .loaded(let state): + return state.pinnedEventContents.count + case .loading(let numberOfEvents): + return numberOfEvents + } + } + + var selectedPinIndex: Int { + switch self { + case .loaded(let state): + return state.selectedPinIndex + case .loading(let numbersOfEvents): + // We always want the index to be the last one when loading, since is the default one. + return numbersOfEvents - 1 + } + } + + var displayedMessage: AttributedString { + switch self { + case .loading: + return AttributedString(L10n.screenRoomPinnedBannerLoadingDescription) + case .loaded(let state): + return state.selectedPinContent + } + } + var bannerIndicatorDescription: AttributedString { let index = selectedPinIndex + 1 let boldPlaceholder = "{bold}" var finalString = AttributedString(L10n.screenRoomPinnedBannerIndicatorDescription(boldPlaceholder)) - var boldString = AttributedString(L10n.screenRoomPinnedBannerIndicator(index, pinnedEventContents.count)) + var boldString = AttributedString(L10n.screenRoomPinnedBannerIndicator(index, count)) boldString.bold() finalString.replace(boldPlaceholder, with: boldString) return finalString } mutating func nextPin() { - guard !pinnedEventContents.isEmpty else { - return + switch self { + case .loaded(var state): + state.nextPin() + self = .loaded(state: state) + default: + break + } + } + + mutating func setPinnedEventContents(_ pinnedEventContents: OrderedDictionary) { + switch self { + case .loading: + // The default selected event should always be the last one. + self = .loaded(state: .init(pinnedEventContents: pinnedEventContents, selectedPinEventID: pinnedEventContents.keys.last)) + case .loaded(var state): + state.pinnedEventContents = pinnedEventContents + self = .loaded(state: state) } - let currentIndex = selectedPinIndex - let nextIndex = (currentIndex + 1) % pinnedEventContents.count - selectedPinEventID = pinnedEventContents.keys[nextIndex] } } diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index 2e282300b7..cf4a204d1f 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -33,6 +33,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol private let timelineController: RoomTimelineControllerProtocol private let mediaPlayerProvider: MediaPlayerProviderProtocol private let userIndicatorController: UserIndicatorControllerProtocol + private let networkMonitor: NetworkMonitorProtocol private let appMediator: AppMediatorProtocol private let appSettings: AppSettings private let analyticsService: AnalyticsService @@ -49,6 +50,25 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol private var paginateBackwardsTask: Task? private var paginateForwardsTask: Task? + private var pinnedEventsTimelineProviderSetupTask: Task? + + private var pinnedEventsTimelineProvider: RoomTimelineProviderProtocol? { + didSet { + guard let pinnedEventsTimelineProvider else { + return + } + + buildPinnedEventContent(timelineItems: pinnedEventsTimelineProvider.itemProxies) + pinnedEventsTimelineProvider.updatePublisher + // When pinning or unpinning an item, the timeline might return empty for a short while, so we need to debounce it to prevent weird UI behaviours like the banner disappearing + .debounce(for: .milliseconds(100), scheduler: DispatchQueue.main) + .sink { [weak self] updatedItems, _ in + guard let self else { return } + buildPinnedEventContent(timelineItems: updatedItems) + } + .store(in: &cancellables) + } + } init(roomProxy: RoomProxyProtocol, focussedEventID: String? = nil, @@ -57,6 +77,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol mediaPlayerProvider: MediaPlayerProviderProtocol, voiceMessageMediaManager: VoiceMessageMediaManagerProtocol, userIndicatorController: UserIndicatorControllerProtocol, + networkMonitor: NetworkMonitorProtocol, appMediator: AppMediatorProtocol, appSettings: AppSettings, analyticsService: AnalyticsService) { @@ -67,6 +88,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol self.analyticsService = analyticsService self.userIndicatorController = userIndicatorController self.appMediator = appMediator + self.networkMonitor = networkMonitor pinnedEventStringBuilder = .pinnedEventStringBuilder(userID: roomProxy.ownUserID) let voiceMessageRecorder = VoiceMessageRecorder(audioRecorder: AudioRecorder(), mediaPlayerProvider: mediaPlayerProvider) @@ -127,22 +149,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol } } - Task { - guard let pinnedEventsTimelineProvider = await roomProxy.pinnedEventsTimeline?.timelineProvider else { - return - } - - buildPinnedEventContent(timelineItems: pinnedEventsTimelineProvider.itemProxies) - - pinnedEventsTimelineProvider.updatePublisher - // When pinning or unpinning an item, the timeline might return empty for a short while, so we need to debounce it to prevent weird UI behaviours like the banner disappearing - .debounce(for: .milliseconds(100), scheduler: DispatchQueue.main) - .sink { [weak self] updatedItems, _ in - guard let self else { return } - buildPinnedEventContent(timelineItems: updatedItems) - } - .store(in: &cancellables) - } + setupPinnedEventsTimelineProviderIfNeeded() } // MARK: - Public @@ -218,10 +225,10 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol case let .hasScrolled(direction): state.lastScrollDirection = direction case .tappedPinnedEventsBanner: - if let eventID = state.pinnedEventsState.selectedPinEventID { + if let eventID = state.pinnedEventsBannerState.selectedPinEventID { Task { await focusOnEvent(eventID: eventID) } } - state.pinnedEventsState.nextPin() + state.pinnedEventsBannerState.nextPin() case .viewAllPins: // TODO: Implement break @@ -444,27 +451,17 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol return } // If the subscription has sent a value before the Task has started it might be lost, so before entering the loop we always do an update. - await state.pinnedEventIDs = roomProxy.pinnedEventIDs + await updatePinnedEventIDs() for await _ in roomInfoSubscription.receive(on: DispatchQueue.main).values { guard !Task.isCancelled else { return } - await state.pinnedEventIDs = roomProxy.pinnedEventIDs + await updatePinnedEventIDs() } } .store(in: &cancellables) - appSettings.$sharePresence - .weakAssign(to: \.state.showReadReceipts, on: self) - .store(in: &cancellables) - - appSettings.$viewSourceEnabled - .weakAssign(to: \.state.isViewSourceEnabled, on: self) - .store(in: &cancellables) - - appSettings.$pinningEnabled - .weakAssign(to: \.state.isPinningEnabled, on: self) - .store(in: &cancellables) + setupAppSettingsSubscriptions() roomProxy.membersPublisher .receive(on: DispatchQueue.main) @@ -511,6 +508,56 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol } } .store(in: &cancellables) + + networkMonitor.reachabilityPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] networkState in + if networkState == .reachable { + self?.setupPinnedEventsTimelineProviderIfNeeded() + } + } + .store(in: &cancellables) + } + + private func setupAppSettingsSubscriptions() { + appSettings.$sharePresence + .weakAssign(to: \.state.showReadReceipts, on: self) + .store(in: &cancellables) + + appSettings.$viewSourceEnabled + .weakAssign(to: \.state.isViewSourceEnabled, on: self) + .store(in: &cancellables) + + appSettings.$pinningEnabled + .weakAssign(to: \.state.isPinningEnabled, on: self) + .store(in: &cancellables) + } + + private func setupPinnedEventsTimelineProviderIfNeeded() { + guard pinnedEventsTimelineProvider == nil, + pinnedEventsTimelineProviderSetupTask == nil else { + return + } + + pinnedEventsTimelineProviderSetupTask = Task { [weak self] in + guard let self else { return } + + guard let pinnedEventsTimelineProvider = await roomProxy.pinnedEventsTimeline?.timelineProvider else { + pinnedEventsTimelineProviderSetupTask = nil + return + } + + self.pinnedEventsTimelineProvider = pinnedEventsTimelineProvider + } + } + + private func updatePinnedEventIDs() async { + let pinnedEventIDs = await roomProxy.pinnedEventIDs + // Only update the loading state of the banner + if state.pinnedEventsBannerState.isLoading { + state.pinnedEventsBannerState = .loading(numbersOfEvents: pinnedEventIDs.count) + } + state.pinnedEventIDs = pinnedEventIDs } private func setupDirectRoomSubscriptionsIfNeeded() { @@ -676,7 +723,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol private func buildPinnedEventContent(timelineItems: [TimelineItemProxy]) { var pinnedEventContents = OrderedDictionary() - for item in timelineItems { + for item in timelineItems.reversed() { // Only remote events are pinned if case let .event(event) = item, let eventID = event.id.eventID { @@ -685,7 +732,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol } } - state.pinnedEventsState.pinnedEventContents = pinnedEventContents + state.pinnedEventsBannerState.setPinnedEventContents(pinnedEventContents) } private func buildTimelineViews(timelineItems: [RoomTimelineItemProtocol], isSwitchingTimelines: Bool = false) { @@ -906,6 +953,7 @@ extension RoomScreenViewModel { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsBannerView.swift b/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsBannerView.swift index f022b46f0e..8cb77c8b0f 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsBannerView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/PinnedItemsBanner/PinnedItemsBannerView.swift @@ -18,7 +18,7 @@ import Compound import SwiftUI struct PinnedItemsBannerView: View { - let pinnedEventsState: PinnedEventsState + let state: PinnedEventsBannerState let onMainButtonTap: () -> Void let onViewAllButtonTap: () -> Void @@ -38,7 +38,7 @@ struct PinnedItemsBannerView: View { Button { onMainButtonTap() } label: { HStack(spacing: 0) { HStack(spacing: 10) { - PinnedItemsIndicatorView(pinIndex: pinnedEventsState.selectedPinIndex, pinsCount: pinnedEventsState.pinnedEventContents.count) + PinnedItemsIndicatorView(pinIndex: state.selectedPinIndex, pinsCount: state.count) .accessibilityHidden(true) CompoundIcon(\.pinSolid, size: .small, relativeTo: .compound.bodyMD) .foregroundColor(Color.compound.iconSecondaryAlpha) @@ -48,26 +48,34 @@ struct PinnedItemsBannerView: View { .frame(maxWidth: .infinity, alignment: .leading) } } + .disabled(state.isLoading) .accessibilityElement(children: .contain) } + @ViewBuilder private var viewAllButton: some View { - Button { onViewAllButtonTap() } label: { - Text(L10n.screenRoomPinnedBannerViewAllButtonTitle) - .font(.compound.bodyMDSemibold) - .foregroundStyle(Color.compound.textPrimary) + switch state { + case .loaded: + Button { onViewAllButtonTap() } label: { + Text(L10n.screenRoomPinnedBannerViewAllButtonTitle) + .font(.compound.bodyMDSemibold) + .foregroundStyle(Color.compound.textPrimary) + .padding(.horizontal, 16) + .padding(.vertical, 5) + } + case .loading: + ProgressView() .padding(.horizontal, 16) - .padding(.vertical, 5) } } private var content: some View { VStack(alignment: .leading, spacing: 0) { - Text(pinnedEventsState.bannerIndicatorDescription) + Text(state.bannerIndicatorDescription) .font(.compound.bodySM) .foregroundColor(.compound.textActionAccent) .lineLimit(1) - Text(pinnedEventsState.selectedPinContent) + Text(state.displayedMessage) .font(.compound.bodyMD) .foregroundColor(.compound.textPrimary) .lineLimit(1) @@ -79,27 +87,30 @@ struct PinnedItemsBannerView_Previews: PreviewProvider, TestablePreview { static var attributedContent: AttributedString { var boldPart = AttributedString("Image:") boldPart.bold() - var final = boldPart + " content.png" + var finalString = boldPart + " content.png" // This should be ignored when presented - final.font = .headline - return final + finalString.font = .headline + return finalString } static var previews: some View { VStack(spacing: 20) { - PinnedItemsBannerView(pinnedEventsState: .init(pinnedEventContents: ["1": "Content", - "2": "2", - "3": "3"], - selectedPinEventID: "1"), + PinnedItemsBannerView(state: .loaded(state: .init(pinnedEventContents: ["1": "Content", + "2": "2", + "3": "3"], + selectedPinEventID: "1")), + onMainButtonTap: { }, + onViewAllButtonTap: { }) + PinnedItemsBannerView(state: .loaded(state: .init(pinnedEventContents: ["1": "Very very very very long content here", + "2": "2"], + selectedPinEventID: "1")), onMainButtonTap: { }, onViewAllButtonTap: { }) - PinnedItemsBannerView(pinnedEventsState: .init(pinnedEventContents: ["1": "Very very very very long content here", - "2": "2"], - selectedPinEventID: "1"), + PinnedItemsBannerView(state: .loaded(state: .init(pinnedEventContents: ["1": attributedContent], + selectedPinEventID: "1")), onMainButtonTap: { }, onViewAllButtonTap: { }) - PinnedItemsBannerView(pinnedEventsState: .init(pinnedEventContents: ["1": attributedContent], - selectedPinEventID: "1"), + PinnedItemsBannerView(state: .loading(numbersOfEvents: 5), onMainButtonTap: { }, onViewAllButtonTap: { }) } diff --git a/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptsSummaryView.swift b/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptsSummaryView.swift index 165c8aae93..82433a1ecb 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptsSummaryView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/ReadReceipts/ReadReceiptsSummaryView.swift @@ -58,6 +58,7 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: UserIndicatorControllerMock(), + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index 6d0227d260..3243cd38e8 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -110,7 +110,7 @@ struct RoomScreen: View { } private var pinnedItemsBanner: some View { - PinnedItemsBannerView(pinnedEventsState: context.viewState.pinnedEventsState, + PinnedItemsBannerView(state: context.viewState.pinnedEventsBannerState, onMainButtonTap: { context.send(viewAction: .tappedPinnedEventsBanner) }, onViewAllButtonTap: { context.send(viewAction: .viewAllPins) }) .transition(.move(edge: .top)) @@ -213,6 +213,7 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReadReceiptsView.swift b/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReadReceiptsView.swift index e4933ee342..607eb7d610 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReadReceiptsView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReadReceiptsView.swift @@ -96,6 +96,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift index 3152077a99..d599a3289d 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Timeline/HighlightedTimelineItemModifier.swift @@ -101,6 +101,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineView.swift index 5a0b15423a..d415bb4c8b 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Timeline/TimelineView.swift @@ -86,6 +86,7 @@ struct TimelineView_Previews: PreviewProvider, TestablePreview { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift index 4b6e3878ef..fcf4fdb12f 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift @@ -42,6 +42,11 @@ struct RoomEventStringBuilder { case .redactedMessage: return prefix(L10n.commonMessageRemoved, with: displayName) case .sticker: + if messageEventStringBuilder.prefix == .messageType { + var string = AttributedString(L10n.commonSticker) + string.bold() + return string + } return prefix(L10n.commonSticker, with: displayName) case .failedToParseMessageLike, .failedToParseState: return prefix(L10n.commonUnsupportedEvent, with: displayName) @@ -70,6 +75,14 @@ struct RoomEventStringBuilder { memberIsYou: isOutgoing) .map(AttributedString.init) case .poll(let question, _, _, _, _, _, _): + if messageEventStringBuilder.prefix == .messageType { + let questionPlaceholder = "{question}" + var finalString = AttributedString(L10n.commonPollSummary(questionPlaceholder)) + finalString.bold() + let normalString = AttributedString(question) + finalString.replace(questionPlaceholder, with: normalString) + return finalString + } return prefix(L10n.commonPollSummary(question), with: displayName) case .callInvite: return prefix(L10n.commonCallInvite, with: displayName) @@ -95,7 +108,7 @@ struct RoomEventStringBuilder { RoomEventStringBuilder(stateEventStringBuilder: .init(userID: userID, shouldDisambiguateDisplayNames: false), messageEventStringBuilder: .init(attributedStringBuilder: AttributedStringBuilder(cacheKey: "pinnedEvents", mentionBuilder: PlainMentionBuilder()), - prefix: .mediaType), + prefix: .messageType), shouldDisambiguateDisplayNames: false, shouldPrefixSenderName: false) } diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift index 90ae993043..93c430f931 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift @@ -20,7 +20,7 @@ import MatrixRustSDK struct RoomMessageEventStringBuilder { enum Prefix { case senderName - case mediaType + case messageType case none } @@ -41,19 +41,19 @@ struct RoomMessageEventStringBuilder { case .audio(content: let content): let isVoiceMessage = content.voice != nil var content = AttributedString(isVoiceMessage ? L10n.commonVoiceMessage : L10n.commonAudio) - if prefix == .mediaType { + if prefix == .messageType { content.bold() } message = content case .image(let content): - message = prefix == .mediaType ? prefix(AttributedString(content.body), with: L10n.commonImage) : AttributedString("\(L10n.commonImage) - \(content.body)") + message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonImage) : AttributedString("\(L10n.commonImage) - \(content.body)") case .video(let content): - message = prefix == .mediaType ? prefix(AttributedString(content.body), with: L10n.commonVideo) : AttributedString("\(L10n.commonVideo) - \(content.body)") + message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonVideo) : AttributedString("\(L10n.commonVideo) - \(content.body)") case .file(let content): - message = prefix == .mediaType ? prefix(AttributedString(content.body), with: L10n.commonFile) : AttributedString("\(L10n.commonFile) - \(content.body)") + message = prefix == .messageType ? prefix(AttributedString(content.body), with: L10n.commonFile) : AttributedString("\(L10n.commonFile) - \(content.body)") case .location: var content = AttributedString(L10n.commonSharedLocation) - if prefix == .mediaType { + if prefix == .messageType { content.bold() } message = content diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 81eb828633..4583816ebe 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -47,6 +47,7 @@ class UITestsAppCoordinator: AppCoordinatorProtocol, SecureWindowManagerDelegate AppSettings.resetAllSettings() ServiceLocator.shared.register(appSettings: AppSettings()) ServiceLocator.shared.register(bugReportService: BugReportServiceMock()) + ServiceLocator.shared.register(networkMonitor: NetworkMonitorMock.default) let analyticsClient = AnalyticsClientMock() analyticsClient.isRunning = false diff --git a/ElementX/Sources/UnitTests/UnitTestsAppCoordinator.swift b/ElementX/Sources/UnitTests/UnitTestsAppCoordinator.swift index 689d672580..94f541bece 100644 --- a/ElementX/Sources/UnitTests/UnitTestsAppCoordinator.swift +++ b/ElementX/Sources/UnitTests/UnitTestsAppCoordinator.swift @@ -27,6 +27,7 @@ class UnitTestsAppCoordinator: AppCoordinatorProtocol { AppSettings.resetAllSettings() ServiceLocator.shared.register(appSettings: AppSettings()) ServiceLocator.shared.register(bugReportService: BugReportServiceMock()) + ServiceLocator.shared.register(networkMonitor: NetworkMonitorMock.default) let analyticsClient = AnalyticsClientMock() analyticsClient.isRunning = false diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png index 92c1d53b36..22b97c881f 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5eb75e371a78b17fad61215006b871310665bf8061772985d047facbccc5bae7 -size 129176 +oid sha256:52a543349c38a46a7abf42d9f5b83aed47b40621e358fe63b98487acff03b461 +size 147075 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png index 7019c67c6f..40030d446f 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:745d8fdea278dc6ab55f39501384ecc5efc3899db233c52c797a8542f4885adc -size 154132 +oid sha256:131dadbb128453abb744bd49c2cd592bbd9f0f5bdee5ba6ea71f541a10ee70ee +size 182373 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-en-GB.1.png index 0aeb4f05d1..59dcea9a6a 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-en-GB.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82dc33b9de9b497388b91304afe2623e4fa5c9d5aff246a87b68c4d948a63a37 -size 76715 +oid sha256:ade81f08af5344aab81fdebbffe27a4b04976ce8e3cc8f397d5328c51998ad09 +size 91413 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-pseudo.1.png index 51383825dc..fcd8c4da61 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-pseudo.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_pinnedItemsBannerView-iPhone-15-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48df9215b99d69572bf3c4395e4b13d0b34012691b98bba75c73fc35c3b0b6fb -size 85989 +oid sha256:919e3df86ce263d06f479c701b6981a66b0d6217e13cf3cff12445b9c6a24d77 +size 106938 diff --git a/UnitTests/Sources/PillContextTests.swift b/UnitTests/Sources/PillContextTests.swift index 3ddbd4f78a..331d5ca3c2 100644 --- a/UnitTests/Sources/PillContextTests.swift +++ b/UnitTests/Sources/PillContextTests.swift @@ -32,6 +32,7 @@ class PillContextTests: XCTestCase { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) @@ -60,6 +61,7 @@ class PillContextTests: XCTestCase { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) @@ -81,6 +83,7 @@ class PillContextTests: XCTestCase { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: ServiceLocator.shared.userIndicatorController, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) diff --git a/UnitTests/Sources/PinnedEventsBannerStateTests.swift b/UnitTests/Sources/PinnedEventsBannerStateTests.swift new file mode 100644 index 0000000000..bddb32baf6 --- /dev/null +++ b/UnitTests/Sources/PinnedEventsBannerStateTests.swift @@ -0,0 +1,133 @@ +// +// Copyright 2024 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import XCTest + +@testable import ElementX + +class PinnedEventsBannerStateTests: XCTestCase { + func testEmpty() { + var state = PinnedEventsBannerState.loading(numbersOfEvents: 0) + XCTAssertTrue(state.isEmpty) + + state = .loaded(state: .init()) + XCTAssertTrue(state.isEmpty) + } + + func testLoading() { + let originalState = PinnedEventsBannerState.loading(numbersOfEvents: 5) + + var state = originalState + // This should not affect the state when loading + state.nextPin() + XCTAssertEqual(state, originalState) + + XCTAssertTrue(state.isLoading) + XCTAssertFalse(state.isEmpty) + XCTAssertNil(state.selectedPinEventID) + XCTAssertEqual(state.displayedMessage.string, L10n.screenRoomPinnedBannerLoadingDescription) + XCTAssertEqual(state.selectedPinIndex, 4) + XCTAssertEqual(state.count, 5) + XCTAssertEqual(state.bannerIndicatorDescription.string, L10n.screenRoomPinnedBannerIndicatorDescription(L10n.screenRoomPinnedBannerIndicator(5, 5))) + } + + func testLoadingToLoaded() { + var state = PinnedEventsBannerState.loading(numbersOfEvents: 2) + XCTAssertTrue(state.isLoading) + state.setPinnedEventContents(["1": "test1", "2": "test2"]) + XCTAssertEqual(state, .loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2"], selectedPinEventID: "2"))) + XCTAssertFalse(state.isLoading) + } + + func testLoaded() { + let state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2"], selectedPinEventID: "2")) + XCTAssertFalse(state.isLoading) + XCTAssertFalse(state.isEmpty) + XCTAssertEqual(state.selectedPinEventID, "2") + XCTAssertEqual(state.displayedMessage.string, "test2") + XCTAssertEqual(state.selectedPinIndex, 1) + XCTAssertEqual(state.count, 2) + XCTAssertEqual(state.bannerIndicatorDescription.string, L10n.screenRoomPinnedBannerIndicatorDescription(L10n.screenRoomPinnedBannerIndicator(2, 2))) + } + + func testNextPin() { + var state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2", "3": "test3"], selectedPinEventID: "3")) + XCTAssertEqual(state.selectedPinEventID, "3") + XCTAssertEqual(state.selectedPinIndex, 2) + XCTAssertEqual(state.displayedMessage.string, "test3") + + state.nextPin() + XCTAssertEqual(state.selectedPinEventID, "1") + XCTAssertEqual(state.selectedPinIndex, 0) + XCTAssertEqual(state.displayedMessage.string, "test1") + + state.nextPin() + XCTAssertEqual(state.selectedPinEventID, "2") + XCTAssertEqual(state.selectedPinIndex, 1) + XCTAssertEqual(state.displayedMessage.string, "test2") + } + + func testSetContent() { + var state = PinnedEventsBannerState.loaded(state: .init(pinnedEventContents: ["1": "test1", "2": "test2", "3": "test3", "4": "test4"], selectedPinEventID: "2")) + XCTAssertEqual(state.selectedPinEventID, "2") + XCTAssertEqual(state.selectedPinIndex, 1) + XCTAssertEqual(state.displayedMessage.string, "test2") + XCTAssertEqual(state.count, 4) + XCTAssertFalse(state.isEmpty) + + // let's remove the selected item + state.setPinnedEventContents(["1": "test1", "3": "test3", "4": "test4"]) + // new selected item is the new latest + XCTAssertEqual(state.selectedPinEventID, "4") + XCTAssertEqual(state.selectedPinIndex, 2) + XCTAssertEqual(state.displayedMessage.string, "test4") + XCTAssertEqual(state.count, 3) + XCTAssertFalse(state.isEmpty) + + // let's add a new item at the top + state.setPinnedEventContents(["0": "test0", "1": "test1", "3": "test3", "4": "test4"]) + // selected item doesn't change + XCTAssertEqual(state.selectedPinEventID, "4") + // but the index is updated + XCTAssertEqual(state.selectedPinIndex, 3) + XCTAssertEqual(state.displayedMessage.string, "test4") + XCTAssertEqual(state.count, 4) + XCTAssertFalse(state.isEmpty) + + // let's add a new item at the bottom + state.setPinnedEventContents(["0": "test0", "1": "test1", "3": "test3", "4": "test4", "5": "test5"]) + // selected item doesn't change + XCTAssertEqual(state.selectedPinEventID, "4") + // and index stays the same + XCTAssertEqual(state.selectedPinIndex, 3) + XCTAssertEqual(state.displayedMessage.string, "test4") + XCTAssertEqual(state.count, 5) + XCTAssertFalse(state.isEmpty) + + // set to tempty + state.setPinnedEventContents([:]) + XCTAssertTrue(state.isEmpty) + XCTAssertNil(state.selectedPinEventID) + + // set to one item + state.setPinnedEventContents(["6": "test6", "7": "test7"]) + XCTAssertEqual(state.selectedPinEventID, "7") + XCTAssertEqual(state.selectedPinIndex, 1) + XCTAssertEqual(state.displayedMessage.string, "test7") + XCTAssertEqual(state.count, 2) + XCTAssertFalse(state.isEmpty) + } +} diff --git a/UnitTests/Sources/RoomScreenViewModelTests.swift b/UnitTests/Sources/RoomScreenViewModelTests.swift index b547d928ed..1ca48bd744 100644 --- a/UnitTests/Sources/RoomScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomScreenViewModelTests.swift @@ -351,6 +351,7 @@ class RoomScreenViewModelTests: XCTestCase { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: userIndicatorControllerMock, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) @@ -375,6 +376,7 @@ class RoomScreenViewModelTests: XCTestCase { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: userIndicatorControllerMock, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) @@ -399,6 +401,7 @@ class RoomScreenViewModelTests: XCTestCase { mediaPlayerProvider: MediaPlayerProviderMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(), userIndicatorController: userIndicatorControllerMock, + networkMonitor: ServiceLocator.shared.networkMonitor, appMediator: AppMediatorMock.default, appSettings: ServiceLocator.shared.settings, analyticsService: ServiceLocator.shared.analytics) diff --git a/project.yml b/project.yml index 91f61e8ea4..83b243ed51 100644 --- a/project.yml +++ b/project.yml @@ -60,7 +60,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.31 + exactVersion: 1.0.32 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios