diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 62c10b5a24..43bcd29711 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -195,6 +195,7 @@ 355B11D08CE0CEF97A813236 /* AppRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A9E3FBE8A66B5A17AD7F74 /* AppRoutes.swift */; }; 3582056513A384F110EC8274 /* MediaPlayerProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7A2C4A3A74F0D2FFE9356A /* MediaPlayerProviderTests.swift */; }; 35E975CFDA60E05362A7CF79 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1222DB76B917EB8A55365BA5 /* target.yml */; }; + 3623BACEA8F5BCC63E26A0D3 /* BlanckFormCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F94F70480243CAA65A2008C /* BlanckFormCoordinator.swift */; }; 366D5BFE52CB79E804C7D095 /* CallScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAD9547E47C58930E2CE8306 /* CallScreenViewModelTests.swift */; }; 368C8758FCD079E6AAA18C2C /* NoticeRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */; }; 36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; }; @@ -246,6 +247,7 @@ 42F1C8731166633E35A6D7E6 /* RoomEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A307A44F952CD73E63AE31 /* RoomEventStringBuilder.swift */; }; 4362C770C7E05ADC750E5070 /* LongPressWithFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21DC6A9917A7123E7E9A3F81 /* LongPressWithFeedback.swift */; }; 43EF6D8E694F54C5471BF5F3 /* TimelineBubbleLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DCA495ED42D2463DDAA94D /* TimelineBubbleLayout.swift */; }; + 43F06DF42EC00B3CE2B020A4 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC3F82523D6F48B926D6AF68 /* AppSettings.swift */; }; 43F35A7E5703D64DB0519C59 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */; }; 440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */; }; 44121202B4A260C98BF615A7 /* RoomMembersListScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */; }; @@ -398,7 +400,6 @@ 6BAD956B909A6E29F6CC6E7C /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC23C63849452BC86EA2852 /* ButtonStyle.swift */; }; 6BB6944443C421C722ED1E7D /* portrait_test_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = F2D513D2477B57F90E98EEC0 /* portrait_test_video.mp4 */; }; 6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; }; - 6C5A2C454E6C198AB39ED760 /* SharedUserDefaultsKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA8DC95C079805B0B56E8A9 /* SharedUserDefaultsKeys.swift */; }; 6CD61FAF03E8986523C2ABB8 /* StartChatScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3005886F00029F058DB62BE /* StartChatScreenCoordinator.swift */; }; 6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */; }; 6E47D126DD7585E8F8237CE7 /* LoadableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */; }; @@ -511,7 +512,6 @@ 8868ACFA45E5B5E19514B575 /* LegalInformationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACCC1874C122E2BBE648B8F5 /* LegalInformationScreenUITests.swift */; }; 88F348E2CB14FF71CBBB665D /* AudioRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7475C5AE20BA896930907EA8 /* AudioRoomTimelineItemContent.swift */; }; 890F0D453FE388756479AC97 /* AnalyticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C687844F60BFF532D49A994C /* AnalyticsTests.swift */; }; - 8922219C5C934C4155E8CA50 /* SharedUserDefaultsKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA8DC95C079805B0B56E8A9 /* SharedUserDefaultsKeys.swift */; }; 8944548A684F1C837CEC47F4 /* RoomMembersListScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D0946F77B696176E062D037 /* RoomMembersListScreenModels.swift */; }; 89658A44C9FC19B58FD1C226 /* ServerConfirmationScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */; }; 899359A4D1147601F6C4E364 /* PillConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB8D34E94AB07128DB73D6C7 /* PillConstants.swift */; }; @@ -543,8 +543,6 @@ 9095B9E40DB5CF8BA26CE0D8 /* ReactionsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 153726EDCE1ACBB3D466A916 /* ReactionsSummaryView.swift */; }; 90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; }; 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; - 915E65C12AFA8F3F00DFB3BA /* LAContextMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 915E65C02AFA8F3F00DFB3BA /* LAContextMock.swift */; }; - 915E65C32AFA969D00DFB3BA /* BlanckFormCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 915E65C22AFA969D00DFB3BA /* BlanckFormCoordinator.swift */; }; 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; }; 92133B170A1F917685E9FF78 /* OnboardingScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D168471461717AF5689F64B /* OnboardingScreenUITests.swift */; }; 9219640F4D980CFC5FE855AD /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 536E72DCBEEC4A1FE66CFDCE /* target.yml */; }; @@ -642,6 +640,7 @@ A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; A743841F91B62B0E56217B04 /* SecureBackupKeyBackupScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DCB219D7B7B0299358FF81 /* SecureBackupKeyBackupScreenUITests.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; + A76493FD2AFD4F280028B09D /* NSESettingsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A76493FC2AFD4F280028B09D /* NSESettingsProtocol.swift */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; A7FD7B992E6EE6E5A8429197 /* RoomSummaryDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 142808B69851451AC32A2CEA /* RoomSummaryDetails.swift */; }; A816F7087C495D85048AC50E /* RoomMemberDetailsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */; }; @@ -872,12 +871,12 @@ E3CA565A4B9704F191B191F0 /* JoinedRoomSize+MemberCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */; }; E3E1E255DC8CB34BD8573E0D /* UserIndicatorControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */; }; E45C9FA22BC13B477FD3B4AC /* EmojiDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D99730313BEBF08CDE81EE3 /* EmojiDetection.swift */; }; + E468CC731C3F4D678499E52F /* LAContextMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BA5A62DA4B543827FF82354 /* LAContextMock.swift */; }; E481C8FDCB6C089963C95344 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = BC01130651CB23340B899032 /* DeviceKit */; }; E49F74BD93230BDEFFE5EA51 /* RoomNotificationSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */; }; E4B07FF075C99D04D9AF792D /* AppLockSetupPINScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B410B32B72C90BF94E481F33 /* AppLockSetupPINScreenModels.swift */; }; E4BAEED438A843D7B01D8069 /* CompletionSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F421E51DF00377DE1A01354 /* CompletionSuggestionView.swift */; }; E570117376826665640F0CFD /* SessionVerificationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16CAF20C9AC874A210E2DCF /* SessionVerificationScreenViewModelProtocol.swift */; }; - E571163060CBE87D82CE24FD /* NSESettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9DFC0FBA0FC6FC4DC0FC9FC /* NSESettings.swift */; }; E5F4C992845388B50BABACAA /* ServerSelectionScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8BC4C791D0E88CFCF4E5DF /* ServerSelectionScreenCoordinator.swift */; }; E62EC30B39354A391E32A126 /* AudioRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2D505742FDA21FCDC4C18A /* AudioRoomTimelineView.swift */; }; E67418DACEDBC29E988E6ACD /* message.caf in Resources */ = {isa = PBXBuildFile; fileRef = ED482057AE39D5C6D9C5F3D8 /* message.caf */; }; @@ -1135,6 +1134,7 @@ 1B6E30BB748F3F480F077969 /* RoomMemberDetailsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenModels.swift; sourceTree = ""; }; 1B8E176484A89BAC389D4076 /* RoomMembersListScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreen.swift; sourceTree = ""; }; 1B927CF5EF7FCCDA5EDC474B /* NotificationItemProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxyProtocol.swift; sourceTree = ""; }; + 1BA5A62DA4B543827FF82354 /* LAContextMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LAContextMock.swift; sourceTree = ""; }; 1C21A715237F2B6D6E80998C /* SecureBackupControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupControllerProtocol.swift; sourceTree = ""; }; 1CC09F30B0E1010951952BDC /* SecureBackupLogoutConfirmationScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenUITests.swift; sourceTree = ""; }; 1CC575D1895FA62591451A93 /* RoomMemberDetailsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreen.swift; sourceTree = ""; }; @@ -1525,13 +1525,12 @@ 8F421E51DF00377DE1A01354 /* CompletionSuggestionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionSuggestionView.swift; sourceTree = ""; }; 8F61A0DD8243B395499C99A2 /* InvitesScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenUITests.swift; sourceTree = ""; }; 8F7D42E66E939B709C1EC390 /* MockRoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomSummaryProvider.swift; sourceTree = ""; }; + 8F94F70480243CAA65A2008C /* BlanckFormCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlanckFormCoordinator.swift; sourceTree = ""; }; 8FC803282F9268D49F4ABF14 /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = ""; }; 907FA4DE17DEA1A3738EFB83 /* AudioRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorder.swift; sourceTree = ""; }; 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineItem.swift; sourceTree = ""; }; 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemView.swift; sourceTree = ""; }; 913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachmentData.swift; sourceTree = ""; }; - 915E65C02AFA8F3F00DFB3BA /* LAContextMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LAContextMock.swift; sourceTree = ""; }; - 915E65C22AFA969D00DFB3BA /* BlanckFormCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlanckFormCoordinator.swift; sourceTree = ""; }; 91831D7042EADD0CC2B5EC36 /* SecureBackupScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupScreenUITests.swift; sourceTree = ""; }; 91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = ""; }; 923485F85E1D765EF9D20E88 /* UserProfileCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileCell.swift; sourceTree = ""; }; @@ -1599,6 +1598,7 @@ 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 = ""; }; + A76493FC2AFD4F280028B09D /* NSESettingsProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESettingsProtocol.swift; sourceTree = ""; }; A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = ""; }; A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenCoordinator.swift; sourceTree = ""; }; A8903A9F615BBD0E6D7CD133 /* ApplicationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationProtocol.swift; sourceTree = ""; }; @@ -1806,7 +1806,6 @@ DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenUITests.swift; sourceTree = ""; }; DAB8D7926A5684E18196B538 /* VoiceMessageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCache.swift; sourceTree = ""; }; DB06F22CFA34885B40976061 /* RoomDetailsEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreen.swift; sourceTree = ""; }; - DBA8DC95C079805B0B56E8A9 /* SharedUserDefaultsKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedUserDefaultsKeys.swift; sourceTree = ""; }; DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXTests.swift; sourceTree = ""; }; 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 = ""; }; @@ -1855,7 +1854,6 @@ E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = ""; }; E992D7B8BE54B2AB454613AF /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = ""; }; E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = ""; }; - E9DFC0FBA0FC6FC4DC0FC9FC /* NSESettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESettings.swift; sourceTree = ""; }; EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = ""; }; EBBC5E7C0F8337D2A46EB2DD /* MigrationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenViewModelProtocol.swift; sourceTree = ""; }; EC589E641AE46EFB2962534D /* RoomMemberDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsViewModelTests.swift; sourceTree = ""; }; @@ -2402,10 +2400,10 @@ 2ECFF6B05DAA37EB10DBF7E8 /* UITests */ = { isa = PBXGroup; children = ( + 8F94F70480243CAA65A2008C /* BlanckFormCoordinator.swift */, 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */, 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */, B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */, - 915E65C22AFA969D00DFB3BA /* BlanckFormCoordinator.swift */, ); path = UITests; sourceTree = ""; @@ -2931,9 +2929,9 @@ children = ( 4959CECEC984B3995616F427 /* DataProtectionManager.swift */, D3D455BC2423D911A62ACFB2 /* NSELogger.swift */, - E9DFC0FBA0FC6FC4DC0FC9FC /* NSESettings.swift */, EEAA2832D93EC7D2608703FB /* NSEUserSession.swift */, 49E751D7EDB6043238111D90 /* UNNotificationRequest.swift */, + A76493FC2AFD4F280028B09D /* NSESettingsProtocol.swift */, ); path = Other; sourceTree = ""; @@ -3350,7 +3348,7 @@ 851B95BB98649B8E773D6790 /* AppLockService.swift */, 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */, 490BEADEFB2D6B7C9F618AE8 /* AppLockTimer.swift */, - 915E65C02AFA8F3F00DFB3BA /* LAContextMock.swift */, + 1BA5A62DA4B543827FF82354 /* LAContextMock.swift */, ); path = AppLock; sourceTree = ""; @@ -4186,7 +4184,6 @@ F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */, B3A1398EFF65090FDA1CB639 /* ProcessInfo.swift */, 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */, - DBA8DC95C079805B0B56E8A9 /* SharedUserDefaultsKeys.swift */, 4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */, B1E227F34BE43B08E098796E /* TestablePreview.swift */, 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */, @@ -5078,6 +5075,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 43F06DF42EC00B3CE2B020A4 /* AppSettings.swift in Sources */, F253AAB4C8F06208173C9C4A /* Assets.swift in Sources */, 484202C5D50983442D24D061 /* AttributedString.swift in Sources */, CDCA8A559E098503DDE29477 /* AttributedStringBuilder.swift in Sources */, @@ -5108,7 +5106,6 @@ E2DB696117BAEABAD5718023 /* MediaSourceProxy.swift in Sources */, 4FC085B1E5D1EB804495E2F4 /* MockMediaProvider.swift in Sources */, 5455147CAC63F71E48F7D699 /* NSELogger.swift in Sources */, - E571163060CBE87D82CE24FD /* NSESettings.swift in Sources */, 30CC4F796B27BE8B1DFDBF5A /* NSEUserSession.swift in Sources */, 1D5DC685CED904386C89B7DA /* NSRegularExpresion.swift in Sources */, 5C02841B2A86327B2C377682 /* NotificationConstants.swift in Sources */, @@ -5117,13 +5114,13 @@ B89990DD875B0B603D4D4332 /* NotificationItemProxyProtocol.swift in Sources */, B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */, 234E2C782981003971ABE96E /* PermalinkBuilder.swift in Sources */, + A76493FD2AFD4F280028B09D /* NSESettingsProtocol.swift in Sources */, 62418EA4E3EB597AD184AEB6 /* PillConstants.swift in Sources */, 55CDD3968D95D1A820B5491E /* PlaceholderAvatarImage.swift in Sources */, F12F6BED7B6D7EE4BEE55039 /* PlainMentionBuilder.swift in Sources */, 414F50CFCFEEE2611127DCFB /* RestorationToken.swift in Sources */, 17BC15DA08A52587466698C5 /* RoomMessageEventStringBuilder.swift in Sources */, 7354D094A4C59B555F407FA1 /* RustTracing.swift in Sources */, - 6C5A2C454E6C198AB39ED760 /* SharedUserDefaultsKeys.swift in Sources */, 422E8D182CA688D4565CD1E1 /* String.swift in Sources */, ECA636DAF071C611FDC2BB57 /* Strings+Untranslated.swift in Sources */, 6EC7A40A537CFB3D526A111C /* Strings.swift in Sources */, @@ -5355,6 +5352,7 @@ 6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */, A4B0BAD62A12ED76BD611B79 /* BadgeView.swift in Sources */, 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */, + 3623BACEA8F5BCC63E26A0D3 /* BlanckFormCoordinator.swift in Sources */, 5EE1D4E316D66943E97FDCF2 /* BloomView.swift in Sources */, B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */, E794AB6ABE1FF5AF0573FEA1 /* BlurHashEncode.swift in Sources */, @@ -5502,11 +5500,11 @@ FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */, CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */, 454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */, + E468CC731C3F4D678499E52F /* LAContextMock.swift in Sources */, D5681C80D8281560AACE0035 /* Label.swift in Sources */, EEAE954289DE813A61656AE0 /* LayoutDirection.swift in Sources */, 42B084FDE621FBEE433AF444 /* LegalInformationScreen.swift in Sources */, 9EBDC79CAC9B63A0D626E333 /* LegalInformationScreenCoordinator.swift in Sources */, - 915E65C12AFA8F3F00DFB3BA /* LAContextMock.swift in Sources */, F40B097470D3110DFDB1FAAA /* LegalInformationScreenModels.swift in Sources */, BDED6DA7AD1E76018C424143 /* LegalInformationScreenViewModel.swift in Sources */, A9D349478F7D4A2B1E40CEF9 /* LegalInformationScreenViewModelProtocol.swift in Sources */, @@ -5790,8 +5788,6 @@ E0B6A569AC3E81D233B43D60 /* SettingsScreenViewModel.swift in Sources */, A009BDFB0A6816D4C392ADCB /* SettingsScreenViewModelProtocol.swift in Sources */, 1C8BC70A18060677E295A846 /* ShareToMapsAppActivity.swift in Sources */, - 915E65C32AFA969D00DFB3BA /* BlanckFormCoordinator.swift in Sources */, - 8922219C5C934C4155E8CA50 /* SharedUserDefaultsKeys.swift in Sources */, 274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */, 77920AFA8091AC6B9F190C90 /* Signposter.swift in Sources */, 8BC8EF6705A78946C1F22891 /* SoftLogoutScreen.swift in Sources */, @@ -6132,6 +6128,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -6156,6 +6153,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -6181,6 +6179,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; + OTHER_SWIFT_FLAGS = "-DIS_MAIN_APP"; PILLS_UT_TYPE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER).pills"; PRODUCT_BUNDLE_IDENTIFIER = "$(BASE_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(APP_NAME)"; @@ -6421,6 +6420,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = "$(MARKETING_VERSION)"; + OTHER_SWIFT_FLAGS = "-DIS_NSE"; PRODUCT_BUNDLE_IDENTIFIER = "${BASE_BUNDLE_IDENTIFIER}.nse"; PRODUCT_DISPLAY_NAME = "$(APP_DISPLAY_NAME)"; PRODUCT_NAME = NSE; @@ -6616,7 +6616,7 @@ repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = "0.0.1-november23"; + version = "0.0.2-november23"; }; }; 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index ac87ac3802..c66c4bd6ad 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -130,8 +130,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-rust-components-swift", "state" : { - "revision" : "29870facdcf257e9cd79ee0eacd52b7425b92736", - "version" : "0.0.1-november23" + "revision" : "f647c08eb338ddc20a41429330f366b6bb97d879", + "version" : "0.0.2-november23" } }, { diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index cc6bece1e9..ad923b512c 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -171,9 +171,11 @@ "common_video" = "Video"; "common_voice_message" = "Voice message"; "common_waiting" = "Waiting…"; -"common_waiting_for_decryption_key" = "Waiting for decryption key"; +"common_waiting_for_decryption_key" = "Waiting for this message"; +"common.report_a_problem" = "Report a problem"; "common_poll_end_confirmation" = "Are you sure you want to end this poll?"; "common_poll_summary" = "Poll: %1$@"; +"common_verify_device" = "Verify device"; "confirm_recovery_key_banner_message" = "Your chat backup is currently out of sync. You need to confirm your recovery key to maintain access to your chat backup."; "confirm_recovery_key_banner_title" = "Confirm your recovery key"; "crash_detection_dialog_content" = "%1$@ crashed the last time it was used. Would you like to share a crash report with us?"; @@ -217,6 +219,8 @@ "notification_invitation_action_join" = "Join"; "notification_invitation_action_reject" = "Reject"; "notification_invite_body" = "Invited you to chat"; +"notification_mentioned_you_body" = "%1$@ mentioned you.\n%2$@"; +"notification_mentioned_you_fallback_body" = "You have been mentioned.\n%1$@"; "notification_new_messages" = "New Messages"; "notification_reaction_body" = "Reacted with %1$@"; "notification_room_action_mark_as_read" = "Mark as read"; @@ -421,6 +425,8 @@ "screen_recovery_key_change_success" = "Recovery key changed"; "screen_recovery_key_change_title" = "Change recovery key?"; "screen_recovery_key_confirm_description" = "Enter your recovery key to confirm access to your chat backup."; +"screen_recovery_key_confirm_error_content" = "Please try again to confirm access to your chat backup."; +"screen_recovery_key_confirm_error_title" = "Incorrect recovery key"; "screen_recovery_key_confirm_key_description" = "Enter the 48 character code."; "screen_recovery_key_confirm_key_placeholder" = "Enter..."; "screen_recovery_key_confirm_success" = "Recovery key confirmed"; @@ -518,6 +524,7 @@ "screen_session_verification_positive_button_canceled" = "Retry verification"; "screen_session_verification_positive_button_initial" = "I am ready"; "screen_session_verification_positive_button_verifying_ongoing" = "Waiting to match"; +"screen_session_verification_ready_subtitle" = "Compare a unique set of emojis."; "screen_session_verification_request_accepted_subtitle" = "Compare the unique emoji, ensuring they appear in the same order."; "screen_session_verification_they_dont_match" = "They don’t match"; "screen_session_verification_they_match" = "They match"; diff --git a/ElementX/Sources/Application/AppSettings.swift b/ElementX/Sources/Application/AppSettings.swift index 4b19e7f002..8fead7b17a 100644 --- a/ElementX/Sources/Application/AppSettings.swift +++ b/ElementX/Sources/Application/AppSettings.swift @@ -52,7 +52,7 @@ final class AppSettings { /// UserDefaults to be used on reads and writes. private static var store: UserDefaults! = UserDefaults(suiteName: suiteName) - + static func reset() { MXLog.warning("Resetting the AppSettings.") store.removePersistentDomain(forName: suiteName) @@ -181,6 +181,7 @@ final class AppSettings { // MARK: - Analytics + #if !IS_NSE #if DEBUG /// The configuration to use for analytics during development. Set `isEnabled` to false to disable analytics in debug builds. /// **Note:** Analytics are disabled by default for forks. If you are maintaining a fork, set custom configurations. @@ -205,6 +206,7 @@ final class AppSettings { @UserPreference(key: UserDefaultsKeys.timelineStyle, defaultValue: TimelineStyle.bubbles, storageType: .userDefaults(store)) var timelineStyle + #endif @UserPreference(key: UserDefaultsKeys.shouldCollapseRoomStateEvents, defaultValue: true, storageType: .volatile) var shouldCollapseRoomStateEvents @@ -234,9 +236,9 @@ final class AppSettings { /// Tag describing which set of device specific rules a pusher executes. @UserPreference(key: UserDefaultsKeys.pusherProfileTag, storageType: .userDefaults(store)) var pusherProfileTag: String? - - // MARK: - Other + // MARK: - Other + let permalinkBaseURL: URL = "https://matrix.to" // MARK: - Logging diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 04f1389a9a..62762c64f2 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -376,13 +376,15 @@ public enum L10n { public static var commonVerificationCancelled: String { return L10n.tr("Localizable", "common_verification_cancelled") } /// Verification complete public static var commonVerificationComplete: String { return L10n.tr("Localizable", "common_verification_complete") } + /// Verify device + public static var commonVerifyDevice: String { return L10n.tr("Localizable", "common_verify_device") } /// Video public static var commonVideo: String { return L10n.tr("Localizable", "common_video") } /// Voice message public static var commonVoiceMessage: String { return L10n.tr("Localizable", "common_voice_message") } /// Waiting… public static var commonWaiting: String { return L10n.tr("Localizable", "common_waiting") } - /// Waiting for decryption key + /// Waiting for this message public static var commonWaitingForDecryptionKey: String { return L10n.tr("Localizable", "common_waiting_for_decryption_key") } /// Your chat backup is currently out of sync. You need to confirm your recovery key to maintain access to your chat backup. public static var confirmRecoveryKeyBannerMessage: String { return L10n.tr("Localizable", "confirm_recovery_key_banner_message") } @@ -506,6 +508,16 @@ public enum L10n { } /// Invited you to chat public static var notificationInviteBody: String { return L10n.tr("Localizable", "notification_invite_body") } + /// %1$@ mentioned you. + /// %2$@ + public static func notificationMentionedYouBody(_ p1: Any, _ p2: Any) -> String { + return L10n.tr("Localizable", "notification_mentioned_you_body", String(describing: p1), String(describing: p2)) + } + /// You have been mentioned. + /// %1$@ + public static func notificationMentionedYouFallbackBody(_ p1: Any) -> String { + return L10n.tr("Localizable", "notification_mentioned_you_fallback_body", String(describing: p1)) + } /// New Messages public static var notificationNewMessages: String { return L10n.tr("Localizable", "notification_new_messages") } /// Plural format key: "%#@COUNT@" @@ -1020,6 +1032,10 @@ public enum L10n { public static var screenRecoveryKeyChangeTitle: String { return L10n.tr("Localizable", "screen_recovery_key_change_title") } /// Enter your recovery key to confirm access to your chat backup. public static var screenRecoveryKeyConfirmDescription: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_description") } + /// Please try again to confirm access to your chat backup. + public static var screenRecoveryKeyConfirmErrorContent: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_error_content") } + /// Incorrect recovery key + public static var screenRecoveryKeyConfirmErrorTitle: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_error_title") } /// Enter the 48 character code. public static var screenRecoveryKeyConfirmKeyDescription: String { return L10n.tr("Localizable", "screen_recovery_key_confirm_key_description") } /// Enter... @@ -1240,6 +1256,8 @@ public enum L10n { public static var screenSessionVerificationPositiveButtonInitial: String { return L10n.tr("Localizable", "screen_session_verification_positive_button_initial") } /// Waiting to match public static var screenSessionVerificationPositiveButtonVerifyingOngoing: String { return L10n.tr("Localizable", "screen_session_verification_positive_button_verifying_ongoing") } + /// Compare a unique set of emojis. + public static var screenSessionVerificationReadySubtitle: String { return L10n.tr("Localizable", "screen_session_verification_ready_subtitle") } /// Compare the unique emoji, ensuring they appear in the same order. public static var screenSessionVerificationRequestAcceptedSubtitle: String { return L10n.tr("Localizable", "screen_session_verification_request_accepted_subtitle") } /// They don’t match @@ -1547,6 +1565,11 @@ public enum L10n { /// Edit poll public static var editPoll: String { return L10n.tr("Localizable", "action.edit_poll") } } + + public enum Common { + /// Report a problem + public static var reportAProblem: String { return L10n.tr("Localizable", "common.report_a_problem") } + } } // swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length // swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index d9dcafe3d8..7b2d1e012b 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -234,27 +234,27 @@ class SDKClientMock: SDKClientProtocol { } //MARK: - getMediaFile - public var getMediaFileMediaSourceBodyMimeTypeTempDirThrowableError: Error? - public var getMediaFileMediaSourceBodyMimeTypeTempDirCallsCount = 0 - public var getMediaFileMediaSourceBodyMimeTypeTempDirCalled: Bool { - return getMediaFileMediaSourceBodyMimeTypeTempDirCallsCount > 0 - } - public var getMediaFileMediaSourceBodyMimeTypeTempDirReceivedArguments: (mediaSource: MediaSource, body: String?, mimeType: String, tempDir: String?)? - public var getMediaFileMediaSourceBodyMimeTypeTempDirReceivedInvocations: [(mediaSource: MediaSource, body: String?, mimeType: String, tempDir: String?)] = [] - public var getMediaFileMediaSourceBodyMimeTypeTempDirReturnValue: MediaFileHandle! - public var getMediaFileMediaSourceBodyMimeTypeTempDirClosure: ((MediaSource, String?, String, String?) throws -> MediaFileHandle)? - - public func getMediaFile(mediaSource: MediaSource, body: String?, mimeType: String, tempDir: String?) throws -> MediaFileHandle { - if let error = getMediaFileMediaSourceBodyMimeTypeTempDirThrowableError { + public var getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirThrowableError: Error? + public var getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirCallsCount = 0 + public var getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirCalled: Bool { + return getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirCallsCount > 0 + } + public var getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirReceivedArguments: (mediaSource: MediaSource, body: String?, mimeType: String, useCache: Bool, tempDir: String?)? + public var getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirReceivedInvocations: [(mediaSource: MediaSource, body: String?, mimeType: String, useCache: Bool, tempDir: String?)] = [] + public var getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirReturnValue: MediaFileHandle! + public var getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirClosure: ((MediaSource, String?, String, Bool, String?) throws -> MediaFileHandle)? + + public func getMediaFile(mediaSource: MediaSource, body: String?, mimeType: String, useCache: Bool, tempDir: String?) throws -> MediaFileHandle { + if let error = getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirThrowableError { throw error } - getMediaFileMediaSourceBodyMimeTypeTempDirCallsCount += 1 - getMediaFileMediaSourceBodyMimeTypeTempDirReceivedArguments = (mediaSource: mediaSource, body: body, mimeType: mimeType, tempDir: tempDir) - getMediaFileMediaSourceBodyMimeTypeTempDirReceivedInvocations.append((mediaSource: mediaSource, body: body, mimeType: mimeType, tempDir: tempDir)) - if let getMediaFileMediaSourceBodyMimeTypeTempDirClosure = getMediaFileMediaSourceBodyMimeTypeTempDirClosure { - return try getMediaFileMediaSourceBodyMimeTypeTempDirClosure(mediaSource, body, mimeType, tempDir) + getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirCallsCount += 1 + getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirReceivedArguments = (mediaSource: mediaSource, body: body, mimeType: mimeType, useCache: useCache, tempDir: tempDir) + getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirReceivedInvocations.append((mediaSource: mediaSource, body: body, mimeType: mimeType, useCache: useCache, tempDir: tempDir)) + if let getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirClosure = getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirClosure { + return try getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirClosure(mediaSource, body, mimeType, useCache, tempDir) } else { - return getMediaFileMediaSourceBodyMimeTypeTempDirReturnValue + return getMediaFileMediaSourceBodyMimeTypeUseCacheTempDirReturnValue } } //MARK: - getMediaThumbnail diff --git a/ElementX/Sources/Other/Extensions/UNNotificationContent.swift b/ElementX/Sources/Other/Extensions/UNNotificationContent.swift index 149fae7354..2b13e8b4da 100644 --- a/ElementX/Sources/Other/Extensions/UNNotificationContent.swift +++ b/ElementX/Sources/Other/Extensions/UNNotificationContent.swift @@ -86,8 +86,12 @@ extension UNMutableNotificationContent { switch await mediaProvider.loadFileFromSource(mediaSource) { case .success(let file): do { + guard let url = file.url else { + MXLog.error("Couldn't add media attachment: URL is nil") + return self + } let identifier = ProcessInfo.processInfo.globallyUniqueString - let newURL = try FileManager.default.copyFileToTemporaryDirectory(file: file.url, with: "\(identifier).\(file.url.pathExtension)") + let newURL = try FileManager.default.copyFileToTemporaryDirectory(file: url, with: "\(identifier).\(url.pathExtension)") let attachment = try UNNotificationAttachment(identifier: identifier, url: newURL, options: nil) diff --git a/ElementX/Sources/Other/Pills/PlainMentionBuilder.swift b/ElementX/Sources/Other/Pills/PlainMentionBuilder.swift index fb3093f99e..b935b871fc 100644 --- a/ElementX/Sources/Other/Pills/PlainMentionBuilder.swift +++ b/ElementX/Sources/Other/Pills/PlainMentionBuilder.swift @@ -20,5 +20,7 @@ import Foundation struct PlainMentionBuilder: MentionBuilderProtocol { func handleAllUsersMention(for attributedString: NSMutableAttributedString, in range: NSRange) { } - func handleUserMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, userID: String) { } + func handleUserMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, userID: String) { + attributedString.insert(NSAttributedString(string: "@"), at: range.location) + } } diff --git a/ElementX/Sources/Services/Media/Provider/MediaFileHandleProxy.swift b/ElementX/Sources/Services/Media/Provider/MediaFileHandleProxy.swift index cf7f798ee2..00fe7f4105 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaFileHandleProxy.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaFileHandleProxy.swift @@ -37,8 +37,14 @@ class MediaFileHandleProxy { } /// The media file's location on disk. - var url: URL { - URL(filePath: handle.path()) + var url: URL? { + do { + let path = try handle.path() + return URL(filePath: path) + } catch { + MXLog.error("URL is missing for media file handle: \(error)") + return nil + } } } @@ -60,6 +66,10 @@ extension MediaFileHandleProxy: Hashable { /// /// This type allows for mocking but doesn't provide the automatic clean-up mechanism provided by the SDK. private class UnmanagedMediaFileHandle: MediaFileHandleProtocol { + func persist(path: String) throws -> Bool { + false + } + let url: URL init(url: URL) { diff --git a/ElementX/Sources/Services/Media/Provider/MediaLoader.swift b/ElementX/Sources/Services/Media/Provider/MediaLoader.swift index 1ca69fe458..fd286ed1a5 100644 --- a/ElementX/Sources/Services/Media/Provider/MediaLoader.swift +++ b/ElementX/Sources/Services/Media/Provider/MediaLoader.swift @@ -48,7 +48,7 @@ actor MediaLoader: MediaLoaderProtocol { func loadMediaFileForSource(_ source: MediaSourceProxy, body: String?) async throws -> MediaFileHandleProxy { let result = try await Task.dispatch(on: clientQueue) { - try self.client.getMediaFile(mediaSource: source.underlyingSource, body: body, mimeType: source.mimeType ?? "application/octet-stream", tempDir: nil) + try self.client.getMediaFile(mediaSource: source.underlyingSource, body: body, mimeType: source.mimeType ?? "application/octet-stream", useCache: true, tempDir: nil) } return MediaFileHandleProxy(handle: result) diff --git a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift index cbda78c959..bad0fa8a7c 100644 --- a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift +++ b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxy.swift @@ -60,6 +60,10 @@ struct NotificationItemProxy: NotificationItemProxyProtocol { var isNoisy: Bool { notificationItem.isNoisy ?? false } + + var hasMention: Bool { + notificationItem.hasMention ?? false + } var senderAvatarMediaSource: MediaSourceProxy? { if let senderAvatarURLString = notificationItem.senderInfo.avatarUrl, @@ -114,4 +118,6 @@ struct EmptyNotificationItemProxy: NotificationItemProxyProtocol { var notificationIdentifier: String { "" } var roomJoinedMembers: Int { 0 } + + var hasMention: Bool { false } } diff --git a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxyProtocol.swift b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxyProtocol.swift index 9f1ca8d419..20149a6532 100644 --- a/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxyProtocol.swift +++ b/ElementX/Sources/Services/Notification/Proxy/NotificationItemProxyProtocol.swift @@ -44,6 +44,8 @@ protocol NotificationItemProxyProtocol { var isRoomDirect: Bool { get } var isNoisy: Bool { get } + + var hasMention: Bool { get } } extension NotificationItemProxyProtocol { diff --git a/ElementX/Sources/Services/SecureBackup/SecureBackupController.swift b/ElementX/Sources/Services/SecureBackup/SecureBackupController.swift index bae72b8d2d..f5d7f5d7ee 100644 --- a/ElementX/Sources/Services/SecureBackup/SecureBackupController.swift +++ b/ElementX/Sources/Services/SecureBackup/SecureBackupController.swift @@ -182,7 +182,7 @@ extension BackupState { var keyBackupState: SecureBackupKeyBackupState { switch self { case .unknown: - return .unknown + return .disabled case .creating: return .enabling case .enabling: @@ -195,8 +195,6 @@ extension BackupState { return .enabled case .disabling: return .disabling - case .disabled: - return .disabled } } } diff --git a/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManager.swift b/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManager.swift index 3c6932d7ea..62f6241e55 100644 --- a/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManager.swift +++ b/ElementX/Sources/Services/VoiceMessage/VoiceMessageMediaManager.swift @@ -18,6 +18,7 @@ import Foundation enum VoiceMessageMediaManagerError: Error { case unsupportedMimeTye + case missingURL } private final class VoiceMessageConversionRequest { @@ -76,8 +77,11 @@ class VoiceMessageMediaManager: VoiceMessageMediaManagerProtocol { } // Convert from ogg - let convertedFileURL = URL.temporaryDirectory.appendingPathComponent(fileHandle.url.deletingPathExtension().lastPathComponent).appendingPathExtension(AudioConverterPreferredFileExtension.mpeg4aac.rawValue) - try audioConverter.convertToMPEG4AAC(sourceURL: fileHandle.url, destinationURL: convertedFileURL) + guard let url = fileHandle.url else { + throw VoiceMessageMediaManagerError.missingURL + } + let convertedFileURL = URL.temporaryDirectory.appendingPathComponent(url.deletingPathExtension().lastPathComponent).appendingPathExtension(AudioConverterPreferredFileExtension.mpeg4aac.rawValue) + try audioConverter.convertToMPEG4AAC(sourceURL: url, destinationURL: convertedFileURL) // Cache the file and return the url let result = voiceMessageCache.cache(mediaSource: source, using: convertedFileURL, move: true) diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index ab43ea33e5..b1b42c0399 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -123,6 +123,8 @@ targets: SWIFT_OBJC_BRIDGING_HEADER: ElementX/SupportingFiles/ElementX-Bridging-Header.h SWIFT_OBJC_INTERFACE_HEADER_NAME: GeneratedInterface-Swift.h PILLS_UT_TYPE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER).pills + OTHER_SWIFT_FLAGS: + - "-DIS_MAIN_APP" preBuildScripts: - name: 🛠 SwiftGen diff --git a/NSE/Sources/NotificationContentBuilder.swift b/NSE/Sources/NotificationContentBuilder.swift index 054acd78eb..1f1ab19140 100644 --- a/NSE/Sources/NotificationContentBuilder.swift +++ b/NSE/Sources/NotificationContentBuilder.swift @@ -99,8 +99,19 @@ struct NotificationContentBuilder { private func processRoomMessage(notificationItem: NotificationItemProxyProtocol, messageType: MessageType, mediaProvider: MediaProviderProtocol?) async throws -> UNMutableNotificationContent { var notification = try await processCommonRoomMessage(notificationItem: notificationItem, mediaProvider: mediaProvider) - let senderDisplayName = notificationItem.senderDisplayName ?? notificationItem.roomDisplayName - notification.body = String(messageEventStringBuilder.buildAttributedString(for: messageType, senderDisplayName: senderDisplayName, prefixWithSenderName: false).characters) + let displayName = notificationItem.senderDisplayName ?? notificationItem.roomDisplayName + let message = String(messageEventStringBuilder.buildAttributedString(for: messageType, senderDisplayName: displayName, prefixWithSenderName: false).characters) + let body: String + if notificationItem.hasMention { + if let senderDisplayName = notificationItem.senderDisplayName { + body = L10n.notificationMentionedYouBody(senderDisplayName, message) + } else { + body = L10n.notificationMentionedYouFallbackBody(message) + } + } else { + body = message + } + notification.body = body switch messageType { case .image(content: let content): diff --git a/NSE/Sources/NotificationServiceExtension.swift b/NSE/Sources/NotificationServiceExtension.swift index 0c7139f491..a9f57be7a7 100644 --- a/NSE/Sources/NotificationServiceExtension.swift +++ b/NSE/Sources/NotificationServiceExtension.swift @@ -40,8 +40,8 @@ import UserNotifications // We keep a global `environment` singleton to ensure that our app context, // database, logging, etc. are only ever setup once per *process* -private let settings = NSESettings() -private let notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: .homeDirectory, +private let settings: NSESettingsProtocol = AppSettings() +private let notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: settings.permalinkBaseURL, mentionBuilder: PlainMentionBuilder()))) private let keychainController = KeychainController(service: .sessions, accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier) diff --git a/NSE/Sources/Other/NSESettings.swift b/NSE/Sources/Other/NSESettings.swift deleted file mode 100644 index 486c4ff4b0..0000000000 --- a/NSE/Sources/Other/NSESettings.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright 2023 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -final class NSESettings { - private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier - - /// UserDefaults to be used on reads and writes. - private static var store: UserDefaults! = UserDefaults(suiteName: suiteName) - - /// The log level that should be used by `MXLog`. - @UserPreference(key: SharedUserDefaultsKeys.logLevel, defaultValue: TracingConfiguration.LogLevel.info, storageType: .userDefaults(store)) - var logLevel -} diff --git a/ElementX/Sources/Other/SharedUserDefaultsKeys.swift b/NSE/Sources/Other/NSESettingsProtocol.swift similarity index 75% rename from ElementX/Sources/Other/SharedUserDefaultsKeys.swift rename to NSE/Sources/Other/NSESettingsProtocol.swift index 93c3614cf7..bbef735ca5 100644 --- a/ElementX/Sources/Other/SharedUserDefaultsKeys.swift +++ b/NSE/Sources/Other/NSESettingsProtocol.swift @@ -14,6 +14,12 @@ // limitations under the License. // -enum SharedUserDefaultsKeys: String { - case logLevel +import Foundation + +protocol NSESettingsProtocol { + var permalinkBaseURL: URL { get } + + var logLevel: TracingConfiguration.LogLevel { get } } + +extension AppSettings: NSESettingsProtocol { } diff --git a/NSE/SupportingFiles/target.yml b/NSE/SupportingFiles/target.yml index d77d37757d..741ac94b9b 100644 --- a/NSE/SupportingFiles/target.yml +++ b/NSE/SupportingFiles/target.yml @@ -66,8 +66,8 @@ targets: DEVELOPMENT_TEAM: $(DEVELOPMENT_TEAM) CODE_SIGN_ENTITLEMENTS: NSE/SupportingFiles/NSE.entitlements SWIFT_OBJC_INTERFACE_HEADER_NAME: GeneratedInterface-Swift.h - debug: - release: + OTHER_SWIFT_FLAGS: + - "-DIS_NSE" sources: - path: ../Sources @@ -91,7 +91,6 @@ targets: - path: ../../ElementX/Sources/Other/Logging - path: ../../ElementX/Sources/Other/MatrixEntityRegex.swift - path: ../../ElementX/Sources/Other/PermalinkBuilder.swift - - path: ../../ElementX/Sources/Other/SharedUserDefaultsKeys.swift - path: ../../ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift - path: ../../ElementX/Sources/Other/UserAgentBuilder.swift - path: ../../ElementX/Sources/Other/UserPreference.swift @@ -107,3 +106,4 @@ targets: - path: ../../ElementX/Sources/Services/Notification/Proxy - path: ../../ElementX/Sources/Services/Room/RoomSummary/RoomMessageEventStringBuilder.swift - path: ../../ElementX/Sources/Services/UserSession/RestorationToken.swift + - path: ../../ElementX/Sources/Application/AppSettings.swift diff --git a/project.yml b/project.yml index 065e0c2074..736287e741 100644 --- a/project.yml +++ b/project.yml @@ -45,7 +45,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/matrix-org/matrix-rust-components-swift - exactVersion: 0.0.1-november23 + exactVersion: 0.0.2-november23 # path: ../matrix-rust-sdk Compound: url: https://github.com/vector-im/compound-ios