mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 11:58:32 +00:00
Adop the new SDK permalink detector and user builder
This commit is contained in:
committed by
Stefan Ceriu
parent
f8920d4d11
commit
fcc25dd441
@@ -102,6 +102,7 @@
|
|||||||
155063E980E763D4910EA3CF /* Analytics+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */; };
|
155063E980E763D4910EA3CF /* Analytics+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CFE236419E830E8946639C /* Analytics+SwiftUI.swift */; };
|
||||||
1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */; };
|
1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */; };
|
||||||
157E5FDDF419C0B2CA7E2C28 /* TimelineItemBubbledStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */; };
|
157E5FDDF419C0B2CA7E2C28 /* TimelineItemBubbledStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */; };
|
||||||
|
1583E2D766E4485FF91662FC /* PermalinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3EB5B1848CF4F64E63C6B7 /* PermalinkTests.swift */; };
|
||||||
158A2D528CC78C4E7A8ED608 /* MockRoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */; };
|
158A2D528CC78C4E7A8ED608 /* MockRoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */; };
|
||||||
167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */; };
|
167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */; };
|
||||||
16CBD087038DE3815CDA512C /* PollMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D38391154120264910D19528 /* PollMock.swift */; };
|
16CBD087038DE3815CDA512C /* PollMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D38391154120264910D19528 /* PollMock.swift */; };
|
||||||
@@ -148,7 +149,6 @@
|
|||||||
22882C710BC99EC34A5024A0 /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; };
|
22882C710BC99EC34A5024A0 /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; };
|
||||||
22C5483D01EEB290B8339817 /* HomeScreenInviteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FC33C3F6BF597E095CE9FA /* HomeScreenInviteCell.swift */; };
|
22C5483D01EEB290B8339817 /* HomeScreenInviteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FC33C3F6BF597E095CE9FA /* HomeScreenInviteCell.swift */; };
|
||||||
2335D1AB954C151FD8779F45 /* RoomPermissionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0096BC5DA86AF6B6E5742AC /* RoomPermissionsTests.swift */; };
|
2335D1AB954C151FD8779F45 /* RoomPermissionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0096BC5DA86AF6B6E5742AC /* RoomPermissionsTests.swift */; };
|
||||||
234E2C782981003971ABE96E /* PermalinkBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */; };
|
|
||||||
23701DE32ACD6FD40AA992C3 /* MediaUploadingPreprocessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE203026B9AD3DB412439866 /* MediaUploadingPreprocessorTests.swift */; };
|
23701DE32ACD6FD40AA992C3 /* MediaUploadingPreprocessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE203026B9AD3DB412439866 /* MediaUploadingPreprocessorTests.swift */; };
|
||||||
237FC70AA257B935F53316BA /* SessionVerificationControllerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */; };
|
237FC70AA257B935F53316BA /* SessionVerificationControllerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */; };
|
||||||
241CDEFE23819867D9B39066 /* RoomChangePermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */; };
|
241CDEFE23819867D9B39066 /* RoomChangePermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE75941583A033A9EDC9FE0 /* RoomChangePermissionsScreenViewModel.swift */; };
|
||||||
@@ -169,7 +169,6 @@
|
|||||||
274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97CE98208321C4D66E363612 /* ShimmerModifier.swift */; };
|
274CE3C986841D15FD530BF5 /* ShimmerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97CE98208321C4D66E363612 /* ShimmerModifier.swift */; };
|
||||||
275EDE8849A2AC1D9309ED7C /* TemplateScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */; };
|
275EDE8849A2AC1D9309ED7C /* TemplateScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */; };
|
||||||
2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = F75DF9500D69A3AAF8339E69 /* Untranslated.stringsdict */; };
|
2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = F75DF9500D69A3AAF8339E69 /* Untranslated.stringsdict */; };
|
||||||
27E9263DA75E266690A37EB1 /* PermalinkBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */; };
|
|
||||||
27F015B0D5436633B5B3C8C3 /* SecureBackupRecoveryKeyScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */; };
|
27F015B0D5436633B5B3C8C3 /* SecureBackupRecoveryKeyScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */; };
|
||||||
2814E7075BF3A5C0CCBC9F90 /* RoomDirectorySearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AF32E4136FD6F159D86C2C /* RoomDirectorySearchView.swift */; };
|
2814E7075BF3A5C0CCBC9F90 /* RoomDirectorySearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AF32E4136FD6F159D86C2C /* RoomDirectorySearchView.swift */; };
|
||||||
281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
|
281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
|
||||||
@@ -539,7 +538,6 @@
|
|||||||
7FF6E1FBE6E9517FD29A1D8E /* RoomChangeRolesScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48A5C34C4E4268EF65D171EF /* RoomChangeRolesScreenModels.swift */; };
|
7FF6E1FBE6E9517FD29A1D8E /* RoomChangeRolesScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48A5C34C4E4268EF65D171EF /* RoomChangeRolesScreenModels.swift */; };
|
||||||
8015842CB4DE1BE414D2CDED /* AppLockSetupBiometricsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */; };
|
8015842CB4DE1BE414D2CDED /* AppLockSetupBiometricsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C62E07C1164F5120727A2A8 /* AppLockSetupBiometricsScreenCoordinator.swift */; };
|
||||||
804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */; };
|
804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */; };
|
||||||
80D00A7C62AAB44F54725C43 /* PermalinkBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */; };
|
|
||||||
80DEA2A4B20F9E279EAE6B2B /* UserProfile+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */; };
|
80DEA2A4B20F9E279EAE6B2B /* UserProfile+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */; };
|
||||||
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36C0A6D59717193F49EA986 /* UserSessionTests.swift */; };
|
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36C0A6D59717193F49EA986 /* UserSessionTests.swift */; };
|
||||||
8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */; };
|
8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */; };
|
||||||
@@ -1569,7 +1567,6 @@
|
|||||||
6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableState.swift; sourceTree = "<group>"; };
|
6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableState.swift; sourceTree = "<group>"; };
|
||||||
6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = "<group>"; };
|
6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = "<group>"; };
|
||||||
6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelTests.swift; sourceTree = "<group>"; };
|
6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilderTests.swift; sourceTree = "<group>"; };
|
|
||||||
6FC5015B9634698BDB8701AF /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
6FC5015B9634698BDB8701AF /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
7023EB4F3B7C7D1FBA68638B /* TimelineItemDebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemDebugView.swift; sourceTree = "<group>"; };
|
7023EB4F3B7C7D1FBA68638B /* TimelineItemDebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemDebugView.swift; sourceTree = "<group>"; };
|
||||||
7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModel.swift; sourceTree = "<group>"; };
|
7061BE2C0BF427C38AEDEF5E /* SecureBackupRecoveryKeyScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
@@ -2120,7 +2117,6 @@
|
|||||||
F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = "<group>"; };
|
F733F135E6D67BBBEB76CC30 /* AppLockUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockUITests.swift; sourceTree = "<group>"; };
|
||||||
F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedBodyText.swift; sourceTree = "<group>"; };
|
F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedBodyText.swift; sourceTree = "<group>"; };
|
||||||
F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreen.swift; sourceTree = "<group>"; };
|
F7478623CECC9438014244BA /* ServerConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreen.swift; sourceTree = "<group>"; };
|
||||||
F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilder.swift; sourceTree = "<group>"; };
|
|
||||||
F7E8A8047B50E3607ACD354E /* ImageProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageProviderProtocol.swift; sourceTree = "<group>"; };
|
F7E8A8047B50E3607ACD354E /* ImageProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageProviderProtocol.swift; sourceTree = "<group>"; };
|
||||||
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = "<group>"; };
|
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = "<group>"; };
|
||||||
F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionScreenTests.swift; sourceTree = "<group>"; };
|
F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionScreenTests.swift; sourceTree = "<group>"; };
|
||||||
@@ -2129,6 +2125,7 @@
|
|||||||
F9E543072DE58E751F028998 /* TimelineProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxy.swift; sourceTree = "<group>"; };
|
F9E543072DE58E751F028998 /* TimelineProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxy.swift; sourceTree = "<group>"; };
|
||||||
F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = "<group>"; };
|
F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
F9ED8E731E21055F728E5FED /* TimelineStartRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStartRoomTimelineView.swift; sourceTree = "<group>"; };
|
F9ED8E731E21055F728E5FED /* TimelineStartRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStartRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
|
FA3EB5B1848CF4F64E63C6B7 /* PermalinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkTests.swift; sourceTree = "<group>"; };
|
||||||
FA7BB497B2F539C17E88F6B7 /* NotificationSettingsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
FA7BB497B2F539C17E88F6B7 /* NotificationSettingsEditScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsEditScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomScreen.swift; sourceTree = "<group>"; };
|
FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomScreen.swift; sourceTree = "<group>"; };
|
||||||
FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenViewModel.swift; sourceTree = "<group>"; };
|
FB7BAD55A4E2B8E5828CD64C /* SoftLogoutScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
@@ -3586,7 +3583,7 @@
|
|||||||
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */,
|
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */,
|
||||||
8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */,
|
8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */,
|
||||||
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */,
|
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */,
|
||||||
6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */,
|
FA3EB5B1848CF4F64E63C6B7 /* PermalinkTests.swift */,
|
||||||
31A6314FDC51DA25712D9A81 /* PillContextTests.swift */,
|
31A6314FDC51DA25712D9A81 /* PillContextTests.swift */,
|
||||||
347D708104CCEF771428C9A3 /* PollFormScreenViewModelTests.swift */,
|
347D708104CCEF771428C9A3 /* PollFormScreenViewModelTests.swift */,
|
||||||
25E7E9B7FEAB6169D960C206 /* QRCodeLoginScreenViewModelTests.swift */,
|
25E7E9B7FEAB6169D960C206 /* QRCodeLoginScreenViewModelTests.swift */,
|
||||||
@@ -4581,7 +4578,6 @@
|
|||||||
6A580295A56B55A856CC4084 /* InfoPlistReader.swift */,
|
6A580295A56B55A856CC4084 /* InfoPlistReader.swift */,
|
||||||
6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */,
|
6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */,
|
||||||
10B7F8EE25775DE2A305CBB5 /* NotificationCenterProtocol.swift */,
|
10B7F8EE25775DE2A305CBB5 /* NotificationCenterProtocol.swift */,
|
||||||
F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */,
|
|
||||||
B3A1398EFF65090FDA1CB639 /* ProcessInfo.swift */,
|
B3A1398EFF65090FDA1CB639 /* ProcessInfo.swift */,
|
||||||
53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */,
|
53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */,
|
||||||
4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */,
|
4481799F455B3DA243BDA2AC /* ShareToMapsAppActivity.swift */,
|
||||||
@@ -5691,7 +5687,6 @@
|
|||||||
5D70FAE4D2BF4553AFFFFE41 /* NotificationItemProxy.swift in Sources */,
|
5D70FAE4D2BF4553AFFFFE41 /* NotificationItemProxy.swift in Sources */,
|
||||||
B89990DD875B0B603D4D4332 /* NotificationItemProxyProtocol.swift in Sources */,
|
B89990DD875B0B603D4D4332 /* NotificationItemProxyProtocol.swift in Sources */,
|
||||||
B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */,
|
B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */,
|
||||||
234E2C782981003971ABE96E /* PermalinkBuilder.swift in Sources */,
|
|
||||||
62418EA4E3EB597AD184AEB6 /* PillConstants.swift in Sources */,
|
62418EA4E3EB597AD184AEB6 /* PillConstants.swift in Sources */,
|
||||||
55CDD3968D95D1A820B5491E /* PlaceholderAvatarImage.swift in Sources */,
|
55CDD3968D95D1A820B5491E /* PlaceholderAvatarImage.swift in Sources */,
|
||||||
F12F6BED7B6D7EE4BEE55039 /* PlainMentionBuilder.swift in Sources */,
|
F12F6BED7B6D7EE4BEE55039 /* PlainMentionBuilder.swift in Sources */,
|
||||||
@@ -5782,7 +5777,7 @@
|
|||||||
C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */,
|
C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */,
|
||||||
E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */,
|
E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */,
|
||||||
50381244BA280451771BE3ED /* PINTextFieldTests.swift in Sources */,
|
50381244BA280451771BE3ED /* PINTextFieldTests.swift in Sources */,
|
||||||
27E9263DA75E266690A37EB1 /* PermalinkBuilderTests.swift in Sources */,
|
1583E2D766E4485FF91662FC /* PermalinkTests.swift in Sources */,
|
||||||
3982E60F9C126437D5E488A3 /* PillContextTests.swift in Sources */,
|
3982E60F9C126437D5E488A3 /* PillContextTests.swift in Sources */,
|
||||||
FF7E8ECC8E7E1D1851517536 /* PollFormScreenViewModelTests.swift in Sources */,
|
FF7E8ECC8E7E1D1851517536 /* PollFormScreenViewModelTests.swift in Sources */,
|
||||||
D415764645491F10344FC6AC /* Publisher.swift in Sources */,
|
D415764645491F10344FC6AC /* Publisher.swift in Sources */,
|
||||||
@@ -6237,7 +6232,6 @@
|
|||||||
847DE3A7EB9FCA2C429C6E85 /* PINTextField.swift in Sources */,
|
847DE3A7EB9FCA2C429C6E85 /* PINTextField.swift in Sources */,
|
||||||
7501442D52A65F73DF79FFD4 /* PaginationIndicatorRoomTimelineItem.swift in Sources */,
|
7501442D52A65F73DF79FFD4 /* PaginationIndicatorRoomTimelineItem.swift in Sources */,
|
||||||
764AFCC225B044CF5F9B41E5 /* PaginationIndicatorRoomTimelineView.swift in Sources */,
|
764AFCC225B044CF5F9B41E5 /* PaginationIndicatorRoomTimelineView.swift in Sources */,
|
||||||
80D00A7C62AAB44F54725C43 /* PermalinkBuilder.swift in Sources */,
|
|
||||||
962A4F8AD6312804E2C6BB6E /* PhotoLibraryPicker.swift in Sources */,
|
962A4F8AD6312804E2C6BB6E /* PhotoLibraryPicker.swift in Sources */,
|
||||||
EE4E2C1922BBF5169E213555 /* PillAttachmentViewProvider.swift in Sources */,
|
EE4E2C1922BBF5169E213555 /* PillAttachmentViewProvider.swift in Sources */,
|
||||||
899359A4D1147601F6C4E364 /* PillConstants.swift in Sources */,
|
899359A4D1147601F6C4E364 /* PillConstants.swift in Sources */,
|
||||||
|
|||||||
@@ -289,8 +289,6 @@ final class AppSettings {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// MARK: - Shared
|
// MARK: - Shared
|
||||||
|
|
||||||
let permalinkBaseURL: URL = "https://matrix.to"
|
|
||||||
|
|
||||||
@UserPreference(key: UserDefaultsKeys.logLevel, defaultValue: TracingConfiguration.LogLevel.info, storageType: .userDefaults(store))
|
@UserPreference(key: UserDefaultsKeys.logLevel, defaultValue: TracingConfiguration.LogLevel.info, storageType: .userDefaults(store))
|
||||||
var logLevel
|
var logLevel
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import MatrixRustSDK
|
||||||
|
|
||||||
enum AppRoute: Equatable {
|
enum AppRoute: Equatable {
|
||||||
/// The callback used to complete login with OIDC.
|
/// The callback used to complete login with OIDC.
|
||||||
@@ -43,7 +44,7 @@ struct AppRouteURLParser {
|
|||||||
|
|
||||||
init(appSettings: AppSettings) {
|
init(appSettings: AppSettings) {
|
||||||
urlParsers = [
|
urlParsers = [
|
||||||
MatrixPermalinkParser(appSettings: appSettings),
|
MatrixPermalinkParser(),
|
||||||
OIDCCallbackURLParser(appSettings: appSettings),
|
OIDCCallbackURLParser(appSettings: appSettings),
|
||||||
ElementCallURLParser()
|
ElementCallURLParser()
|
||||||
]
|
]
|
||||||
@@ -121,13 +122,15 @@ struct ElementCallURLParser: URLParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct MatrixPermalinkParser: URLParser {
|
struct MatrixPermalinkParser: URLParser {
|
||||||
let appSettings: AppSettings
|
|
||||||
|
|
||||||
func route(from url: URL) -> AppRoute? {
|
func route(from url: URL) -> AppRoute? {
|
||||||
switch PermalinkBuilder.detectPermalink(in: url, baseURL: appSettings.permalinkBaseURL) {
|
guard let matrixEntity = parseMatrixEntityFrom(uri: url.absoluteString) else {
|
||||||
case .userIdentifier(let userID):
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch matrixEntity.id {
|
||||||
|
case .user(let userID):
|
||||||
return .roomMemberDetails(userID: userID)
|
return .roomMemberDetails(userID: userID)
|
||||||
case .roomIdentifier(let roomID):
|
case .room(let roomID):
|
||||||
return .room(roomID: roomID)
|
return .room(roomID: roomID)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -421,8 +421,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
let userID = userSession.clientProxy.userID
|
let userID = userSession.clientProxy.userID
|
||||||
|
|
||||||
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: appSettings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||||
mentionBuilder: MentionBuilder()),
|
|
||||||
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
|
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
|
||||||
|
|
||||||
let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy,
|
let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy,
|
||||||
@@ -509,8 +508,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
analyticsService: analytics,
|
analyticsService: analytics,
|
||||||
userIndicatorController: userIndicatorController,
|
userIndicatorController: userIndicatorController,
|
||||||
notificationSettings: userSession.clientProxy.notificationSettings,
|
notificationSettings: userSession.clientProxy.notificationSettings,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: appSettings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
let coordinator = RoomDetailsScreenCoordinator(parameters: params)
|
let coordinator = RoomDetailsScreenCoordinator(parameters: params)
|
||||||
coordinator.actions.sink { [weak self] action in
|
coordinator.actions.sink { [weak self] action in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
@@ -846,8 +844,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
let userID = userSession.clientProxy.userID
|
let userID = userSession.clientProxy.userID
|
||||||
|
|
||||||
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: appSettings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||||
mentionBuilder: MentionBuilder()),
|
|
||||||
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
|
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
|
||||||
|
|
||||||
let roomTimelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy,
|
let roomTimelineController = roomTimelineControllerFactory.buildRoomTimelineController(roomProxy: roomProxy,
|
||||||
|
|||||||
@@ -326,8 +326,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
|
|
||||||
private func presentHomeScreen() {
|
private func presentHomeScreen() {
|
||||||
let parameters = HomeScreenCoordinatorParameters(userSession: userSession,
|
let parameters = HomeScreenCoordinatorParameters(userSession: userSession,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||||
mentionBuilder: MentionBuilder()),
|
|
||||||
bugReportService: bugReportService,
|
bugReportService: bugReportService,
|
||||||
navigationStackCoordinator: detailNavigationStackCoordinator,
|
navigationStackCoordinator: detailNavigationStackCoordinator,
|
||||||
selectedRoomPublisher: selectedRoomSubject.asCurrentValuePublisher())
|
selectedRoomPublisher: selectedRoomSubject.asCurrentValuePublisher())
|
||||||
|
|||||||
@@ -17,12 +17,12 @@
|
|||||||
import DTCoreText
|
import DTCoreText
|
||||||
import Foundation
|
import Foundation
|
||||||
import LRUCache
|
import LRUCache
|
||||||
|
import MatrixRustSDK
|
||||||
|
|
||||||
struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||||
private let cacheKey: String
|
private let cacheKey: String
|
||||||
private let temporaryBlockquoteMarkingColor = UIColor.magenta
|
private let temporaryBlockquoteMarkingColor = UIColor.magenta
|
||||||
private let temporaryCodeBlockMarkingColor = UIColor.cyan
|
private let temporaryCodeBlockMarkingColor = UIColor.cyan
|
||||||
private let permalinkBaseURL: URL
|
|
||||||
private let mentionBuilder: MentionBuilderProtocol
|
private let mentionBuilder: MentionBuilderProtocol
|
||||||
|
|
||||||
private static let defaultKey = "default"
|
private static let defaultKey = "default"
|
||||||
@@ -34,9 +34,8 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
|||||||
caches.removeAll()
|
caches.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
init(cacheKey: String = defaultKey, permalinkBaseURL: URL, mentionBuilder: MentionBuilderProtocol) {
|
init(cacheKey: String = defaultKey, mentionBuilder: MentionBuilderProtocol) {
|
||||||
self.cacheKey = cacheKey
|
self.cacheKey = cacheKey
|
||||||
self.permalinkBaseURL = permalinkBaseURL
|
|
||||||
self.mentionBuilder = mentionBuilder
|
self.mentionBuilder = mentionBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,29 +205,45 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
|||||||
private func addLinksAndMentions(_ attributedString: NSMutableAttributedString) {
|
private func addLinksAndMentions(_ attributedString: NSMutableAttributedString) {
|
||||||
let string = attributedString.string
|
let string = attributedString.string
|
||||||
|
|
||||||
var matches = MatrixEntityRegex.userIdentifierRegex.matches(in: string, options: []).map { TypedMatch(match: $0, type: .permalink(type: .userID)) }
|
// Event identifiers and room aliases and identifiers detected in plain text are techincally incomplete
|
||||||
matches.append(contentsOf: MatrixEntityRegex.roomIdentifierRegex.matches(in: string, options: []).map { TypedMatch(match: $0, type: .permalink(type: .roomID)) })
|
// without via parameters and we won't bother detecting them
|
||||||
|
|
||||||
// As of right now we do not handle event id links in any way so there is no need to add them as links
|
var matches: [TextParsingMatch] = MatrixEntityRegex.userIdentifierRegex.matches(in: string, options: []).compactMap { match in
|
||||||
// matches.append(contentsOf: MatrixEntityRegex.eventIdentifierRegex.matches(in: string, options: []))
|
guard let matchRange = Range(match.range, in: string) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let identifier = String(string[matchRange])
|
||||||
|
|
||||||
|
return TextParsingMatch(type: .userID(identifier: identifier), range: match.range)
|
||||||
|
}
|
||||||
|
|
||||||
matches.append(contentsOf: MatrixEntityRegex.roomAliasRegex.matches(in: string, options: []).map { TypedMatch(match: $0, type: .permalink(type: .roomAlias)) })
|
matches.append(contentsOf: MatrixEntityRegex.linkRegex.matches(in: string, options: []).compactMap { match in
|
||||||
|
guard let matchRange = Range(match.range, in: string) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var link = String(string[matchRange])
|
||||||
|
|
||||||
|
if !link.contains("://") {
|
||||||
|
link.insert(contentsOf: "https://", at: link.startIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextParsingMatch(type: .link(urlString: link), range: match.range)
|
||||||
|
})
|
||||||
|
|
||||||
matches.append(contentsOf: MatrixEntityRegex.linkRegex.matches(in: string, options: []).map { TypedMatch(match: $0, type: .link) })
|
matches.append(contentsOf: MatrixEntityRegex.allUsersRegex.matches(in: attributedString.string, options: []).map { match in
|
||||||
|
TextParsingMatch(type: .atRoom, range: match.range)
|
||||||
matches.append(contentsOf: MatrixEntityRegex.allUsersRegex.matches(in: attributedString.string, options: []).map { TypedMatch(match: $0, type: .atRoom) })
|
})
|
||||||
|
|
||||||
guard matches.count > 0 else {
|
guard matches.count > 0 else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the links by length so the longest one always takes priority
|
// Sort the links by length so the longest one always takes priority
|
||||||
matches.sorted { $0.match.range.length > $1.match.range.length }.forEach { [attributedString] typedMatch in
|
matches.sorted { $0.range.length > $1.range.length }.forEach { [attributedString] match in
|
||||||
guard let matchRange = Range(typedMatch.match.range, in: string) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasLink = false
|
var hasLink = false
|
||||||
attributedString.enumerateAttribute(.link, in: typedMatch.match.range, options: []) { value, _, stop in
|
attributedString.enumerateAttribute(.link, in: match.range, options: []) { value, _, stop in
|
||||||
if value != nil {
|
if value != nil {
|
||||||
hasLink = true
|
hasLink = true
|
||||||
stop.pointee = true
|
stop.pointee = true
|
||||||
@@ -239,24 +254,12 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch typedMatch.type {
|
switch match.type {
|
||||||
case .atRoom:
|
case .atRoom:
|
||||||
attributedString.addAttribute(.MatrixAllUsersMention, value: true, range: typedMatch.match.range)
|
attributedString.addAttribute(.MatrixAllUsersMention, value: true, range: match.range)
|
||||||
case let .permalink(type):
|
case .userID, .link:
|
||||||
let identifier = String(string[matchRange])
|
if let url = match.link {
|
||||||
|
attributedString.addAttribute(.link, value: url, range: match.range)
|
||||||
if let url = type.getPermalinkFrom(identifier: identifier, baseURL: permalinkBaseURL) {
|
|
||||||
attributedString.addAttribute(.link, value: url, range: typedMatch.match.range)
|
|
||||||
}
|
|
||||||
case .link:
|
|
||||||
var link = String(string[matchRange])
|
|
||||||
|
|
||||||
if !link.contains("://") {
|
|
||||||
link.insert(contentsOf: "https://", at: link.startIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let url = URL(string: link) {
|
|
||||||
attributedString.addAttribute(.link, value: url, range: typedMatch.match.range)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,18 +268,18 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
|||||||
func detectPermalinks(_ attributedString: NSMutableAttributedString) {
|
func detectPermalinks(_ attributedString: NSMutableAttributedString) {
|
||||||
attributedString.enumerateAttribute(.link, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in
|
attributedString.enumerateAttribute(.link, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in
|
||||||
if value != nil {
|
if value != nil {
|
||||||
if let url = value as? URL {
|
if let url = value as? URL, let matrixEntity = parseMatrixEntityFrom(uri: url.absoluteString) {
|
||||||
switch PermalinkBuilder.detectPermalink(in: url, baseURL: permalinkBaseURL) {
|
switch matrixEntity.id {
|
||||||
case .userIdentifier(let identifier):
|
case .user(let userID):
|
||||||
mentionBuilder.handleUserMention(for: attributedString, in: range, url: url, userID: identifier)
|
mentionBuilder.handleUserMention(for: attributedString, in: range, url: url, userID: userID)
|
||||||
case .roomIdentifier(let identifier):
|
case .room(let roomID):
|
||||||
attributedString.addAttributes([.MatrixRoomID: identifier], range: range)
|
attributedString.addAttributes([.MatrixRoomID: roomID], range: range)
|
||||||
case .roomAlias(let alias):
|
case .roomAlias(let alias):
|
||||||
attributedString.addAttributes([.MatrixRoomAlias: alias], range: range)
|
attributedString.addAttributes([.MatrixRoomAlias: alias], range: range)
|
||||||
case .event(let roomIdentifier, let eventIdentifier):
|
case .eventOnRoomId(let roomID, let eventID):
|
||||||
attributedString.addAttributes([.MatrixEventID: EventIDAttributeValue(roomID: roomIdentifier, eventID: eventIdentifier)], range: range)
|
attributedString.addAttributes([.MatrixEventOnRoomID: EventOnRoomIDAttribute.Value(roomID: roomID, eventID: eventID)], range: range)
|
||||||
case .none:
|
case .eventOnRoomAlias(let alias, let eventID):
|
||||||
break
|
attributedString.addAttributes([.MatrixEventOnRoomAlias: EventOnRoomAliasAttribute.Value(alias: alias, eventID: eventID)], range: range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,7 +350,8 @@ extension NSAttributedString.Key {
|
|||||||
static let MatrixUserID: NSAttributedString.Key = .init(rawValue: UserIDAttribute.name)
|
static let MatrixUserID: NSAttributedString.Key = .init(rawValue: UserIDAttribute.name)
|
||||||
static let MatrixRoomID: NSAttributedString.Key = .init(rawValue: RoomIDAttribute.name)
|
static let MatrixRoomID: NSAttributedString.Key = .init(rawValue: RoomIDAttribute.name)
|
||||||
static let MatrixRoomAlias: NSAttributedString.Key = .init(rawValue: RoomAliasAttribute.name)
|
static let MatrixRoomAlias: NSAttributedString.Key = .init(rawValue: RoomAliasAttribute.name)
|
||||||
static let MatrixEventID: NSAttributedString.Key = .init(rawValue: EventIDAttribute.name)
|
static let MatrixEventOnRoomID: NSAttributedString.Key = .init(rawValue: EventOnRoomIDAttribute.name)
|
||||||
|
static let MatrixEventOnRoomAlias: NSAttributedString.Key = .init(rawValue: EventOnRoomAliasAttribute.name)
|
||||||
static let MatrixAllUsersMention: NSAttributedString.Key = .init(rawValue: AllUsersMentionAttribute.name)
|
static let MatrixAllUsersMention: NSAttributedString.Key = .init(rawValue: AllUsersMentionAttribute.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,30 +360,24 @@ protocol MentionBuilderProtocol {
|
|||||||
func handleAllUsersMention(for attributedString: NSMutableAttributedString, in range: NSRange)
|
func handleAllUsersMention(for attributedString: NSMutableAttributedString, in range: NSRange)
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct TypedMatch {
|
private struct TextParsingMatch {
|
||||||
enum MatchType {
|
enum MatchType {
|
||||||
case permalink(type: MentionType)
|
case userID(identifier: String)
|
||||||
case link
|
case link(urlString: String)
|
||||||
case atRoom
|
case atRoom
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MentionType {
|
let type: MatchType
|
||||||
case roomAlias
|
let range: NSRange
|
||||||
case roomID
|
|
||||||
case userID
|
var link: URL? {
|
||||||
|
switch type {
|
||||||
func getPermalinkFrom(identifier: String, baseURL: URL) -> URL? {
|
case .userID(let identifier):
|
||||||
switch self {
|
return try? URL(string: matrixToUserPermalink(userId: identifier))
|
||||||
case .roomAlias:
|
case .link(let urlString):
|
||||||
return try? PermalinkBuilder.permalinkTo(roomAlias: identifier, baseURL: baseURL)
|
return URL(string: urlString)
|
||||||
case .roomID:
|
default:
|
||||||
return try? PermalinkBuilder.permalinkTo(roomIdentifier: identifier, baseURL: baseURL)
|
return nil
|
||||||
case .userID:
|
|
||||||
return try? PermalinkBuilder.permalinkTo(userIdentifier: identifier, baseURL: baseURL)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let match: NSTextCheckingResult
|
|
||||||
let type: MatchType
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,21 +36,29 @@ enum RoomAliasAttribute: AttributedStringKey {
|
|||||||
static var name = "MXRoomAliasAttribute"
|
static var name = "MXRoomAliasAttribute"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EventOnRoomIDAttribute: AttributedStringKey {
|
||||||
|
struct Value: Hashable {
|
||||||
|
let roomID: String
|
||||||
|
let eventID: String
|
||||||
|
}
|
||||||
|
|
||||||
|
static var name = "MXEventOnRoomIDAttribute"
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EventOnRoomAliasAttribute: AttributedStringKey {
|
||||||
|
struct Value: Hashable {
|
||||||
|
let alias: String
|
||||||
|
let eventID: String
|
||||||
|
}
|
||||||
|
|
||||||
|
static var name = "MXEventOnRoomAliasAttribute"
|
||||||
|
}
|
||||||
|
|
||||||
enum AllUsersMentionAttribute: AttributedStringKey {
|
enum AllUsersMentionAttribute: AttributedStringKey {
|
||||||
typealias Value = Bool
|
typealias Value = Bool
|
||||||
static var name = "MXAllUsersMentionAttribute"
|
static var name = "MXAllUsersMentionAttribute"
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EventIDAttributeValue: Hashable {
|
|
||||||
let roomID: String
|
|
||||||
let eventID: String
|
|
||||||
}
|
|
||||||
|
|
||||||
enum EventIDAttribute: AttributedStringKey {
|
|
||||||
typealias Value = EventIDAttributeValue
|
|
||||||
static var name = "MXEventIDAttribute"
|
|
||||||
}
|
|
||||||
|
|
||||||
// periphery: ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
|
// periphery: ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
|
||||||
extension AttributeScopes {
|
extension AttributeScopes {
|
||||||
struct ElementXAttributes: AttributeScope {
|
struct ElementXAttributes: AttributeScope {
|
||||||
@@ -59,7 +67,8 @@ extension AttributeScopes {
|
|||||||
let userID: UserIDAttribute
|
let userID: UserIDAttribute
|
||||||
let roomID: RoomIDAttribute
|
let roomID: RoomIDAttribute
|
||||||
let roomAlias: RoomAliasAttribute
|
let roomAlias: RoomAliasAttribute
|
||||||
let eventID: EventIDAttribute
|
let eventOnRoomID: EventOnRoomIDAttribute
|
||||||
|
let eventOnRoomAlias: EventOnRoomAliasAttribute
|
||||||
|
|
||||||
let allUsersMention: AllUsersMentionAttribute
|
let allUsersMention: AllUsersMentionAttribute
|
||||||
|
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2022 New Vector Ltd
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
enum PermalinkBuilderError: Error {
|
|
||||||
case invalidUserIdentifier
|
|
||||||
case invalidRoomIdentifier
|
|
||||||
case invalidRoomAlias
|
|
||||||
case invalidEventIdentifier
|
|
||||||
case failedConstructingURL
|
|
||||||
case failedAddingPercentEncoding
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PermalinkType: Equatable {
|
|
||||||
case userIdentifier(String)
|
|
||||||
case roomIdentifier(String)
|
|
||||||
case roomAlias(String)
|
|
||||||
case event(roomIdentifier: String, eventIdentifier: String)
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PermalinkBuilder {
|
|
||||||
private static var uriComponentCharacterSet: CharacterSet = {
|
|
||||||
var charset = CharacterSet.alphanumerics
|
|
||||||
charset.insert(charactersIn: "-_.!~*'()")
|
|
||||||
return charset
|
|
||||||
}()
|
|
||||||
|
|
||||||
static func detectPermalink(in url: URL, baseURL: URL) -> PermalinkType? {
|
|
||||||
guard url.absoluteString.hasPrefix(baseURL.absoluteString) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
guard var fragment = urlComponents.fragment else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if fragment.hasPrefix("/") {
|
|
||||||
fragment = String(fragment.dropFirst(1))
|
|
||||||
}
|
|
||||||
|
|
||||||
if let userIdentifierRange = MatrixEntityRegex.userIdentifierRegex.firstMatch(in: fragment)?.range {
|
|
||||||
return .userIdentifier((fragment as NSString).substring(with: userIdentifierRange))
|
|
||||||
}
|
|
||||||
|
|
||||||
if let roomAliasRange = MatrixEntityRegex.roomAliasRegex.firstMatch(in: fragment)?.range {
|
|
||||||
return .roomAlias((fragment as NSString).substring(with: roomAliasRange))
|
|
||||||
}
|
|
||||||
|
|
||||||
if let roomIdentifierRange = MatrixEntityRegex.roomIdentifierRegex.firstMatch(in: fragment)?.range {
|
|
||||||
let roomIdentifier = (fragment as NSString).substring(with: roomIdentifierRange)
|
|
||||||
|
|
||||||
if let eventIdentifierRange = MatrixEntityRegex.eventIdentifierRegex.firstMatch(in: fragment)?.range {
|
|
||||||
let eventIdentifier = (fragment as NSString).substring(with: eventIdentifierRange)
|
|
||||||
return .event(roomIdentifier: roomIdentifier, eventIdentifier: eventIdentifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
return .roomIdentifier(roomIdentifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(*, deprecated, message: "Use a room's `matrixToPermalink` method instead")
|
|
||||||
static func permalinkTo(userIdentifier: String, baseURL: URL) throws -> URL {
|
|
||||||
guard MatrixEntityRegex.isMatrixUserIdentifier(userIdentifier) else {
|
|
||||||
throw PermalinkBuilderError.invalidUserIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
let urlString = "\(baseURL)/#/\(userIdentifier)"
|
|
||||||
|
|
||||||
guard let url = URL(string: urlString) else {
|
|
||||||
throw PermalinkBuilderError.failedConstructingURL
|
|
||||||
}
|
|
||||||
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(*, deprecated, message: "Use a room's `matrixToPermalink` method instead")
|
|
||||||
static func permalinkTo(roomIdentifier: String, baseURL: URL) throws -> URL {
|
|
||||||
guard MatrixEntityRegex.isMatrixRoomIdentifier(roomIdentifier) else {
|
|
||||||
throw PermalinkBuilderError.invalidRoomIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
return try permalinkTo(roomIdentifierOrAlias: roomIdentifier, baseURL: baseURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(*, deprecated, message: "Use a room's `matrixToPermalink` method instead")
|
|
||||||
static func permalinkTo(roomAlias: String, baseURL: URL) throws -> URL {
|
|
||||||
guard MatrixEntityRegex.isMatrixRoomAlias(roomAlias) else {
|
|
||||||
throw PermalinkBuilderError.invalidRoomAlias
|
|
||||||
}
|
|
||||||
|
|
||||||
return try permalinkTo(roomIdentifierOrAlias: roomAlias, baseURL: baseURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(*, deprecated, message: "Use a room's `matrixToEventPermalink` method instead")
|
|
||||||
static func permalinkTo(eventIdentifier: String, roomIdentifier: String, baseURL: URL) throws -> URL {
|
|
||||||
guard MatrixEntityRegex.isMatrixEventIdentifier(eventIdentifier) else {
|
|
||||||
throw PermalinkBuilderError.invalidEventIdentifier
|
|
||||||
}
|
|
||||||
guard MatrixEntityRegex.isMatrixRoomIdentifier(roomIdentifier) else {
|
|
||||||
throw PermalinkBuilderError.invalidRoomIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let roomId = roomIdentifier.addingPercentEncoding(withAllowedCharacters: uriComponentCharacterSet),
|
|
||||||
let eventId = eventIdentifier.addingPercentEncoding(withAllowedCharacters: uriComponentCharacterSet) else {
|
|
||||||
throw PermalinkBuilderError.failedAddingPercentEncoding
|
|
||||||
}
|
|
||||||
|
|
||||||
let urlString = "\(baseURL)/#/\(roomId)/\(eventId)"
|
|
||||||
|
|
||||||
guard let url = URL(string: urlString) else {
|
|
||||||
throw PermalinkBuilderError.failedConstructingURL
|
|
||||||
}
|
|
||||||
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Private
|
|
||||||
|
|
||||||
private static func permalinkTo(roomIdentifierOrAlias: String, baseURL: URL) throws -> URL {
|
|
||||||
guard let identifier = roomIdentifierOrAlias.addingPercentEncoding(withAllowedCharacters: uriComponentCharacterSet) else {
|
|
||||||
throw PermalinkBuilderError.failedAddingPercentEncoding
|
|
||||||
}
|
|
||||||
|
|
||||||
let urlString = "\(baseURL)/#/\(identifier)"
|
|
||||||
|
|
||||||
guard let url = URL(string: urlString) else {
|
|
||||||
throw PermalinkBuilderError.failedConstructingURL
|
|
||||||
}
|
|
||||||
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import MatrixRustSDK
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class MessageTextView: UITextView, PillAttachmentViewProviderDelegate {
|
final class MessageTextView: UITextView, PillAttachmentViewProviderDelegate {
|
||||||
@@ -129,8 +130,7 @@ struct MessageText: UIViewRepresentable {
|
|||||||
|
|
||||||
final class Coordinator: NSObject, UITextViewDelegate {
|
final class Coordinator: NSObject, UITextViewDelegate {
|
||||||
var openURLAction: OpenURLAction
|
var openURLAction: OpenURLAction
|
||||||
let permalinkBaseURL = ServiceLocator.shared.settings.permalinkBaseURL
|
|
||||||
|
|
||||||
init(openURLAction: OpenURLAction) {
|
init(openURLAction: OpenURLAction) {
|
||||||
self.openURLAction = openURLAction
|
self.openURLAction = openURLAction
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ struct MessageText: UIViewRepresentable {
|
|||||||
return false
|
return false
|
||||||
case .preview:
|
case .preview:
|
||||||
// We don't want to show a URL preview for permalinks
|
// We don't want to show a URL preview for permalinks
|
||||||
return PermalinkBuilder.detectPermalink(in: URL, baseURL: permalinkBaseURL) == nil
|
return parseMatrixEntityFrom(uri: URL.absoluteString) == nil
|
||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ struct MessageText: UIViewRepresentable {
|
|||||||
switch textItem.content {
|
switch textItem.content {
|
||||||
case let .link(url):
|
case let .link(url):
|
||||||
// We don't want to show a URL preview for permalinks
|
// We don't want to show a URL preview for permalinks
|
||||||
let isPermalink = PermalinkBuilder.detectPermalink(in: url, baseURL: permalinkBaseURL) != nil
|
let isPermalink = parseMatrixEntityFrom(uri: url.absoluteString) != nil
|
||||||
return .init(preview: isPermalink ? nil : .default, menu: defaultMenu)
|
return .init(preview: isPermalink ? nil : .default, menu: defaultMenu)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
@@ -197,7 +197,7 @@ struct MessageText_Previews: PreviewProvider, TestablePreview {
|
|||||||
|
|
||||||
private static let htmlStringWithList = "<p>This is a list</p>\n<ul>\n<li>One</li>\n<li>Two</li>\n<li>And number 3</li>\n</ul>\n"
|
private static let htmlStringWithList = "<p>This is a list</p>\n<ul>\n<li>One</li>\n<li>Two</li>\n<li>And number 3</li>\n</ul>\n"
|
||||||
|
|
||||||
private static let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
private static let attributedStringBuilder = AttributedStringBuilder(mentionBuilder: MentionBuilder())
|
||||||
|
|
||||||
static var attachmentPreview: some View {
|
static var attachmentPreview: some View {
|
||||||
MessageText(attributedString: attributedStringWithAttachment)
|
MessageText(attributedString: attributedStringWithAttachment)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import MatrixRustSDK
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct MatrixUserShareLink<Label: View>: View {
|
struct MatrixUserShareLink<Label: View>: View {
|
||||||
@@ -22,8 +23,7 @@ struct MatrixUserShareLink<Label: View>: View {
|
|||||||
|
|
||||||
init(userID: String, @ViewBuilder label: () -> Label) {
|
init(userID: String, @ViewBuilder label: () -> Label) {
|
||||||
self.label = label()
|
self.label = label()
|
||||||
permalink = try? PermalinkBuilder.permalinkTo(userIdentifier: userID,
|
permalink = try? URL(string: matrixToUserPermalink(userId: userID))
|
||||||
baseURL: ServiceLocator.shared.settings.permalinkBaseURL)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
import Combine
|
import Combine
|
||||||
import Foundation
|
import Foundation
|
||||||
import GameKit
|
import GameKit
|
||||||
|
import MatrixRustSDK
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import WysiwygComposer
|
import WysiwygComposer
|
||||||
|
|
||||||
@@ -210,7 +211,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
|||||||
private func setupMentionsHandling(mentionDisplayHelper: MentionDisplayHelper) {
|
private func setupMentionsHandling(mentionDisplayHelper: MentionDisplayHelper) {
|
||||||
wysiwygViewModel.mentionDisplayHelper = mentionDisplayHelper
|
wysiwygViewModel.mentionDisplayHelper = mentionDisplayHelper
|
||||||
|
|
||||||
let attributedStringBuilder = AttributedStringBuilder(cacheKey: "Composer", permalinkBaseURL: appSettings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
let attributedStringBuilder = AttributedStringBuilder(cacheKey: "Composer", mentionBuilder: MentionBuilder())
|
||||||
|
|
||||||
wysiwygViewModel.mentionReplacer = ComposerMentionReplacer { urlString, string in
|
wysiwygViewModel.mentionReplacer = ComposerMentionReplacer { urlString, string in
|
||||||
let attributedString: NSMutableAttributedString
|
let attributedString: NSMutableAttributedString
|
||||||
@@ -231,7 +232,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
|||||||
private func handleSuggestion(_ suggestion: SuggestionItem) {
|
private func handleSuggestion(_ suggestion: SuggestionItem) {
|
||||||
switch suggestion {
|
switch suggestion {
|
||||||
case let .user(item):
|
case let .user(item):
|
||||||
guard let url = try? PermalinkBuilder.permalinkTo(userIdentifier: item.id, baseURL: appSettings.permalinkBaseURL) else {
|
guard let url = try? URL(string: matrixToUserPermalink(userId: item.id)) else {
|
||||||
MXLog.error("Could not build user permalink")
|
MXLog.error("Could not build user permalink")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -319,8 +319,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: notificationSettingsProxy,
|
notificationSettingsProxy: notificationSettingsProxy,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: .userDirectory,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static let dmRoomViewModel = {
|
static let dmRoomViewModel = {
|
||||||
@@ -345,8 +344,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: notificationSettingsProxy,
|
notificationSettingsProxy: notificationSettingsProxy,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: .userDirectory,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static let simpleRoomViewModel = {
|
static let simpleRoomViewModel = {
|
||||||
@@ -370,8 +368,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: notificationSettingsProxy,
|
notificationSettingsProxy: notificationSettingsProxy,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: .userDirectory,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ struct FormattedBodyText_Previews: PreviewProvider, TestablePreview {
|
|||||||
"<p>test</p>\n<p>test</p>"
|
"<p>test</p>\n<p>test</p>"
|
||||||
]
|
]
|
||||||
|
|
||||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
let attributedStringBuilder = AttributedStringBuilder(mentionBuilder: MentionBuilder())
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading, spacing: 24.0) {
|
VStack(alignment: .leading, spacing: 24.0) {
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ struct TextRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static func itemWith(html: String, timestamp: String, isOutgoing: Bool, senderId: String) -> TextRoomTimelineItem {
|
private static func itemWith(html: String, timestamp: String, isOutgoing: Bool, senderId: String) -> TextRoomTimelineItem {
|
||||||
let builder = AttributedStringBuilder(cacheKey: "preview", permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
let builder = AttributedStringBuilder(cacheKey: "preview", mentionBuilder: MentionBuilder())
|
||||||
let attributedString = builder.fromHTML(html)
|
let attributedString = builder.fromHTML(html)
|
||||||
|
|
||||||
return TextRoomTimelineItem(id: .random,
|
return TextRoomTimelineItem(id: .random,
|
||||||
|
|||||||
@@ -681,7 +681,6 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
let roomListService = syncService.roomListService()
|
let roomListService = syncService.roomListService()
|
||||||
|
|
||||||
let roomMessageEventStringBuilder = RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(cacheKey: "roomList",
|
let roomMessageEventStringBuilder = RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(cacheKey: "roomList",
|
||||||
permalinkBaseURL: appSettings.permalinkBaseURL,
|
|
||||||
mentionBuilder: PlainMentionBuilder()))
|
mentionBuilder: PlainMentionBuilder()))
|
||||||
let eventStringBuilder = RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID),
|
let eventStringBuilder = RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID),
|
||||||
messageEventStringBuilder: roomMessageEventStringBuilder)
|
messageEventStringBuilder: roomMessageEventStringBuilder)
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ extension RoomMemberProxyProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var permalink: URL? {
|
var permalink: URL? {
|
||||||
try? PermalinkBuilder.permalinkTo(userIdentifier: userID,
|
try? URL(string: matrixToUserPermalink(userId: userID))
|
||||||
baseURL: ServiceLocator.shared.settings.permalinkBaseURL)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name used for sorting the member alphabetically. This will be the displayname if,
|
/// The name used for sorting the member alphabetically. This will be the displayname if,
|
||||||
|
|||||||
@@ -97,8 +97,7 @@ enum RoomTimelineItemFixtures {
|
|||||||
isThreaded: false,
|
isThreaded: false,
|
||||||
sender: .init(id: "", displayName: "Helena"),
|
sender: .init(id: "", displayName: "Helena"),
|
||||||
content: .init(body: "",
|
content: .init(body: "",
|
||||||
formattedBody: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
formattedBody: AttributedStringBuilder(mentionBuilder: MentionBuilder())
|
||||||
mentionBuilder: MentionBuilder())
|
|
||||||
.fromHTML("Hol' up <blockquote>New home office set up!</blockquote>That's amazing! Congrats 🥳")))
|
.fromHTML("Hol' up <blockquote>New home office set up!</blockquote>That's amazing! Congrats 🥳")))
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ import UserNotifications
|
|||||||
// database, logging, etc. are only ever setup once per *process*
|
// database, logging, etc. are only ever setup once per *process*
|
||||||
|
|
||||||
private let settings: NSESettingsProtocol = AppSettings()
|
private let settings: NSESettingsProtocol = AppSettings()
|
||||||
private let notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: settings.permalinkBaseURL,
|
private let notificationContentBuilder = NotificationContentBuilder(messageEventStringBuilder: RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(mentionBuilder: PlainMentionBuilder())))
|
||||||
mentionBuilder: PlainMentionBuilder())))
|
|
||||||
private let keychainController = KeychainController(service: .sessions,
|
private let keychainController = KeychainController(service: .sessions,
|
||||||
accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier)
|
accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier)
|
||||||
private var userSessions = [String: NSEUserSession]()
|
private var userSessions = [String: NSEUserSession]()
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
protocol NSESettingsProtocol {
|
protocol NSESettingsProtocol {
|
||||||
var permalinkBaseURL: URL { get }
|
|
||||||
|
|
||||||
var logLevel: TracingConfiguration.LogLevel { get }
|
var logLevel: TracingConfiguration.LogLevel { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ targets:
|
|||||||
- path: ../../ElementX/Sources/Other/InfoPlistReader.swift
|
- path: ../../ElementX/Sources/Other/InfoPlistReader.swift
|
||||||
- path: ../../ElementX/Sources/Other/Logging
|
- path: ../../ElementX/Sources/Other/Logging
|
||||||
- path: ../../ElementX/Sources/Other/MatrixEntityRegex.swift
|
- path: ../../ElementX/Sources/Other/MatrixEntityRegex.swift
|
||||||
- path: ../../ElementX/Sources/Other/PermalinkBuilder.swift
|
|
||||||
- path: ../../ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift
|
- path: ../../ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift
|
||||||
- path: ../../ElementX/Sources/Other/UserAgentBuilder.swift
|
- path: ../../ElementX/Sources/Other/UserAgentBuilder.swift
|
||||||
- path: ../../ElementX/Sources/Other/UserPreference.swift
|
- path: ../../ElementX/Sources/Other/UserPreference.swift
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class AppRouteURLParserTests: XCTestCase {
|
|||||||
|
|
||||||
func testMatrixUserURL() {
|
func testMatrixUserURL() {
|
||||||
let userID = "@test:matrix.org"
|
let userID = "@test:matrix.org"
|
||||||
guard let url = URL(string: "\(appSettings.permalinkBaseURL)/#/\(userID)") else {
|
guard let url = URL(string: "https://matrix.to/#/\(userID)") else {
|
||||||
XCTFail("Invalid url")
|
XCTFail("Invalid url")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ class AppRouteURLParserTests: XCTestCase {
|
|||||||
|
|
||||||
func testMatrixRoomIdentifierURL() {
|
func testMatrixRoomIdentifierURL() {
|
||||||
let id = "!abcdefghijklmnopqrstuvwxyz1234567890:matrix.org"
|
let id = "!abcdefghijklmnopqrstuvwxyz1234567890:matrix.org"
|
||||||
guard let url = URL(string: "\(appSettings.permalinkBaseURL)/#/\(id)") else {
|
guard let url = URL(string: "https://matrix.to/#/\(id)") else {
|
||||||
XCTFail("Invalid url")
|
XCTFail("Invalid url")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
class AttributedStringBuilderTests: XCTestCase {
|
class AttributedStringBuilderTests: XCTestCase {
|
||||||
private let permalinkBaseURL = ServiceLocator.shared.settings.permalinkBaseURL
|
private lazy var attributedStringBuilder = AttributedStringBuilder(mentionBuilder: MentionBuilder())
|
||||||
private lazy var attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: permalinkBaseURL, mentionBuilder: MentionBuilder())
|
|
||||||
private let maxHeaderPointSize = ceil(UIFont.preferredFont(forTextStyle: .body).pointSize * 1.2)
|
private let maxHeaderPointSize = ceil(UIFont.preferredFont(forTextStyle: .body).pointSize * 1.2)
|
||||||
|
|
||||||
func testRenderHTMLStringWithHeaders() {
|
func testRenderHTMLStringWithHeaders() {
|
||||||
@@ -192,35 +191,11 @@ class AttributedStringBuilderTests: XCTestCase {
|
|||||||
func testUserIdLink() {
|
func testUserIdLink() {
|
||||||
let userId = "@user:matrix.org"
|
let userId = "@user:matrix.org"
|
||||||
let string = "The user is \(userId)."
|
let string = "The user is \(userId)."
|
||||||
let expectedLink = "\(permalinkBaseURL)/#/\(userId)"
|
let expectedLink = "https://matrix.to/#/\(userId)"
|
||||||
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: expectedLink, expectedRuns: 3)
|
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: expectedLink, expectedRuns: 3)
|
||||||
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: expectedLink, expectedRuns: 3)
|
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: expectedLink, expectedRuns: 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRoomAliasLink() {
|
|
||||||
let roomAlias = "#matrix:matrix.org"
|
|
||||||
let string = "The room alias is \(roomAlias)."
|
|
||||||
let expectedLink = "https://matrix.to/#/%23matrix%3Amatrix.org"
|
|
||||||
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: expectedLink, expectedRuns: 3)
|
|
||||||
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: expectedLink, expectedRuns: 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testRoomIdLink() {
|
|
||||||
let roomId = "!roomidentifier:matrix.org"
|
|
||||||
let string = "The room is \(roomId)."
|
|
||||||
let expectedLink = "https://matrix.to/#/!roomidentifier%3Amatrix.org"
|
|
||||||
checkLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expectedLink: expectedLink, expectedRuns: 3)
|
|
||||||
checkLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expectedLink: expectedLink, expectedRuns: 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// As of right now we do not handle event id links in any way so there is no need to add them as links
|
|
||||||
// func testEventIdLink() {
|
|
||||||
// let eventId = "$eventidentifier"
|
|
||||||
// let string = "The event is \(eventId)."
|
|
||||||
// checkMatrixEntityLinkIn(attributedString: attributedStringBuilder.fromHTML(string), expected: eventId)
|
|
||||||
// checkMatrixEntityLinkIn(attributedString: attributedStringBuilder.fromPlain(string), expected: eventId)
|
|
||||||
// }
|
|
||||||
|
|
||||||
func testDefaultFont() {
|
func testDefaultFont() {
|
||||||
let htmlString = "<b>Test</b> <i>string</i>."
|
let htmlString = "<b>Test</b> <i>string</i>."
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class AttributedStringTests: XCTestCase {
|
|||||||
func testReplacingFontWithPresentationIntent() {
|
func testReplacingFontWithPresentationIntent() {
|
||||||
// Given a string parsed from HTML that contains specific fixed size fonts.
|
// Given a string parsed from HTML that contains specific fixed size fonts.
|
||||||
let boldString = "Bold"
|
let boldString = "Bold"
|
||||||
guard let originalString = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
guard let originalString = AttributedStringBuilder(mentionBuilder: MentionBuilder())
|
||||||
.fromHTML("Normal <b>\(boldString)</b> Normal.") else {
|
.fromHTML("Normal <b>\(boldString)</b> Normal.") else {
|
||||||
XCTFail("The attributed string should be built from the HTML.")
|
XCTFail("The attributed string should be built from the HTML.")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2022 New Vector Ltd
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
|
|
||||||
@testable import ElementX
|
|
||||||
import XCTest
|
|
||||||
|
|
||||||
class PermalinkBuilderTests: XCTestCase {
|
|
||||||
private var appSettings: AppSettings!
|
|
||||||
|
|
||||||
override func setUp() {
|
|
||||||
AppSettings.configureWithSuiteName("io.element.elementx.unitests")
|
|
||||||
AppSettings.resetAllSettings()
|
|
||||||
appSettings = AppSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
func testUserIdentifierPermalink() {
|
|
||||||
let userId = "@abcdefghijklmnopqrstuvwxyz1234567890._-=/:matrix.org"
|
|
||||||
|
|
||||||
do {
|
|
||||||
let permalink = try PermalinkBuilder.permalinkTo(userIdentifier: userId, baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTAssertEqual(permalink, URL(string: "\(appSettings.permalinkBaseURL)/#/\(userId)"))
|
|
||||||
} catch {
|
|
||||||
XCTFail("User identifier must be valid: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testInvalidUserIdentifier() {
|
|
||||||
do {
|
|
||||||
_ = try PermalinkBuilder.permalinkTo(userIdentifier: "This1sN0tV4lid!@#$%^&*()", baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTFail("A permalink should not be created.")
|
|
||||||
} catch {
|
|
||||||
XCTAssertEqual(error as? PermalinkBuilderError, PermalinkBuilderError.invalidUserIdentifier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testRoomIdentifierPermalink() throws {
|
|
||||||
let roomId = "!abcdefghijklmnopqrstuvwxyz1234567890:matrix.org"
|
|
||||||
|
|
||||||
do {
|
|
||||||
let permalink = try PermalinkBuilder.permalinkTo(roomIdentifier: roomId, baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTAssertEqual(permalink, URL(string: "\(appSettings.permalinkBaseURL)/#/!abcdefghijklmnopqrstuvwxyz1234567890%3Amatrix.org"))
|
|
||||||
} catch {
|
|
||||||
XCTFail("Room identifier must be valid: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testMautrixBridgePermalink() throws {
|
|
||||||
let roomId = "!mautrix-signal-v6:maunium.net"
|
|
||||||
|
|
||||||
do {
|
|
||||||
let permalink = try PermalinkBuilder.permalinkTo(roomIdentifier: roomId, baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTAssertEqual(permalink, URL(string: "\(appSettings.permalinkBaseURL)/#/!mautrix-signal-v6%3Amaunium.net"))
|
|
||||||
} catch {
|
|
||||||
XCTFail("Room identifier must be valid: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testInvalidRoomIdentifier() {
|
|
||||||
do {
|
|
||||||
_ = try PermalinkBuilder.permalinkTo(roomIdentifier: "This1sN0tV4lid!@#$%^&*()", baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTFail("A permalink should not be created.")
|
|
||||||
} catch {
|
|
||||||
XCTAssertEqual(error as? PermalinkBuilderError, PermalinkBuilderError.invalidRoomIdentifier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testRoomAliasPermalink() throws {
|
|
||||||
let roomAlias = "#abcdefghijklmnopqrstuvwxyz-_.1234567890:matrix.org"
|
|
||||||
|
|
||||||
do {
|
|
||||||
let permalink = try PermalinkBuilder.permalinkTo(roomAlias: roomAlias, baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTAssertEqual(permalink, URL(string: "\(appSettings.permalinkBaseURL)/#/%23abcdefghijklmnopqrstuvwxyz-_.1234567890%3Amatrix.org"))
|
|
||||||
} catch {
|
|
||||||
XCTFail("Room alias must be valid: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testInvalidRoomAlias() {
|
|
||||||
do {
|
|
||||||
_ = try PermalinkBuilder.permalinkTo(roomAlias: "This1sN0tV4lid!@#$%^&*()", baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTFail("A permalink should not be created.")
|
|
||||||
} catch {
|
|
||||||
XCTAssertEqual(error as? PermalinkBuilderError, PermalinkBuilderError.invalidRoomAlias)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testEventPermalink() throws {
|
|
||||||
let eventId = "$abcdefghijklmnopqrstuvwxyz1234567890"
|
|
||||||
let roomId = "!abcdefghijklmnopqrstuvwxyz1234567890:matrix.org"
|
|
||||||
|
|
||||||
do {
|
|
||||||
let permalink = try PermalinkBuilder.permalinkTo(eventIdentifier: eventId, roomIdentifier: roomId, baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTAssertEqual(permalink, URL(string: "\(appSettings.permalinkBaseURL)/#/!abcdefghijklmnopqrstuvwxyz1234567890%3Amatrix.org/%24abcdefghijklmnopqrstuvwxyz1234567890"))
|
|
||||||
} catch {
|
|
||||||
XCTFail("Room and event identifiers must be valid: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testInvalidEventIdentifier() {
|
|
||||||
do {
|
|
||||||
_ = try PermalinkBuilder.permalinkTo(eventIdentifier: "This1sN0tV4lid!@#$%^&*()", roomIdentifier: "", baseURL: appSettings.permalinkBaseURL)
|
|
||||||
XCTFail("A permalink should not be created.")
|
|
||||||
} catch {
|
|
||||||
XCTAssertEqual(error as? PermalinkBuilderError, PermalinkBuilderError.invalidEventIdentifier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testPermalinkDetection() {
|
|
||||||
var url: URL = "https://www.matrix.org"
|
|
||||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url, baseURL: appSettings.permalinkBaseURL), nil)
|
|
||||||
|
|
||||||
url = "https://matrix.to/#/@bob:matrix.org?via=matrix.org"
|
|
||||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url, baseURL: appSettings.permalinkBaseURL), PermalinkType.userIdentifier("@bob:matrix.org"))
|
|
||||||
|
|
||||||
url = "https://matrix.to/#/!roomidentifier:matrix.org?via=matrix.org"
|
|
||||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url, baseURL: appSettings.permalinkBaseURL), PermalinkType.roomIdentifier("!roomidentifier:matrix.org"))
|
|
||||||
|
|
||||||
url = "https://matrix.to/#/%23roomalias:matrix.org?via=matrix.org"
|
|
||||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url, baseURL: appSettings.permalinkBaseURL), PermalinkType.roomAlias("#roomalias:matrix.org"))
|
|
||||||
|
|
||||||
url = "https://matrix.to/#/!roomidentifier:matrix.org/$eventidentifier?via=matrix.org"
|
|
||||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url, baseURL: appSettings.permalinkBaseURL), PermalinkType.event(roomIdentifier: "!roomidentifier:matrix.org", eventIdentifier: "$eventidentifier"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2022 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
@testable import ElementX
|
||||||
|
import MatrixRustSDK
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
/// Just for API sanity checking, they're already properly tested in the SDK/Ruma
|
||||||
|
class PermalinkTests: XCTestCase {
|
||||||
|
func testUserIdentifierPermalink() {
|
||||||
|
let invalidUserId = "This1sN0tV4lid!@#$%^&*()"
|
||||||
|
XCTAssertNil(try? matrixToUserPermalink(userId: invalidUserId))
|
||||||
|
|
||||||
|
let validUserId = "@abcdefghijklmnopqrstuvwxyz1234567890._-=/:matrix.org"
|
||||||
|
XCTAssertEqual(try? matrixToUserPermalink(userId: validUserId), .some("https://matrix.to/#/@abcdefghijklmnopqrstuvwxyz1234567890._-=%2F:matrix.org"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPermalinkDetection() {
|
||||||
|
var url: URL = "https://www.matrix.org"
|
||||||
|
XCTAssertNil(parseMatrixEntityFrom(uri: url.absoluteString))
|
||||||
|
|
||||||
|
url = "https://matrix.to/#/@bob:matrix.org?via=matrix.org"
|
||||||
|
XCTAssertEqual(parseMatrixEntityFrom(uri: url.absoluteString),
|
||||||
|
MatrixEntity(id: .user(id: "@bob:matrix.org"),
|
||||||
|
via: ["matrix.org"]))
|
||||||
|
|
||||||
|
url = "https://matrix.to/#/!roomidentifier:matrix.org?via=matrix.org"
|
||||||
|
XCTAssertEqual(parseMatrixEntityFrom(uri: url.absoluteString),
|
||||||
|
MatrixEntity(id: .room(id: "!roomidentifier:matrix.org"),
|
||||||
|
via: ["matrix.org"]))
|
||||||
|
|
||||||
|
url = "https://matrix.to/#/%23roomalias:matrix.org?via=matrix.org"
|
||||||
|
XCTAssertEqual(parseMatrixEntityFrom(uri: url.absoluteString),
|
||||||
|
MatrixEntity(id: .roomAlias(alias: "#roomalias:matrix.org"),
|
||||||
|
via: ["matrix.org"]))
|
||||||
|
|
||||||
|
url = "https://matrix.to/#/!roomidentifier:matrix.org/$eventidentifier?via=matrix.org"
|
||||||
|
XCTAssertEqual(parseMatrixEntityFrom(uri: url.absoluteString),
|
||||||
|
MatrixEntity(id: .eventOnRoomId(roomId: "!roomidentifier:matrix.org", eventId: "$eventidentifier"),
|
||||||
|
via: ["matrix.org"]))
|
||||||
|
|
||||||
|
url = "https://matrix.to/#/#roomalias:matrix.org/$eventidentifier?via=matrix.org"
|
||||||
|
XCTAssertEqual(parseMatrixEntityFrom(uri: url.absoluteString),
|
||||||
|
MatrixEntity(id: .eventOnRoomAlias(alias: "#roomalias:matrix.org", eventId: "$eventidentifier"),
|
||||||
|
via: ["matrix.org"]))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,8 +39,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: notificationSettingsProxyMock,
|
notificationSettingsProxy: notificationSettingsProxyMock,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
AppSettings.resetAllSettings()
|
AppSettings.resetAllSettings()
|
||||||
}
|
}
|
||||||
@@ -54,8 +53,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
let deferred = deferFulfillment(context.$viewState) { state in
|
let deferred = deferFulfillment(context.$viewState) { state in
|
||||||
state.bindings.leaveRoomAlertItem != nil
|
state.bindings.leaveRoomAlertItem != nil
|
||||||
}
|
}
|
||||||
@@ -76,8 +74,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
let deferred = deferFulfillment(context.$viewState) { state in
|
let deferred = deferFulfillment(context.$viewState) { state in
|
||||||
state.bindings.leaveRoomAlertItem != nil
|
state.bindings.leaveRoomAlertItem != nil
|
||||||
}
|
}
|
||||||
@@ -99,8 +96,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
context.send(viewAction: .processTapLeave)
|
context.send(viewAction: .processTapLeave)
|
||||||
XCTAssertEqual(context.leaveRoomAlertItem?.state, .empty)
|
XCTAssertEqual(context.leaveRoomAlertItem?.state, .empty)
|
||||||
@@ -152,8 +148,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
let deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
let deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||||
state.dmRecipient != nil
|
state.dmRecipient != nil
|
||||||
@@ -175,8 +170,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||||
state.dmRecipient != nil
|
state.dmRecipient != nil
|
||||||
@@ -209,8 +203,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||||
state.dmRecipient != nil
|
state.dmRecipient != nil
|
||||||
@@ -242,8 +235,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||||
state.dmRecipient != nil
|
state.dmRecipient != nil
|
||||||
@@ -276,8 +268,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||||
state.dmRecipient != nil
|
state.dmRecipient != nil
|
||||||
@@ -311,8 +302,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
||||||
|
|
||||||
@@ -328,8 +318,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
||||||
|
|
||||||
@@ -364,8 +353,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
||||||
|
|
||||||
@@ -387,8 +375,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
||||||
|
|
||||||
@@ -410,8 +397,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
||||||
|
|
||||||
@@ -430,8 +416,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
||||||
|
|
||||||
@@ -450,8 +435,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
notificationSettingsProxy: NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()),
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
_ = await context.$viewState.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main).values.first()
|
||||||
|
|
||||||
@@ -468,8 +452,7 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
notificationSettingsProxy: notificationSettingsProxyMock,
|
notificationSettingsProxy: notificationSettingsProxyMock,
|
||||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()))
|
||||||
mentionBuilder: MentionBuilder()))
|
|
||||||
|
|
||||||
var deferred = deferFulfillment(context.$viewState) { state in
|
var deferred = deferFulfillment(context.$viewState) { state in
|
||||||
state.notificationSettingsState.isError
|
state.notificationSettingsState.isError
|
||||||
|
|||||||
Reference in New Issue
Block a user