diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 58b9459cd..cd042f238 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 63; + objectVersion = 77; objects = { /* Begin PBXAggregateTarget section */ @@ -1537,7 +1537,7 @@ 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; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; 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 = ""; }; @@ -1620,7 +1620,7 @@ 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAttachmentPicker.swift; sourceTree = ""; }; 12B09A94C519227264A41208 /* RoomMembershipDetailsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembershipDetailsProxy.swift; sourceTree = ""; }; 12FD5280AF55AB7F50F8E47D /* preview_avatar_room.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = preview_avatar_room.jpg; sourceTree = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; sourceTree = ""; }; + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; 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 = ""; }; @@ -1640,7 +1640,7 @@ 16D09C79746BDCD9173EB3A7 /* RoomDetailsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenModels.swift; sourceTree = ""; }; 16D353E10A64172D863769BF /* TombstonedAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TombstonedAvatarImage.swift; sourceTree = ""; }; 1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogAnalyticsClient.swift; sourceTree = ""; }; - 174E4AEF3DED300AA81046EC /* compound-ios */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "compound-ios"; sourceTree = SOURCE_ROOT; }; + 174E4AEF3DED300AA81046EC /* compound-ios */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "compound-ios"; path = "compound-ios"; sourceTree = SOURCE_ROOT; }; 17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyMock.swift; sourceTree = ""; }; 17BAE25A0E9E9F2F1BBA8930 /* DeactivateAccountScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenViewModel.swift; sourceTree = ""; }; 181CF280BC8E3F335AFCB4B8 /* RemotePreferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemotePreferenceTests.swift; sourceTree = ""; }; @@ -1728,7 +1728,7 @@ 25E7E9B7FEAB6169D960C206 /* QRCodeLoginScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeLoginScreenViewModelTests.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; lastKnownFileType = text; path = PreviewTests.xctestplan; sourceTree = ""; }; + 267BB1D5B08A9511F894CB57 /* PreviewTests.xctestplan */ = {isa = PBXFileReference; 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 = ""; }; 2711E5996016ABD6EAAEB58A /* LogLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogLevel.swift; sourceTree = ""; }; @@ -1811,7 +1811,7 @@ 355C8C46DA9C0B45F1B7FC4F /* SpaceRoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomProxy.swift; sourceTree = ""; }; 35A057BA9BE0F079784CD061 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 35AFCF4C05DEED04E3DB1A16 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; - 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 36DA824791172B9821EACBED /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxyMock.swift; sourceTree = ""; }; 3747C96188856006F784BF49 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ko; path = ko.lproj/Localizable.stringsdict; sourceTree = ""; }; 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallScreenViewModel.swift; sourceTree = ""; }; @@ -1926,7 +1926,7 @@ 4A2B5274C1D3D2999D643786 /* EncryptionResetPasswordScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenViewModelProtocol.swift; sourceTree = ""; }; 4A5B4CD611DE7E94F5BA87B2 /* AppLockTimerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockTimerTests.swift; sourceTree = ""; }; 4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupControllerMock.swift; sourceTree = ""; }; - 4B1F71AC585827E6C416C15A /* AppIcon.icon */ = {isa = PBXFileReference; lastKnownFileType = folder.iconcomposer.icon; path = AppIcon.icon; sourceTree = ""; }; + 4B1F71AC585827E6C416C15A /* AppIcon.icon */ = {isa = PBXFileReference; path = AppIcon.icon; sourceTree = ""; }; 4B2B564CA6570E1487A7C7CC /* SpaceRoomListProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomListProxy.swift; sourceTree = ""; }; 4B2D4EEBE8C098BBADD10939 /* SecureBackupKeyBackupScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenCoordinator.swift; sourceTree = ""; }; 4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = ""; }; @@ -2262,7 +2262,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 = ""; }; 8DA1E8F287680C8ED25EDBAC /* NetworkMonitorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitorMock.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; 8E1584F8BCF407BB94F48F04 /* EncryptionResetPasswordScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreen.swift; sourceTree = ""; }; 8EAF4A49F3ACD8BB8B0D2371 /* ClientSDKMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientSDKMock.swift; sourceTree = ""; }; 8F062DD2CCD95DC33528A16F /* KnockRequestProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnockRequestProxy.swift; sourceTree = ""; }; @@ -2408,7 +2408,7 @@ AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationAnnotation.swift; sourceTree = ""; }; AB07F03461023BC39C730922 /* PhishingDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhishingDetector.swift; sourceTree = ""; }; AB26D5444A4A7E095222DE8B /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.stringsdict"; sourceTree = ""; }; - AB389C38BD41EB3E47092CFB /* AccessibilityTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = AccessibilityTests.xctestplan; sourceTree = ""; }; + AB389C38BD41EB3E47092CFB /* AccessibilityTests.xctestplan */ = {isa = PBXFileReference; path = AccessibilityTests.xctestplan; sourceTree = ""; }; ABA4CF2F5B4F68D02E412004 /* ServerConfirmationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModelProtocol.swift; sourceTree = ""; }; AC0275CEE9CA078B34028BDF /* AppLockScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockScreenViewModelTests.swift; sourceTree = ""; }; AC1DA29A5A041CC0BACA7CB0 /* MockImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageCache.swift; sourceTree = ""; }; @@ -2475,7 +2475,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 = ""; }; B5D829FD8958376614504B18 /* TargetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetConfiguration.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; B6404166CBF5CC88673FF9E2 /* RoomDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetails.swift; sourceTree = ""; }; B65DDCF8E41759890355ACBC /* AuthenticationStartScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModelProtocol.swift; sourceTree = ""; }; B682FE2C44C5E163E7023B05 /* CopyTextButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyTextButton.swift; sourceTree = ""; }; @@ -2505,7 +2505,7 @@ BA40B98B098B6F0371B750B3 /* TemplateScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenModels.swift; sourceTree = ""; }; BA919F521E9F0EE3638AFC85 /* BugReportScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreen.swift; sourceTree = ""; }; BB284643AF7AB131E307DCE0 /* AudioSessionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioSessionProtocol.swift; sourceTree = ""; }; - BB576F4118C35E6B5124FA22 /* test_apple_image.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_apple_image.heic; sourceTree = ""; }; + BB576F4118C35E6B5124FA22 /* test_apple_image.heic */ = {isa = PBXFileReference; path = test_apple_image.heic; sourceTree = ""; }; BB5B00A014307CE37B2812CD /* TimelineViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewModelProtocol.swift; sourceTree = ""; }; BB6ED50FE104992419310EEB /* NotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandler.swift; sourceTree = ""; }; BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenCoordinator.swift; sourceTree = ""; }; @@ -2608,7 +2608,7 @@ CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = ""; }; - CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; CF19027E7FFA5E63D148873A /* CreateRoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomScreenViewModel.swift; sourceTree = ""; }; CF847A34FC4C8C937CD39E08 /* LabsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenViewModelProtocol.swift; sourceTree = ""; }; CFFA5E881D281810AB428EA3 /* RoomPowerLevelsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelsProxy.swift; sourceTree = ""; }; @@ -2676,7 +2676,7 @@ DC0AEA686E425F86F6BA0404 /* UNNotification+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNNotification+Creator.swift"; sourceTree = ""; }; DC10CCC8D68B863E20660DBC /* MessageForwardingScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelProtocol.swift; sourceTree = ""; }; DC528B3764E3CF7FCFEF40E7 /* PollInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollInteractionHandler.swift; sourceTree = ""; }; - DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_voice_message.m4a; sourceTree = ""; }; + DCA2D836BD10303F37FAAEED /* test_voice_message.m4a */ = {isa = PBXFileReference; path = test_voice_message.m4a; sourceTree = ""; }; DCAC01A97A43BE07B9E94E43 /* ShareExtensionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionModels.swift; sourceTree = ""; }; DCDAB580109C09A6AA97AF7E /* PollFormScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFormScreenTests.swift; sourceTree = ""; }; DCF239C619971FDE48132550 /* SecureBackupLogoutConfirmationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenModels.swift; sourceTree = ""; }; @@ -2723,7 +2723,7 @@ E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashDecode.swift; sourceTree = ""; }; E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreen.swift; sourceTree = ""; }; E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsProxyProtocol.swift; sourceTree = ""; }; - E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = portrait_test_video.mp4; sourceTree = ""; }; + E5E7D4EE7CA295E5039FDA21 /* portrait_test_video.mp4 */ = {isa = PBXFileReference; path = portrait_test_video.mp4; sourceTree = ""; }; E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = ""; }; E5F2B6443D1ED8602F328539 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = ""; }; E5FDFAA04174CC99FB66391C /* EditRoomAddressScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditRoomAddressScreenViewModel.swift; sourceTree = ""; }; @@ -2770,7 +2770,7 @@ ED0CBEAB5F796BEFBAF7BB6A /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.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; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = ""; }; ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = ""; }; EDDE826EAB1BAB80C1104980 /* SpaceFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceFlowCoordinator.swift; sourceTree = ""; }; @@ -6951,7 +6951,6 @@ el, en, "en-US", - eo, es, et, eu, @@ -7012,6 +7011,7 @@ EE40B0E16A55BD23ECBFFD22 /* XCRemoteSwiftPackageReference "matrix-rich-text-editor-swift" */, C89CF7729E028671C5DC461E /* XCLocalSwiftPackageReference "compound-ios" */, ); + preferredProjectObjectVersion = 77; projectDirPath = ""; projectRoot = ""; targets = ( @@ -8841,7 +8841,9 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - OTHER_SWIFT_FLAGS = "-DRELEASE"; + OTHER_SWIFT_FLAGS = ( + "-DRELEASE", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.accessibility.tests"; PRODUCT_NAME = AccessibilityTests; SDKROOT = iphoneos; @@ -8860,7 +8862,9 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - OTHER_SWIFT_FLAGS = "-DDEBUG"; + OTHER_SWIFT_FLAGS = ( + "-DDEBUG", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.accessibility.tests"; PRODUCT_NAME = AccessibilityTests; SDKROOT = iphoneos; @@ -8882,7 +8886,9 @@ "@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; @@ -8931,7 +8937,9 @@ "@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)"; @@ -8957,7 +8965,9 @@ "@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)"; @@ -9182,7 +9192,9 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - OTHER_SWIFT_FLAGS = "-DDEBUG"; + OTHER_SWIFT_FLAGS = ( + "-DDEBUG", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.ui.tests"; PRODUCT_NAME = UITests; SDKROOT = iphoneos; @@ -9201,7 +9213,9 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - OTHER_SWIFT_FLAGS = "-DRELEASE"; + OTHER_SWIFT_FLAGS = ( + "-DRELEASE", + ); PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.ui.tests"; PRODUCT_NAME = UITests; SDKROOT = iphoneos; @@ -9223,7 +9237,9 @@ "@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; @@ -9478,7 +9494,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 25.11.18; + version = 25.11.24; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5d1aceab3..7db426487 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -158,8 +158,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "bc6e76ae6432caf7463f37eb1c2a320f255c9daf", - "version" : "25.11.18" + "revision" : "05f951fe1144ef2296fa93110274e9bf51c80cb7", + "version" : "25.11.24" } }, { @@ -327,7 +327,7 @@ { "identity" : "swiftui-introspect", "kind" : "remoteSourceControl", - "location" : "https://github.com/siteline/SwiftUI-Introspect.git", + "location" : "https://github.com/siteline/SwiftUI-Introspect", "state" : { "revision" : "a08b87f96b41055577721a6e397562b21ad52454", "version" : "26.0.0" diff --git a/ElementX/Sources/Mocks/ClientProxyMock.swift b/ElementX/Sources/Mocks/ClientProxyMock.swift index 2625243b3..5239ba2be 100644 --- a/ElementX/Sources/Mocks/ClientProxyMock.swift +++ b/ElementX/Sources/Mocks/ClientProxyMock.swift @@ -140,7 +140,7 @@ extension ClientProxyMock { } } - userIdentityForReturnValue = .success(UserIdentityProxyMock(configuration: .init())) + userIdentityForFallBackToServerReturnValue = .success(UserIdentityProxyMock(configuration: .init())) underlyingIsReportRoomSupported = true underlyingIsLiveKitRTCSupported = true diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 5bcd005cb..bdf8c9077 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -5297,15 +5297,15 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable { } //MARK: - userIdentity - var userIdentityForUnderlyingCallsCount = 0 - var userIdentityForCallsCount: Int { + var userIdentityForFallBackToServerUnderlyingCallsCount = 0 + var userIdentityForFallBackToServerCallsCount: Int { get { if Thread.isMainThread { - return userIdentityForUnderlyingCallsCount + return userIdentityForFallBackToServerUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = userIdentityForUnderlyingCallsCount + returnValue = userIdentityForFallBackToServerUnderlyingCallsCount } return returnValue! @@ -5313,29 +5313,29 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable { } set { if Thread.isMainThread { - userIdentityForUnderlyingCallsCount = newValue + userIdentityForFallBackToServerUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - userIdentityForUnderlyingCallsCount = newValue + userIdentityForFallBackToServerUnderlyingCallsCount = newValue } } } } - var userIdentityForCalled: Bool { - return userIdentityForCallsCount > 0 + var userIdentityForFallBackToServerCalled: Bool { + return userIdentityForFallBackToServerCallsCount > 0 } - var userIdentityForReceivedUserID: String? - var userIdentityForReceivedInvocations: [String] = [] + var userIdentityForFallBackToServerReceivedArguments: (userID: String, fallBackToServer: Bool)? + var userIdentityForFallBackToServerReceivedInvocations: [(userID: String, fallBackToServer: Bool)] = [] - var userIdentityForUnderlyingReturnValue: Result! - var userIdentityForReturnValue: Result! { + var userIdentityForFallBackToServerUnderlyingReturnValue: Result! + var userIdentityForFallBackToServerReturnValue: Result! { get { if Thread.isMainThread { - return userIdentityForUnderlyingReturnValue + return userIdentityForFallBackToServerUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = userIdentityForUnderlyingReturnValue + returnValue = userIdentityForFallBackToServerUnderlyingReturnValue } return returnValue! @@ -5343,26 +5343,26 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable { } set { if Thread.isMainThread { - userIdentityForUnderlyingReturnValue = newValue + userIdentityForFallBackToServerUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - userIdentityForUnderlyingReturnValue = newValue + userIdentityForFallBackToServerUnderlyingReturnValue = newValue } } } } - var userIdentityForClosure: ((String) async -> Result)? + var userIdentityForFallBackToServerClosure: ((String, Bool) async -> Result)? - func userIdentity(for userID: String) async -> Result { - userIdentityForCallsCount += 1 - userIdentityForReceivedUserID = userID + func userIdentity(for userID: String, fallBackToServer: Bool) async -> Result { + userIdentityForFallBackToServerCallsCount += 1 + userIdentityForFallBackToServerReceivedArguments = (userID: userID, fallBackToServer: fallBackToServer) DispatchQueue.main.async { - self.userIdentityForReceivedInvocations.append(userID) + self.userIdentityForFallBackToServerReceivedInvocations.append((userID: userID, fallBackToServer: fallBackToServer)) } - if let userIdentityForClosure = userIdentityForClosure { - return await userIdentityForClosure(userID) + if let userIdentityForFallBackToServerClosure = userIdentityForFallBackToServerClosure { + return await userIdentityForFallBackToServerClosure(userID, fallBackToServer) } else { - return userIdentityForReturnValue + return userIdentityForFallBackToServerReturnValue } } //MARK: - setTimelineMediaVisibility diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index a7294d316..6f1d2266c 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -8816,16 +8816,16 @@ open class EncryptionSDKMock: MatrixRustSDK.Encryption, @unchecked Sendable { //MARK: - userIdentity - open var userIdentityUserIdThrowableError: Error? - var userIdentityUserIdUnderlyingCallsCount = 0 - open var userIdentityUserIdCallsCount: Int { + open var userIdentityUserIdFallbackToServerThrowableError: Error? + var userIdentityUserIdFallbackToServerUnderlyingCallsCount = 0 + open var userIdentityUserIdFallbackToServerCallsCount: Int { get { if Thread.isMainThread { - return userIdentityUserIdUnderlyingCallsCount + return userIdentityUserIdFallbackToServerUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = userIdentityUserIdUnderlyingCallsCount + returnValue = userIdentityUserIdFallbackToServerUnderlyingCallsCount } return returnValue! @@ -8833,29 +8833,29 @@ open class EncryptionSDKMock: MatrixRustSDK.Encryption, @unchecked Sendable { } set { if Thread.isMainThread { - userIdentityUserIdUnderlyingCallsCount = newValue + userIdentityUserIdFallbackToServerUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - userIdentityUserIdUnderlyingCallsCount = newValue + userIdentityUserIdFallbackToServerUnderlyingCallsCount = newValue } } } } - open var userIdentityUserIdCalled: Bool { - return userIdentityUserIdCallsCount > 0 + open var userIdentityUserIdFallbackToServerCalled: Bool { + return userIdentityUserIdFallbackToServerCallsCount > 0 } - open var userIdentityUserIdReceivedUserId: String? - open var userIdentityUserIdReceivedInvocations: [String] = [] + open var userIdentityUserIdFallbackToServerReceivedArguments: (userId: String, fallbackToServer: Bool)? + open var userIdentityUserIdFallbackToServerReceivedInvocations: [(userId: String, fallbackToServer: Bool)] = [] - var userIdentityUserIdUnderlyingReturnValue: UserIdentity? - open var userIdentityUserIdReturnValue: UserIdentity? { + var userIdentityUserIdFallbackToServerUnderlyingReturnValue: UserIdentity? + open var userIdentityUserIdFallbackToServerReturnValue: UserIdentity? { get { if Thread.isMainThread { - return userIdentityUserIdUnderlyingReturnValue + return userIdentityUserIdFallbackToServerUnderlyingReturnValue } else { var returnValue: UserIdentity?? = nil DispatchQueue.main.sync { - returnValue = userIdentityUserIdUnderlyingReturnValue + returnValue = userIdentityUserIdFallbackToServerUnderlyingReturnValue } return returnValue! @@ -8863,29 +8863,29 @@ open class EncryptionSDKMock: MatrixRustSDK.Encryption, @unchecked Sendable { } set { if Thread.isMainThread { - userIdentityUserIdUnderlyingReturnValue = newValue + userIdentityUserIdFallbackToServerUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - userIdentityUserIdUnderlyingReturnValue = newValue + userIdentityUserIdFallbackToServerUnderlyingReturnValue = newValue } } } } - open var userIdentityUserIdClosure: ((String) async throws -> UserIdentity?)? + open var userIdentityUserIdFallbackToServerClosure: ((String, Bool) async throws -> UserIdentity?)? - open override func userIdentity(userId: String) async throws -> UserIdentity? { - if let error = userIdentityUserIdThrowableError { + open override func userIdentity(userId: String, fallbackToServer: Bool) async throws -> UserIdentity? { + if let error = userIdentityUserIdFallbackToServerThrowableError { throw error } - userIdentityUserIdCallsCount += 1 - userIdentityUserIdReceivedUserId = userId + userIdentityUserIdFallbackToServerCallsCount += 1 + userIdentityUserIdFallbackToServerReceivedArguments = (userId: userId, fallbackToServer: fallbackToServer) DispatchQueue.main.async { - self.userIdentityUserIdReceivedInvocations.append(userId) + self.userIdentityUserIdFallbackToServerReceivedInvocations.append((userId: userId, fallbackToServer: fallbackToServer)) } - if let userIdentityUserIdClosure = userIdentityUserIdClosure { - return try await userIdentityUserIdClosure(userId) + if let userIdentityUserIdFallbackToServerClosure = userIdentityUserIdFallbackToServerClosure { + return try await userIdentityUserIdFallbackToServerClosure(userId, fallbackToServer) } else { - return userIdentityUserIdReturnValue + return userIdentityUserIdFallbackToServerReturnValue } } @@ -22936,6 +22936,127 @@ open class SpaceServiceSDKMock: MatrixRustSDK.SpaceService, @unchecked Sendable } fileprivate var underlyingHandle: UInt64! + //MARK: - addChildToSpace + + open var addChildToSpaceChildIdSpaceIdThrowableError: Error? + var addChildToSpaceChildIdSpaceIdUnderlyingCallsCount = 0 + open var addChildToSpaceChildIdSpaceIdCallsCount: Int { + get { + if Thread.isMainThread { + return addChildToSpaceChildIdSpaceIdUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = addChildToSpaceChildIdSpaceIdUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + addChildToSpaceChildIdSpaceIdUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + addChildToSpaceChildIdSpaceIdUnderlyingCallsCount = newValue + } + } + } + } + open var addChildToSpaceChildIdSpaceIdCalled: Bool { + return addChildToSpaceChildIdSpaceIdCallsCount > 0 + } + open var addChildToSpaceChildIdSpaceIdReceivedArguments: (childId: String, spaceId: String)? + open var addChildToSpaceChildIdSpaceIdReceivedInvocations: [(childId: String, spaceId: String)] = [] + open var addChildToSpaceChildIdSpaceIdClosure: ((String, String) async throws -> Void)? + + open override func addChildToSpace(childId: String, spaceId: String) async throws { + if let error = addChildToSpaceChildIdSpaceIdThrowableError { + throw error + } + addChildToSpaceChildIdSpaceIdCallsCount += 1 + addChildToSpaceChildIdSpaceIdReceivedArguments = (childId: childId, spaceId: spaceId) + DispatchQueue.main.async { + self.addChildToSpaceChildIdSpaceIdReceivedInvocations.append((childId: childId, spaceId: spaceId)) + } + try await addChildToSpaceChildIdSpaceIdClosure?(childId, spaceId) + } + + //MARK: - joinedParentsOfChild + + open var joinedParentsOfChildChildIdThrowableError: Error? + var joinedParentsOfChildChildIdUnderlyingCallsCount = 0 + open var joinedParentsOfChildChildIdCallsCount: Int { + get { + if Thread.isMainThread { + return joinedParentsOfChildChildIdUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = joinedParentsOfChildChildIdUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + joinedParentsOfChildChildIdUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + joinedParentsOfChildChildIdUnderlyingCallsCount = newValue + } + } + } + } + open var joinedParentsOfChildChildIdCalled: Bool { + return joinedParentsOfChildChildIdCallsCount > 0 + } + open var joinedParentsOfChildChildIdReceivedChildId: String? + open var joinedParentsOfChildChildIdReceivedInvocations: [String] = [] + + var joinedParentsOfChildChildIdUnderlyingReturnValue: [SpaceRoom]! + open var joinedParentsOfChildChildIdReturnValue: [SpaceRoom]! { + get { + if Thread.isMainThread { + return joinedParentsOfChildChildIdUnderlyingReturnValue + } else { + var returnValue: [SpaceRoom]? = nil + DispatchQueue.main.sync { + returnValue = joinedParentsOfChildChildIdUnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + joinedParentsOfChildChildIdUnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + joinedParentsOfChildChildIdUnderlyingReturnValue = newValue + } + } + } + } + open var joinedParentsOfChildChildIdClosure: ((String) async throws -> [SpaceRoom])? + + open override func joinedParentsOfChild(childId: String) async throws -> [SpaceRoom] { + if let error = joinedParentsOfChildChildIdThrowableError { + throw error + } + joinedParentsOfChildChildIdCallsCount += 1 + joinedParentsOfChildChildIdReceivedChildId = childId + DispatchQueue.main.async { + self.joinedParentsOfChildChildIdReceivedInvocations.append(childId) + } + if let joinedParentsOfChildChildIdClosure = joinedParentsOfChildChildIdClosure { + return try await joinedParentsOfChildChildIdClosure(childId) + } else { + return joinedParentsOfChildChildIdReturnValue + } + } + //MARK: - joinedSpaces var joinedSpacesUnderlyingCallsCount = 0 @@ -23076,6 +23197,52 @@ open class SpaceServiceSDKMock: MatrixRustSDK.SpaceService, @unchecked Sendable } } + //MARK: - removeChildFromSpace + + open var removeChildFromSpaceChildIdSpaceIdThrowableError: Error? + var removeChildFromSpaceChildIdSpaceIdUnderlyingCallsCount = 0 + open var removeChildFromSpaceChildIdSpaceIdCallsCount: Int { + get { + if Thread.isMainThread { + return removeChildFromSpaceChildIdSpaceIdUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = removeChildFromSpaceChildIdSpaceIdUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + removeChildFromSpaceChildIdSpaceIdUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + removeChildFromSpaceChildIdSpaceIdUnderlyingCallsCount = newValue + } + } + } + } + open var removeChildFromSpaceChildIdSpaceIdCalled: Bool { + return removeChildFromSpaceChildIdSpaceIdCallsCount > 0 + } + open var removeChildFromSpaceChildIdSpaceIdReceivedArguments: (childId: String, spaceId: String)? + open var removeChildFromSpaceChildIdSpaceIdReceivedInvocations: [(childId: String, spaceId: String)] = [] + open var removeChildFromSpaceChildIdSpaceIdClosure: ((String, String) async throws -> Void)? + + open override func removeChildFromSpace(childId: String, spaceId: String) async throws { + if let error = removeChildFromSpaceChildIdSpaceIdThrowableError { + throw error + } + removeChildFromSpaceChildIdSpaceIdCallsCount += 1 + removeChildFromSpaceChildIdSpaceIdReceivedArguments = (childId: childId, spaceId: spaceId) + DispatchQueue.main.async { + self.removeChildFromSpaceChildIdSpaceIdReceivedInvocations.append((childId: childId, spaceId: spaceId)) + } + try await removeChildFromSpaceChildIdSpaceIdClosure?(childId, spaceId) + } + //MARK: - spaceRoomList open var spaceRoomListSpaceIdThrowableError: Error? diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift index b6eae7ea1..dc2af074a 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift @@ -329,14 +329,14 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr if roomProxy.isDirectOneToOneRoom { if var dmRecipientInfo = state.dmRecipientInfo { - if case let .success(userIdentity) = await userSession.clientProxy.userIdentity(for: dmRecipientInfo.member.id) { + if case let .success(userIdentity) = await userSession.clientProxy.userIdentity(for: dmRecipientInfo.member.id, fallBackToServer: true) { dmRecipientInfo.verificationState = userIdentity?.verificationState state.dmRecipientInfo = dmRecipientInfo } } } else { for member in roomProxy.membersPublisher.value { - if case let .success(userIdentity) = await userSession.clientProxy.userIdentity(for: member.userID) { + if case let .success(userIdentity) = await userSession.clientProxy.userIdentity(for: member.userID, fallBackToServer: false) { if userIdentity?.verificationState == .verificationViolation { state.hasMemberIdentityVerificationStateViolations = true return diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index 72e23dd04..db1daa738 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -446,7 +446,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { let clientProxyMock = ClientProxyMock(.init()) - clientProxyMock.userIdentityForClosure = { userID in + clientProxyMock.userIdentityForFallBackToServerClosure = { userID, _ in let identity = switch userID { case RoomMemberProxyMock.mockDan.userID: UserIdentityProxyMock(configuration: .init(verificationState: verificationState)) diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift index 76c84ed24..e45d53aa6 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift @@ -112,7 +112,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro actionsSubject.send(.openUserProfile) } - if case let .success(.some(identity)) = await userSession.clientProxy.userIdentity(for: state.userID) { + if case let .success(.some(identity)) = await userSession.clientProxy.userIdentity(for: state.userID, fallBackToServer: true) { state.verificationState = identity.verificationState } else { MXLog.error("Failed to find the member's identity.") diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift index 12206ff13..73718d5dc 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift @@ -209,7 +209,7 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview { let clientProxyMock = ClientProxyMock(.init()) - clientProxyMock.userIdentityForClosure = { userID in + clientProxyMock.userIdentityForFallBackToServerClosure = { userID, _ in let identity = switch userID { case RoomMemberProxyMock.mockDan.userID: UserIdentityProxyMock(configuration: .init(verificationState: .verified)) diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift index 7970b402b..fd86b017e 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift @@ -132,7 +132,7 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe for member in members { var verificationState: UserIdentityVerificationState = .notVerified if roomProxy.infoPublisher.value.isEncrypted, // We don't care about identity statuses on non-encrypted rooms - case let .success(userIdentity) = await userSession.clientProxy.userIdentity(for: member.userID), + case let .success(userIdentity) = await userSession.clientProxy.userIdentity(for: member.userID, fallBackToServer: false), let userIdentity { verificationState = userIdentity.verificationState } diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift index dd2b32b44..a292f4eeb 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift @@ -240,7 +240,7 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview { } let clientProxyMock = ClientProxyMock(.init()) - clientProxyMock.userIdentityForClosure = { userID in + clientProxyMock.userIdentityForFallBackToServerClosure = { userID, _ in let identity = switch userID { case RoomMemberProxyMock.mockAlice.userID: UserIdentityProxyMock(configuration: .init(verificationState: .verified)) diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index 952d6adb3..92ad22650 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -257,7 +257,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol private func updateVerificationBadge() async { guard roomProxy.isDirectOneToOneRoom, let dmRecipient = roomProxy.membersPublisher.value.first(where: { $0.userID != roomProxy.ownUserID }), - case let .success(userIdentity) = await clientProxy.userIdentity(for: dmRecipient.userID) else { + case let .success(userIdentity) = await clientProxy.userIdentity(for: dmRecipient.userID, fallBackToServer: true) else { state.dmRecipientVerificationState = .notVerified return } diff --git a/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenViewModel.swift b/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenViewModel.swift index f650da5af..c9904d621 100644 --- a/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenViewModel.swift +++ b/ElementX/Sources/Screens/ThreadTimelineScreen/ThreadTimelineScreenViewModel.swift @@ -86,7 +86,7 @@ class ThreadTimelineScreenViewModel: ThreadTimelineScreenViewModelType, ThreadTi private func updateVerificationBadge() async { guard roomProxy.isDirectOneToOneRoom, let dmRecipient = roomProxy.membersPublisher.value.first(where: { $0.userID != roomProxy.ownUserID }), - case let .success(userIdentity) = await userSession.clientProxy.userIdentity(for: dmRecipient.userID) else { + case let .success(userIdentity) = await userSession.clientProxy.userIdentity(for: dmRecipient.userID, fallBackToServer: true) else { state.dmRecipientVerificationState = .notVerified return } diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift index 0490ba959..0c75dd706 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift @@ -73,7 +73,7 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr private func loadProfile() async { async let profileResult = userSession.clientProxy.profile(for: state.userID) - async let identityResult = userSession.clientProxy.userIdentity(for: state.userID) + async let identityResult = userSession.clientProxy.userIdentity(for: state.userID, fallBackToServer: true) switch await profileResult { case .success(let userProfile): diff --git a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift index 28e98a9b3..bf5b888d1 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift @@ -119,7 +119,7 @@ struct UserProfileScreen_Previews: PreviewProvider, TestablePreview { static func makeViewModel(userID: String) -> UserProfileScreenViewModel { let clientProxyMock = ClientProxyMock(.init()) - clientProxyMock.userIdentityForClosure = { userID in + clientProxyMock.userIdentityForFallBackToServerClosure = { userID, _ in let identity = switch userID { case RoomMemberProxyMock.mockDan.userID: UserIdentityProxyMock(configuration: .init(verificationState: .verified)) diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index e9ddcd831..ccd64a0d5 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -1097,7 +1097,7 @@ class ClientProxy: ClientProxyProtocol { MXLog.info("Pinning current identity for user: \(userID)") do { - guard let userIdentity = try await client.encryption().userIdentity(userId: userID) else { + guard let userIdentity = try await client.encryption().userIdentity(userId: userID, fallbackToServer: true) else { MXLog.error("Failed retrieving identity for user: \(userID)") return .failure(.failedRetrievingUserIdentity) } @@ -1113,7 +1113,7 @@ class ClientProxy: ClientProxyProtocol { MXLog.info("Withdrawing current identity verification for user: \(userID)") do { - guard let userIdentity = try await client.encryption().userIdentity(userId: userID) else { + guard let userIdentity = try await client.encryption().userIdentity(userId: userID, fallbackToServer: true) else { MXLog.error("Failed retrieving identity for user: \(userID)") return .failure(.failedRetrievingUserIdentity) } @@ -1133,9 +1133,9 @@ class ClientProxy: ClientProxyProtocol { } } - func userIdentity(for userID: String) async -> Result { + func userIdentity(for userID: String, fallBackToServer: Bool) async -> Result { do { - return try await .success(client.encryption().userIdentity(userId: userID).map(UserIdentityProxy.init)) + return try await .success(client.encryption().userIdentity(userId: userID, fallbackToServer: fallBackToServer).map(UserIdentityProxy.init)) } catch { MXLog.error("Failed retrieving user identity: \(error)") return .failure(.sdkError(error)) diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 697753bf4..1f478cbfe 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -236,7 +236,7 @@ protocol ClientProxyProtocol: AnyObject { func withdrawUserIdentityVerification(_ userID: String) async -> Result func resetIdentity() async -> Result - func userIdentity(for userID: String) async -> Result + func userIdentity(for userID: String, fallBackToServer: Bool) async -> Result // MARK: - Moderation & Safety diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift index 926112d2a..1d8835852 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomEventStringBuilder.swift @@ -16,15 +16,19 @@ struct RoomEventStringBuilder { let shouldPrefixSenderName: Bool func buildAttributedString(for eventItemProxy: EventTimelineItemProxy) -> AttributedString? { - let sender = eventItemProxy.sender - let isOutgoing = eventItemProxy.isOwn + buildAttributedString(for: eventItemProxy.content, + sender: eventItemProxy.sender, + isOutgoing: eventItemProxy.isOwn) + } + + func buildAttributedString(for content: TimelineItemContent, sender: TimelineItemSender, isOutgoing: Bool) -> AttributedString? { let displayName = if shouldDisambiguateDisplayNames { sender.disambiguatedDisplayName ?? sender.id } else { sender.displayName ?? sender.id } - switch eventItemProxy.content { + switch content { case .msgLike(let messageLikeContent): switch messageLikeContent.kind { case .message(let messageContent): diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift index 0c27e113a..7f492bde3 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift @@ -230,10 +230,10 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { return updatedItems } - private func fetchRoomDetails(from room: Room) -> (roomInfo: RoomInfo?, latestEvent: EventTimelineItem?) { + private func fetchRoomDetails(from room: Room) -> (roomInfo: RoomInfo?, latestEvent: LatestEventValue?) { class FetchResult { var roomInfo: RoomInfo? - var latestEvent: EventTimelineItem? + var latestEvent: LatestEventValue? } let semaphore = DispatchSemaphore(value: 0) @@ -241,7 +241,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { Task { do { - result.latestEvent = await room.latestEvent() + result.latestEvent = await room.newLatestEvent() result.roomInfo = try await room.roomInfo() } catch { MXLog.error("Failed fetching room info with error: \(error)") @@ -263,9 +263,18 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { var lastMessageDate: Date? if let latestRoomMessage = roomDetails.latestEvent { - let lastMessage = EventTimelineItemProxy(item: latestRoomMessage, uniqueID: .init("0")) - lastMessageDate = lastMessage.timestamp - attributedLastMessage = eventStringBuilder.buildAttributedString(for: lastMessage) + switch latestRoomMessage { + case .local(let timestamp, let senderID, let profile, let content, _): + let sender = TimelineItemSender(senderID: senderID, senderProfile: profile) + attributedLastMessage = eventStringBuilder.buildAttributedString(for: content, sender: sender, isOutgoing: true) + lastMessageDate = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) + case .remote(let timestamp, let senderID, let isOwn, let profile, let content): + let sender = TimelineItemSender(senderID: senderID, senderProfile: profile) + attributedLastMessage = eventStringBuilder.buildAttributedString(for: content, sender: sender, isOutgoing: isOwn) + lastMessageDate = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) + case .none: + break + } } var inviterProxy: RoomMemberProxyProtocol? diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 75a04544f..dd275edfb 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -108,22 +108,7 @@ class EventTimelineItemProxy { lazy var isEditable = item.isEditable - lazy var sender: TimelineItemSender = { - let profile = item.senderProfile - - switch profile { - case let .ready(displayName, isDisplayNameAmbiguous, avatarUrl): - return .init(id: item.sender, - displayName: displayName, - isDisplayNameAmbiguous: isDisplayNameAmbiguous, - avatarURL: avatarUrl.flatMap(URL.init(string:))) - default: - return .init(id: item.sender, - displayName: nil, - isDisplayNameAmbiguous: false, - avatarURL: nil) - } - }() + lazy var sender = TimelineItemSender(senderID: item.sender, senderProfile: item.senderProfile) lazy var timestamp = Date(timeIntervalSince1970: TimeInterval(item.timestamp / 1000)) diff --git a/ElementX/Sources/Services/Timeline/TimelineItemSender.swift b/ElementX/Sources/Services/Timeline/TimelineItemSender.swift index 56831c060..f3208744f 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemSender.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemSender.swift @@ -6,7 +6,8 @@ // Please see LICENSE files in the repository root for full details. // -import UIKit +import MatrixRustSDK +import SwiftUI struct TimelineItemSender: Identifiable, Hashable { static let test = TimelineItemSender(id: "@test.matrix.org") @@ -22,6 +23,21 @@ struct TimelineItemSender: Identifiable, Hashable { self.isDisplayNameAmbiguous = isDisplayNameAmbiguous self.avatarURL = avatarURL } + + init(senderID: String, senderProfile: ProfileDetails) { + switch senderProfile { + case let .ready(displayName, isDisplayNameAmbiguous, avatarUrl): + self.init(id: senderID, + displayName: displayName, + isDisplayNameAmbiguous: isDisplayNameAmbiguous, + avatarURL: avatarUrl.flatMap(URL.init(string:))) + default: + self.init(id: senderID, + displayName: nil, + isDisplayNameAmbiguous: false, + avatarURL: nil) + } + } var disambiguatedDisplayName: String? { guard let displayName else { diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 8d7196062..10373d3d4 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -678,7 +678,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { case .pending: return .loading case .ready(let content, let senderID, let senderProfile, _, _): - let sender = buildTimelineItemSender(senderID: senderID, senderProfile: senderProfile) + let sender = TimelineItemSender(senderID: senderID, senderProfile: senderProfile) let latestEventContent: TimelineEventContent = switch content { case .msgLike(let messageLikeContent): @@ -814,7 +814,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { case .pending: return .init(details: .loading(eventID: details.eventId()), isThreaded: isThreaded) case let .ready(timelineItem, senderID, senderProfile, _, _): - let sender = buildTimelineItemSender(senderID: senderID, senderProfile: senderProfile) + let sender = TimelineItemSender(senderID: senderID, senderProfile: senderProfile) let replyContent: TimelineEventContent @@ -850,21 +850,6 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol { // MARK: - Helpers - private func buildTimelineItemSender(senderID: String, senderProfile: ProfileDetails?) -> TimelineItemSender { - switch senderProfile { - case let .ready(displayName, isDisplayNameAmbiguous, avatarUrl): - return TimelineItemSender(id: senderID, - displayName: displayName, - isDisplayNameAmbiguous: isDisplayNameAmbiguous, - avatarURL: avatarUrl.flatMap(URL.init(string:))) - default: - return TimelineItemSender(id: senderID, - displayName: nil, - isDisplayNameAmbiguous: false, - avatarURL: nil) - } - } - private func buildMessageTimelineItemContent(messageType: MessageType?, senderID: String, senderDisplayName: String?) -> EventBasedMessageTimelineItemContentType { switch messageType { case .audio(let content): diff --git a/project.yml b/project.yml index a4de8a036..b26967c0e 100644 --- a/project.yml +++ b/project.yml @@ -71,7 +71,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 25.11.18 + exactVersion: 25.11.24 # path: ../matrix-rust-sdk Compound: path: compound-ios