mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-06 12:28:29 +00:00
QuickLook media. (#447)
* Use QL previews for video and present full screen. * Use URL(staticString:) in more places. * Fix DesignKit issues.
This commit is contained in:
@@ -40,6 +40,7 @@ public struct ElementCapsuleButtonStyle: ButtonStyle {
|
|||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.background(background)
|
.background(background)
|
||||||
.opacity(configuration.isPressed ? 0.6 : 1)
|
.opacity(configuration.isPressed ? 0.6 : 1)
|
||||||
|
.contentShape(Capsule())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ public struct ElementTextFieldStyle: TextFieldStyle {
|
|||||||
configuration
|
configuration
|
||||||
.textFieldStyle(BorderedInputFieldStyle(isEditing: isFocused, isError: isError, returnKey: nil))
|
.textFieldStyle(BorderedInputFieldStyle(isEditing: isFocused, isError: isError, returnKey: nil))
|
||||||
.focused($isFocused)
|
.focused($isFocused)
|
||||||
|
.onTapGesture { isFocused = true } // Set focus with taps in the space between the border and text field.
|
||||||
|
|
||||||
if let footerText {
|
if let footerText {
|
||||||
Text(footerText)
|
Text(footerText)
|
||||||
|
|||||||
@@ -47,7 +47,6 @@
|
|||||||
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */; };
|
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */; };
|
||||||
14132418A748C988B85B025E /* OnboardingPageIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09199C43BAB209C0BD89A836 /* OnboardingPageIndicator.swift */; };
|
14132418A748C988B85B025E /* OnboardingPageIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09199C43BAB209C0BD89A836 /* OnboardingPageIndicator.swift */; };
|
||||||
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */; };
|
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */; };
|
||||||
1504CE9A609A348D90B69E47 /* VideoPlayerViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3004DFA1B10951962787D90 /* VideoPlayerViewModelTests.swift */; };
|
|
||||||
152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */; };
|
152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.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 */; };
|
||||||
@@ -61,7 +60,6 @@
|
|||||||
191161FE9E0DA89704301F37 /* Untranslated.strings in Resources */ = {isa = PBXBuildFile; fileRef = D2F7194F440375338F8E2487 /* Untranslated.strings */; };
|
191161FE9E0DA89704301F37 /* Untranslated.strings in Resources */ = {isa = PBXBuildFile; fileRef = D2F7194F440375338F8E2487 /* Untranslated.strings */; };
|
||||||
1950A80CD198BED283DFC2CE /* ClientProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */; };
|
1950A80CD198BED283DFC2CE /* ClientProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */; };
|
||||||
19839F3526CE8C35AAF241AD /* ServerSelectionViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F52BF30D12BA3BD3D3DBB8F /* ServerSelectionViewModelProtocol.swift */; };
|
19839F3526CE8C35AAF241AD /* ServerSelectionViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F52BF30D12BA3BD3D3DBB8F /* ServerSelectionViewModelProtocol.swift */; };
|
||||||
19ED6CF7FDBB1158692D101C /* VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D783758EAE6A88C93564EB /* VideoPlayerViewModel.swift */; };
|
|
||||||
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = A678E40E917620059695F067 /* MatrixRustSDK */; };
|
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = A678E40E917620059695F067 /* MatrixRustSDK */; };
|
||||||
1A8BDEB96C3B2F033FA563F8 /* EmojiPickerHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB785716B9212C093704E767 /* EmojiPickerHeaderView.swift */; };
|
1A8BDEB96C3B2F033FA563F8 /* EmojiPickerHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB785716B9212C093704E767 /* EmojiPickerHeaderView.swift */; };
|
||||||
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; };
|
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; };
|
||||||
@@ -183,7 +181,6 @@
|
|||||||
5D9F0695DC6C0057F85C12B6 /* UserNotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1113CA0A67B4AA227AAFB63B /* UserNotificationController.swift */; };
|
5D9F0695DC6C0057F85C12B6 /* UserNotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1113CA0A67B4AA227AAFB63B /* UserNotificationController.swift */; };
|
||||||
5E0F2E612718BB4397A6D40A /* TextRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */; };
|
5E0F2E612718BB4397A6D40A /* TextRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */; };
|
||||||
5E25568E1CDAD983517E58B5 /* MediaSourceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179423E34EE846E048E49CBF /* MediaSourceProxy.swift */; };
|
5E25568E1CDAD983517E58B5 /* MediaSourceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179423E34EE846E048E49CBF /* MediaSourceProxy.swift */; };
|
||||||
5E540CAEF764D7FBD8D80776 /* VideoPlayerModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A3FC45B7643298BF361CEB1 /* VideoPlayerModels.swift */; };
|
|
||||||
5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; };
|
5F06AD3C66884CE793AE6119 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */; };
|
||||||
5F1FDE49DFD0C680386E48F9 /* TemplateViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B80895CE021B49847BD7D74 /* TemplateViewModelProtocol.swift */; };
|
5F1FDE49DFD0C680386E48F9 /* TemplateViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B80895CE021B49847BD7D74 /* TemplateViewModelProtocol.swift */; };
|
||||||
5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7109E709A7738E6BCC4553E6 /* Localizable.strings */; };
|
5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7109E709A7738E6BCC4553E6 /* Localizable.strings */; };
|
||||||
@@ -388,12 +385,10 @@
|
|||||||
C7B251DC896C0867C51B616D /* AnalyticsPrompt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541542F5AC323709D8563458 /* AnalyticsPrompt.swift */; };
|
C7B251DC896C0867C51B616D /* AnalyticsPrompt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541542F5AC323709D8563458 /* AnalyticsPrompt.swift */; };
|
||||||
C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */; };
|
C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */; };
|
||||||
C8E82786DE1B6A400DA9BA25 /* RoomTimelineItemProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289FA233E896FBC5956C67E0 /* RoomTimelineItemProperties.swift */; };
|
C8E82786DE1B6A400DA9BA25 /* RoomTimelineItemProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289FA233E896FBC5956C67E0 /* RoomTimelineItemProperties.swift */; };
|
||||||
C94A6048C654B01163AE1BF1 /* VideoPlayerViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5282B7A2DCD076AD2CF27F46 /* VideoPlayerViewModelProtocol.swift */; };
|
|
||||||
CA45758F08DF42D41D8A4B29 /* FilePreviewViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF38B69D2C331A499276F400 /* FilePreviewViewModelTests.swift */; };
|
CA45758F08DF42D41D8A4B29 /* FilePreviewViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF38B69D2C331A499276F400 /* FilePreviewViewModelTests.swift */; };
|
||||||
CB137BFB3E083C33E398A6CB /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; };
|
CB137BFB3E083C33E398A6CB /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; };
|
||||||
CB498F4E27AA0545DCEF0F6F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4003BC24B24C9E63D3304177 /* DeviceKit */; };
|
CB498F4E27AA0545DCEF0F6F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4003BC24B24C9E63D3304177 /* DeviceKit */; };
|
||||||
CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; };
|
CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; };
|
||||||
CBF64DE774298D773DBD5354 /* VideoPlayerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB634B42CFE667112369D57 /* VideoPlayerScreen.swift */; };
|
|
||||||
CC2A6B71E12DDF1EE6ECD299 /* RoomMembersCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F118CF7C5548099AACF7E90C /* RoomMembersCoordinator.swift */; };
|
CC2A6B71E12DDF1EE6ECD299 /* RoomMembersCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F118CF7C5548099AACF7E90C /* RoomMembersCoordinator.swift */; };
|
||||||
CC736DA1AA8F8B9FD8785009 /* ScreenshotDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C4AF6E3885730CD560311C /* ScreenshotDetector.swift */; };
|
CC736DA1AA8F8B9FD8785009 /* ScreenshotDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C4AF6E3885730CD560311C /* ScreenshotDetector.swift */; };
|
||||||
CCAA0671B46EAFD0BB528E2C /* apple_emojis_data.json in Resources */ = {isa = PBXBuildFile; fileRef = 8FC26871038FB0E4AAE22605 /* apple_emojis_data.json */; };
|
CCAA0671B46EAFD0BB528E2C /* apple_emojis_data.json in Resources */ = {isa = PBXBuildFile; fileRef = 8FC26871038FB0E4AAE22605 /* apple_emojis_data.json */; };
|
||||||
@@ -409,7 +404,6 @@
|
|||||||
D05A193AE63030F2CFCE2E9C /* UITestScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */; };
|
D05A193AE63030F2CFCE2E9C /* UITestScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */; };
|
||||||
D0619D2E6B9C511190FBEB95 /* RoomMessageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607974D08BD2AF83725D817A /* RoomMessageProtocol.swift */; };
|
D0619D2E6B9C511190FBEB95 /* RoomMessageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607974D08BD2AF83725D817A /* RoomMessageProtocol.swift */; };
|
||||||
D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; };
|
D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; };
|
||||||
D3E603A5E9D529CF293E1BF9 /* VideoPlayerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1651A532305027D3F605E2B /* VideoPlayerCoordinator.swift */; };
|
|
||||||
D59F046B15AA8E971053C1A6 /* RoomDetailsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 813B198AE8833FD12E5A9C78 /* RoomDetailsCoordinator.swift */; };
|
D59F046B15AA8E971053C1A6 /* RoomDetailsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 813B198AE8833FD12E5A9C78 /* RoomDetailsCoordinator.swift */; };
|
||||||
D5C805F49B2C75DC3793E780 /* EmojiItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */; };
|
D5C805F49B2C75DC3793E780 /* EmojiItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37A243E04B58DC6E41FDCD82 /* EmojiItem.swift */; };
|
||||||
D5EA4C6C80579279770D5804 /* ImageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */; };
|
D5EA4C6C80579279770D5804 /* ImageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */; };
|
||||||
@@ -475,7 +469,7 @@
|
|||||||
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; };
|
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; };
|
||||||
FBCD77D557AACBE9B445133A /* MediaProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12C9E0B61A77C7F0EE7918C /* MediaProxy.swift */; };
|
FBCD77D557AACBE9B445133A /* MediaProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12C9E0B61A77C7F0EE7918C /* MediaProxy.swift */; };
|
||||||
FBF09B6C900415800DDF2A21 /* EmojiProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */; };
|
FBF09B6C900415800DDF2A21 /* EmojiProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */; };
|
||||||
FCB9B475F908765531335859 /* NavigationSplitCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63A32A0627A03F00A2900FE /* NavigationSplitCoordinator.swift */; };
|
FCB9B475F908765531335859 /* NavigationSplitCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63A32A0627A03F00A2900FE /* NavigationSplitCoordinatorTests.swift */; };
|
||||||
FCD3F2B82CAB29A07887A127 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 2B43F2AF7456567FE37270A7 /* KeychainAccess */; };
|
FCD3F2B82CAB29A07887A127 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 2B43F2AF7456567FE37270A7 /* KeychainAccess */; };
|
||||||
FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; };
|
FE4593FC2A02AAF92E089565 /* ElementAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF1593DD87F974F8509BB619 /* ElementAnimations.swift */; };
|
||||||
FE79E2BCCF69E8BF4D21E15A /* RoomMessageFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA154570F693D93513E584C1 /* RoomMessageFactory.swift */; };
|
FE79E2BCCF69E8BF4D21E15A /* RoomMessageFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA154570F693D93513E584C1 /* RoomMessageFactory.swift */; };
|
||||||
@@ -557,7 +551,6 @@
|
|||||||
0C88046D6A070D9827181C4D /* OnboardingUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingUITests.swift; sourceTree = "<group>"; };
|
0C88046D6A070D9827181C4D /* OnboardingUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingUITests.swift; sourceTree = "<group>"; };
|
||||||
0CB569EAA5017B5B23970655 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; };
|
0CB569EAA5017B5B23970655 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
0D8F620C8B314840D8602E3F /* NSE.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = NSE.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
0D8F620C8B314840D8602E3F /* NSE.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = NSE.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
0DB634B42CFE667112369D57 /* VideoPlayerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerScreen.swift; sourceTree = "<group>"; };
|
|
||||||
0DD16CE9A66C9040B066AD60 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = vi; path = vi.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
0DD16CE9A66C9040B066AD60 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = vi; path = vi.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationControllerTests.swift; sourceTree = "<group>"; };
|
0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationControllerTests.swift; sourceTree = "<group>"; };
|
||||||
0E7062F88E9D5F79C8A80524 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = th; path = th.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
0E7062F88E9D5F79C8A80524 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = th; path = th.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
@@ -590,7 +583,6 @@
|
|||||||
18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryProtocol.swift; sourceTree = "<group>"; };
|
18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryProtocol.swift; sourceTree = "<group>"; };
|
||||||
1941C8817E6B6971BA4415F5 /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = "<group>"; };
|
1941C8817E6B6971BA4415F5 /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+Untranslated.swift"; sourceTree = "<group>"; };
|
1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+Untranslated.swift"; sourceTree = "<group>"; };
|
||||||
1A3FC45B7643298BF361CEB1 /* VideoPlayerModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerModels.swift; sourceTree = "<group>"; };
|
|
||||||
1A63815AD6A5C306453342F2 /* ImageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineItem.swift; sourceTree = "<group>"; };
|
1A63815AD6A5C306453342F2 /* ImageRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
1BC4437C107D52ED19357DFC /* OnboardingViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewModelProtocol.swift; sourceTree = "<group>"; };
|
1BC4437C107D52ED19357DFC /* OnboardingViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
1C429043E986008B97736636 /* ab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ab; path = ab.lproj/Localizable.strings; sourceTree = "<group>"; };
|
1C429043E986008B97736636 /* ab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ab; path = ab.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
@@ -712,7 +704,6 @@
|
|||||||
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
|
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
51DF91C374901E94D93276F1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "es-MX"; path = "es-MX.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
51DF91C374901E94D93276F1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "es-MX"; path = "es-MX.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||||
5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = "<group>"; };
|
5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = "<group>"; };
|
||||||
5282B7A2DCD076AD2CF27F46 /* VideoPlayerViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModelProtocol.swift; sourceTree = "<group>"; };
|
|
||||||
529513218340CC8419273165 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
529513218340CC8419273165 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = "<group>"; };
|
52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = "<group>"; };
|
||||||
53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = "<group>"; };
|
53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = "<group>"; };
|
||||||
@@ -859,7 +850,6 @@
|
|||||||
A1ED7E89865201EE7D53E6DA /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
A1ED7E89865201EE7D53E6DA /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
A2AC3C656E960E15B5905E05 /* UnsupportedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineView.swift; sourceTree = "<group>"; };
|
A2AC3C656E960E15B5905E05 /* UnsupportedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
A2B6433F516F1E6DFA0E2D89 /* vls */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vls; path = vls.lproj/Localizable.strings; sourceTree = "<group>"; };
|
A2B6433F516F1E6DFA0E2D89 /* vls */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vls; path = vls.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
A3004DFA1B10951962787D90 /* VideoPlayerViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModelTests.swift; sourceTree = "<group>"; };
|
|
||||||
A30A1758E2B73EF38E7C42F8 /* ServerSelectionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionModels.swift; sourceTree = "<group>"; };
|
A30A1758E2B73EF38E7C42F8 /* ServerSelectionModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionModels.swift; sourceTree = "<group>"; };
|
||||||
A34A814CBD56230BC74FFCF4 /* MXLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXLogger.swift; sourceTree = "<group>"; };
|
A34A814CBD56230BC74FFCF4 /* MXLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXLogger.swift; sourceTree = "<group>"; };
|
||||||
A40C19719687984FD9478FBE /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; };
|
A40C19719687984FD9478FBE /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; };
|
||||||
@@ -869,7 +859,7 @@
|
|||||||
A4B5B19A10D3F7C2BC5315DF /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = "<group>"; };
|
A4B5B19A10D3F7C2BC5315DF /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
A4CF2FC815D26B337E78DA45 /* RoomMembersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersViewModel.swift; sourceTree = "<group>"; };
|
A4CF2FC815D26B337E78DA45 /* RoomMembersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersViewModel.swift; sourceTree = "<group>"; };
|
||||||
A5B0B1226DA8DB55918B34CD /* FileCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileCache.swift; sourceTree = "<group>"; };
|
A5B0B1226DA8DB55918B34CD /* FileCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileCache.swift; sourceTree = "<group>"; };
|
||||||
A63A32A0627A03F00A2900FE /* NavigationSplitCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitCoordinator.swift; sourceTree = "<group>"; };
|
A63A32A0627A03F00A2900FE /* NavigationSplitCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitCoordinatorTests.swift; sourceTree = "<group>"; };
|
||||||
A64F0DB78E0AC23C91AD89EF /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = mk.lproj/Localizable.strings; sourceTree = "<group>"; };
|
A64F0DB78E0AC23C91AD89EF /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = mk.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
A65F140F9FE5E8D4DAEFF354 /* RoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxy.swift; sourceTree = "<group>"; };
|
A65F140F9FE5E8D4DAEFF354 /* RoomProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxy.swift; sourceTree = "<group>"; };
|
||||||
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = "<group>"; };
|
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = "<group>"; };
|
||||||
@@ -968,10 +958,8 @@
|
|||||||
D06DFD894157A4C93A02D8B5 /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/Localizable.strings; sourceTree = "<group>"; };
|
D06DFD894157A4C93A02D8B5 /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
|
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
|
||||||
D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
|
D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
D1651A532305027D3F605E2B /* VideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerCoordinator.swift; sourceTree = "<group>"; };
|
|
||||||
D1A9CCCF53495CF3D7B19FCE /* MockSessionVerificationControllerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSessionVerificationControllerProxy.swift; sourceTree = "<group>"; };
|
D1A9CCCF53495CF3D7B19FCE /* MockSessionVerificationControllerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSessionVerificationControllerProxy.swift; sourceTree = "<group>"; };
|
||||||
D263254AFE5B7993FFBBF324 /* NSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NSE.entitlements; sourceTree = "<group>"; };
|
D263254AFE5B7993FFBBF324 /* NSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NSE.entitlements; sourceTree = "<group>"; };
|
||||||
D2D783758EAE6A88C93564EB /* VideoPlayerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModel.swift; sourceTree = "<group>"; };
|
|
||||||
D31DC8105C6233E5FFD9B84C /* element-x-ios */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "element-x-ios"; path = .; sourceTree = SOURCE_ROOT; };
|
D31DC8105C6233E5FFD9B84C /* element-x-ios */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "element-x-ios"; path = .; sourceTree = SOURCE_ROOT; };
|
||||||
D33116993D54FADC0C721C1F /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
|
D33116993D54FADC0C721C1F /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
|
||||||
D3D455BC2423D911A62ACFB2 /* NSELogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSELogger.swift; sourceTree = "<group>"; };
|
D3D455BC2423D911A62ACFB2 /* NSELogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSELogger.swift; sourceTree = "<group>"; };
|
||||||
@@ -1252,18 +1240,6 @@
|
|||||||
path = Resources;
|
path = Resources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
285079C24A5189C48284CC47 /* VideoPlayer */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D1651A532305027D3F605E2B /* VideoPlayerCoordinator.swift */,
|
|
||||||
1A3FC45B7643298BF361CEB1 /* VideoPlayerModels.swift */,
|
|
||||||
D2D783758EAE6A88C93564EB /* VideoPlayerViewModel.swift */,
|
|
||||||
5282B7A2DCD076AD2CF27F46 /* VideoPlayerViewModelProtocol.swift */,
|
|
||||||
5E01022071DDDC48EF453374 /* View */,
|
|
||||||
);
|
|
||||||
path = VideoPlayer;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
2D6DC9871FD7173E51D67C73 /* Cache */ = {
|
2D6DC9871FD7173E51D67C73 /* Cache */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1601,14 +1577,6 @@
|
|||||||
path = EmojiMart;
|
path = EmojiMart;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
5E01022071DDDC48EF453374 /* View */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
0DB634B42CFE667112369D57 /* VideoPlayerScreen.swift */,
|
|
||||||
);
|
|
||||||
path = View;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
605F8221E52991786397FCC9 /* View */ = {
|
605F8221E52991786397FCC9 /* View */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1723,7 +1691,7 @@
|
|||||||
A05707BF550D770168A406DB /* LoginViewModelTests.swift */,
|
A05707BF550D770168A406DB /* LoginViewModelTests.swift */,
|
||||||
F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */,
|
F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */,
|
||||||
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */,
|
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */,
|
||||||
A63A32A0627A03F00A2900FE /* NavigationSplitCoordinator.swift */,
|
A63A32A0627A03F00A2900FE /* NavigationSplitCoordinatorTests.swift */,
|
||||||
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */,
|
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */,
|
||||||
00A941F289F6AB876BA3361A /* OnboardingViewModelTests.swift */,
|
00A941F289F6AB876BA3361A /* OnboardingViewModelTests.swift */,
|
||||||
6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */,
|
6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */,
|
||||||
@@ -1740,7 +1708,6 @@
|
|||||||
1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */,
|
1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */,
|
||||||
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */,
|
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */,
|
||||||
0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */,
|
0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */,
|
||||||
A3004DFA1B10951962787D90 /* VideoPlayerViewModelTests.swift */,
|
|
||||||
53280D2292E6C9C7821773FD /* UserSession */,
|
53280D2292E6C9C7821773FD /* UserSession */,
|
||||||
7583EAC171059A86B767209F /* MediaProvider */,
|
7583EAC171059A86B767209F /* MediaProvider */,
|
||||||
7DBC911559934065993A5FF4 /* NotificationManager */,
|
7DBC911559934065993A5FF4 /* NotificationManager */,
|
||||||
@@ -2361,7 +2328,6 @@
|
|||||||
679E9837ECA8D6776079D16E /* RoomScreen */,
|
679E9837ECA8D6776079D16E /* RoomScreen */,
|
||||||
D958761758AA1110476DE6A3 /* SessionVerification */,
|
D958761758AA1110476DE6A3 /* SessionVerification */,
|
||||||
70B74A432C241E56A7ACE610 /* Settings */,
|
70B74A432C241E56A7ACE610 /* Settings */,
|
||||||
285079C24A5189C48284CC47 /* VideoPlayer */,
|
|
||||||
);
|
);
|
||||||
path = Screens;
|
path = Screens;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -2923,7 +2889,7 @@
|
|||||||
DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */,
|
DC68E866D6E664B0D2B06E74 /* MockImageCache.swift in Sources */,
|
||||||
E9631F628251F77A24AA4BB4 /* MockMediaProxy.swift in Sources */,
|
E9631F628251F77A24AA4BB4 /* MockMediaProxy.swift in Sources */,
|
||||||
981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */,
|
981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */,
|
||||||
FCB9B475F908765531335859 /* NavigationSplitCoordinator.swift in Sources */,
|
FCB9B475F908765531335859 /* NavigationSplitCoordinatorTests.swift in Sources */,
|
||||||
4BB282209EA82015D0DF8F89 /* NavigationStackCoordinatorTests.swift in Sources */,
|
4BB282209EA82015D0DF8F89 /* NavigationStackCoordinatorTests.swift in Sources */,
|
||||||
1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */,
|
1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */,
|
||||||
F9F6D2883BBEBB9A3789A137 /* OnboardingViewModelTests.swift in Sources */,
|
F9F6D2883BBEBB9A3789A137 /* OnboardingViewModelTests.swift in Sources */,
|
||||||
@@ -2946,7 +2912,6 @@
|
|||||||
08248D02BACA75CDC3B39A96 /* UserNotificationCenterSpy.swift in Sources */,
|
08248D02BACA75CDC3B39A96 /* UserNotificationCenterSpy.swift in Sources */,
|
||||||
8196A2E71ACC902DD69F24EE /* UserNotificationControllerTests.swift in Sources */,
|
8196A2E71ACC902DD69F24EE /* UserNotificationControllerTests.swift in Sources */,
|
||||||
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */,
|
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */,
|
||||||
1504CE9A609A348D90B69E47 /* VideoPlayerViewModelTests.swift in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -3249,11 +3214,6 @@
|
|||||||
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */,
|
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */,
|
||||||
7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */,
|
7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */,
|
||||||
AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */,
|
AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */,
|
||||||
D3E603A5E9D529CF293E1BF9 /* VideoPlayerCoordinator.swift in Sources */,
|
|
||||||
5E540CAEF764D7FBD8D80776 /* VideoPlayerModels.swift in Sources */,
|
|
||||||
CBF64DE774298D773DBD5354 /* VideoPlayerScreen.swift in Sources */,
|
|
||||||
19ED6CF7FDBB1158692D101C /* VideoPlayerViewModel.swift in Sources */,
|
|
||||||
C94A6048C654B01163AE1BF1 /* VideoPlayerViewModelProtocol.swift in Sources */,
|
|
||||||
36C10EDEDC0466E3A9D63132 /* VideoRoomTimelineItem.swift in Sources */,
|
36C10EDEDC0466E3A9D63132 /* VideoRoomTimelineItem.swift in Sources */,
|
||||||
64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */,
|
64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */,
|
||||||
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */,
|
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */,
|
||||||
|
|||||||
@@ -90,6 +90,28 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS
|
|||||||
sheetModule?.coordinator
|
sheetModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Published fileprivate var fullScreenCoverModule: NavigationModule? {
|
||||||
|
didSet {
|
||||||
|
if let oldValue {
|
||||||
|
logPresentationChange("Remove fullscreen cover", oldValue)
|
||||||
|
oldValue.coordinator.stop()
|
||||||
|
oldValue.dismissalCallback?()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let fullScreenCoverModule {
|
||||||
|
logPresentationChange("Set fullscreen cover", fullScreenCoverModule)
|
||||||
|
fullScreenCoverModule.coordinator.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCompactLayoutComponents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The currently displayed fullscreen cover coordinator
|
||||||
|
var fullScreenCoverCoordinator: (any CoordinatorProtocol)? {
|
||||||
|
fullScreenCoverModule?.coordinator
|
||||||
|
}
|
||||||
|
|
||||||
@Published fileprivate var compactLayoutRootModule: NavigationModule?
|
@Published fileprivate var compactLayoutRootModule: NavigationModule?
|
||||||
|
|
||||||
var compactLayoutRootCoordinator: (any CoordinatorProtocol)? {
|
var compactLayoutRootCoordinator: (any CoordinatorProtocol)? {
|
||||||
@@ -148,6 +170,19 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS
|
|||||||
|
|
||||||
sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Present a fullscreen cover on top of the split view
|
||||||
|
/// - Parameters:
|
||||||
|
/// - coordinator: the coordinator to display
|
||||||
|
/// - dismissalCallback: called when the fullscreen cover has been dismissed, programatically or otherwise
|
||||||
|
func setFullScreenCoverCoordinator(_ coordinator: (any CoordinatorProtocol)?, dismissalCallback: (() -> Void)? = nil) {
|
||||||
|
guard let coordinator else {
|
||||||
|
fullScreenCoverModule = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fullScreenCoverModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - CoordinatorProtocol
|
// MARK: - CoordinatorProtocol
|
||||||
|
|
||||||
@@ -301,6 +336,11 @@ private struct NavigationSplitCoordinatorView: View {
|
|||||||
// through the NavigationSplitCoordinator as well.
|
// through the NavigationSplitCoordinator as well.
|
||||||
.sheet(item: $navigationSplitCoordinator.sheetModule) { module in
|
.sheet(item: $navigationSplitCoordinator.sheetModule) { module in
|
||||||
module.coordinator.toPresentable()
|
module.coordinator.toPresentable()
|
||||||
|
.tint(.element.accent)
|
||||||
|
}
|
||||||
|
.fullScreenCover(item: $navigationSplitCoordinator.fullScreenCoverModule) { module in
|
||||||
|
module.coordinator.toPresentable()
|
||||||
|
.tint(.element.accent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,6 +429,31 @@ class NavigationStackCoordinator: ObservableObject, CoordinatorProtocol, CustomS
|
|||||||
return sheetModule?.coordinator
|
return sheetModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Published fileprivate var fullScreenCoverModule: NavigationModule? {
|
||||||
|
didSet {
|
||||||
|
if let oldValue {
|
||||||
|
logPresentationChange("Remove fullscreen cover", oldValue)
|
||||||
|
oldValue.coordinator.stop()
|
||||||
|
oldValue.dismissalCallback?()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let fullScreenCoverModule {
|
||||||
|
logPresentationChange("Set fullscreen cover", fullScreenCoverModule)
|
||||||
|
fullScreenCoverModule.coordinator.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The currently presented fullscreen cover coordinator
|
||||||
|
// Fullscreen covers will be presented through the NavigationSplitCoordinator if provided
|
||||||
|
var fullScreenCoverCoordinator: (any CoordinatorProtocol)? {
|
||||||
|
if let navigationSplitCoordinator {
|
||||||
|
return navigationSplitCoordinator.fullScreenCoverCoordinator
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullScreenCoverModule?.coordinator
|
||||||
|
}
|
||||||
|
|
||||||
@Published fileprivate var stackModules = [NavigationModule]() {
|
@Published fileprivate var stackModules = [NavigationModule]() {
|
||||||
didSet {
|
didSet {
|
||||||
let diffs = stackModules.difference(from: oldValue)
|
let diffs = stackModules.difference(from: oldValue)
|
||||||
@@ -488,6 +553,25 @@ class NavigationStackCoordinator: ObservableObject, CoordinatorProtocol, CustomS
|
|||||||
sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Present a fullscreen cover on top of the stack. If this NavigationStackCoordinator is embedded within a NavigationSplitCoordinator
|
||||||
|
/// then the presentation will be proxied to the split
|
||||||
|
/// - Parameters:
|
||||||
|
/// - coordinator: the coordinator to display
|
||||||
|
/// - dismissalCallback: called when the fullscreen cover has been dismissed, programatically or otherwise
|
||||||
|
func setFullScreenCoverCoordinator(_ coordinator: (any CoordinatorProtocol)?, dismissalCallback: (() -> Void)? = nil) {
|
||||||
|
if let navigationSplitCoordinator {
|
||||||
|
navigationSplitCoordinator.setFullScreenCoverCoordinator(coordinator, dismissalCallback: dismissalCallback)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let coordinator else {
|
||||||
|
fullScreenCoverModule = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fullScreenCoverModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - CoordinatorProtocol
|
// MARK: - CoordinatorProtocol
|
||||||
|
|
||||||
func toPresentable() -> AnyView {
|
func toPresentable() -> AnyView {
|
||||||
@@ -524,6 +608,11 @@ private struct NavigationStackCoordinatorView: View {
|
|||||||
}
|
}
|
||||||
.sheet(item: $navigationStackCoordinator.sheetModule) { module in
|
.sheet(item: $navigationStackCoordinator.sheetModule) { module in
|
||||||
module.coordinator.toPresentable()
|
module.coordinator.toPresentable()
|
||||||
|
.tint(.element.accent)
|
||||||
|
}
|
||||||
|
.fullScreenCover(item: $navigationStackCoordinator.fullScreenCoverModule) { module in
|
||||||
|
module.coordinator.toPresentable()
|
||||||
|
.tint(.element.accent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,10 +64,7 @@ extension LoginHomeserver {
|
|||||||
|
|
||||||
/// A mock homeserver that supports only supports authentication via a single SSO provider.
|
/// A mock homeserver that supports only supports authentication via a single SSO provider.
|
||||||
static var mockOIDC: LoginHomeserver {
|
static var mockOIDC: LoginHomeserver {
|
||||||
guard let issuerURL = URL(string: "https://auth.company.com") else {
|
let issuerURL = URL(staticString: "https://auth.company.com")
|
||||||
fatalError("This shoud never fail parsing")
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoginHomeserver(address: "company.com", loginMode: .oidc(issuerURL))
|
return LoginHomeserver(address: "company.com", loginMode: .oidc(issuerURL))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,19 +22,27 @@ struct FilePreviewScreen: View {
|
|||||||
@ObservedObject var context: FilePreviewViewModel.Context
|
@ObservedObject var context: FilePreviewViewModel.Context
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
PreviewController(fileURL: context.viewState.fileURL, title: context.viewState.title)
|
PreviewView(context: context,
|
||||||
.ignoresSafeArea(.all, edges: [.horizontal, .bottom])
|
fileURL: context.viewState.fileURL,
|
||||||
.navigationTitle(ElementL10n.attachmentTypeFile)
|
title: context.viewState.title)
|
||||||
|
.ignoresSafeArea()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct PreviewController: UIViewControllerRepresentable {
|
private struct PreviewView: UIViewControllerRepresentable {
|
||||||
|
let context: FilePreviewViewModel.Context
|
||||||
let fileURL: URL
|
let fileURL: URL
|
||||||
let title: String?
|
let title: String?
|
||||||
|
|
||||||
func makeUIViewController(context: Context) -> UINavigationController {
|
func makeUIViewController(context: Context) -> UINavigationController {
|
||||||
let controller = QLPreviewController()
|
let controller = QLPreviewController()
|
||||||
controller.dataSource = context.coordinator
|
controller.dataSource = context.coordinator
|
||||||
|
|
||||||
|
let doneButton = UIBarButtonItem(title: "Done",
|
||||||
|
style: .done,
|
||||||
|
target: context.coordinator,
|
||||||
|
action: #selector(Coordinator.done))
|
||||||
|
controller.navigationItem.rightBarButtonItem = doneButton
|
||||||
|
|
||||||
return UINavigationController(rootViewController: controller)
|
return UINavigationController(rootViewController: controller)
|
||||||
}
|
}
|
||||||
@@ -42,22 +50,28 @@ private struct PreviewController: UIViewControllerRepresentable {
|
|||||||
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) { }
|
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) { }
|
||||||
|
|
||||||
func makeCoordinator() -> Coordinator {
|
func makeCoordinator() -> Coordinator {
|
||||||
Coordinator(parent: self)
|
Coordinator(view: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Coordinator: NSObject, QLPreviewControllerDataSource {
|
||||||
|
let view: PreviewView
|
||||||
|
|
||||||
class Coordinator: QLPreviewControllerDataSource {
|
init(view: PreviewView) {
|
||||||
let parent: PreviewController
|
self.view = view
|
||||||
|
|
||||||
init(parent: PreviewController) {
|
|
||||||
self.parent = parent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func done() {
|
||||||
|
Task { await view.context.send(viewAction: .cancel) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - QLPreviewControllerDataSource
|
||||||
|
|
||||||
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
|
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
|
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
|
||||||
PreviewItem(previewItemURL: parent.fileURL, previewItemTitle: parent.title)
|
PreviewItem(previewItemURL: view.fileURL, previewItemTitle: view.title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
|||||||
switch result {
|
switch result {
|
||||||
case .displayRoomDetails:
|
case .displayRoomDetails:
|
||||||
self.displayRoomDetails()
|
self.displayRoomDetails()
|
||||||
case .displayVideo(let videoURL):
|
case .displayVideo(let fileURL, let title), .displayFile(let fileURL, let title):
|
||||||
self.displayVideo(for: videoURL)
|
|
||||||
case .displayFile(let fileURL, let title):
|
|
||||||
self.displayFile(for: fileURL, with: title)
|
self.displayFile(for: fileURL, with: title)
|
||||||
case .displayEmojiPicker(let itemId):
|
case .displayEmojiPicker(let itemId):
|
||||||
self.displayEmojiPickerScreen(for: itemId)
|
self.displayEmojiPickerScreen(for: itemId)
|
||||||
@@ -81,25 +79,14 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
|||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func displayVideo(for videoURL: URL) {
|
|
||||||
let params = VideoPlayerCoordinatorParameters(videoURL: videoURL)
|
|
||||||
let coordinator = VideoPlayerCoordinator(parameters: params)
|
|
||||||
|
|
||||||
coordinator.callback = { [weak self] _ in
|
|
||||||
self?.navigationStackCoordinator.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
navigationStackCoordinator.push(coordinator)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func displayFile(for fileURL: URL, with title: String?) {
|
private func displayFile(for fileURL: URL, with title: String?) {
|
||||||
let params = FilePreviewCoordinatorParameters(fileURL: fileURL, title: title)
|
let params = FilePreviewCoordinatorParameters(fileURL: fileURL, title: title)
|
||||||
let coordinator = FilePreviewCoordinator(parameters: params)
|
let coordinator = FilePreviewCoordinator(parameters: params)
|
||||||
coordinator.callback = { [weak self] _ in
|
coordinator.callback = { [weak self] _ in
|
||||||
self?.navigationStackCoordinator.pop()
|
self?.navigationStackCoordinator.setFullScreenCoverCoordinator(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationStackCoordinator.push(coordinator)
|
navigationStackCoordinator.setFullScreenCoverCoordinator(coordinator)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func displayEmojiPickerScreen(for itemId: String) {
|
private func displayEmojiPickerScreen(for itemId: String) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import UIKit
|
|||||||
|
|
||||||
enum RoomScreenViewModelAction {
|
enum RoomScreenViewModelAction {
|
||||||
case displayRoomDetails
|
case displayRoomDetails
|
||||||
case displayVideo(videoURL: URL)
|
case displayVideo(videoURL: URL, title: String?)
|
||||||
case displayFile(fileURL: URL, title: String?)
|
case displayFile(fileURL: URL, title: String?)
|
||||||
case displayEmojiPicker(itemId: String)
|
case displayEmojiPicker(itemId: String)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,8 +140,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
let action = await timelineController.processItemTap(itemId)
|
let action = await timelineController.processItemTap(itemId)
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case .displayVideo(let videoURL):
|
case .displayVideo(let videoURL, let title):
|
||||||
callback?(.displayVideo(videoURL: videoURL))
|
callback?(.displayVideo(videoURL: videoURL, title: title))
|
||||||
case .displayFile(let fileURL, let title):
|
case .displayFile(let fileURL, let title):
|
||||||
callback?(.displayFile(fileURL: fileURL, title: title))
|
callback?(.displayFile(fileURL: fileURL, title: title))
|
||||||
case .none:
|
case .none:
|
||||||
|
|||||||
@@ -1,83 +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 AVKit
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct VideoPlayerCoordinatorParameters {
|
|
||||||
let videoURL: URL
|
|
||||||
}
|
|
||||||
|
|
||||||
enum VideoPlayerCoordinatorAction {
|
|
||||||
case cancel
|
|
||||||
}
|
|
||||||
|
|
||||||
final class VideoPlayerCoordinator: CoordinatorProtocol {
|
|
||||||
private let parameters: VideoPlayerCoordinatorParameters
|
|
||||||
private var viewModel: VideoPlayerViewModelProtocol
|
|
||||||
|
|
||||||
var callback: ((VideoPlayerCoordinatorAction) -> Void)?
|
|
||||||
|
|
||||||
init(parameters: VideoPlayerCoordinatorParameters) {
|
|
||||||
self.parameters = parameters
|
|
||||||
|
|
||||||
viewModel = VideoPlayerViewModel(videoURL: parameters.videoURL,
|
|
||||||
autoplay: UIApplication.shared.applicationState == .active)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Public
|
|
||||||
|
|
||||||
func start() {
|
|
||||||
configureAudioSession(.sharedInstance())
|
|
||||||
|
|
||||||
viewModel.callback = { [weak self] action in
|
|
||||||
guard let self else { return }
|
|
||||||
MXLog.debug("VideoPlayerViewModel did complete with result: \(action).")
|
|
||||||
switch action {
|
|
||||||
case .cancel:
|
|
||||||
self.callback?(.cancel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stop() {
|
|
||||||
deconfigureAudioSession(.sharedInstance())
|
|
||||||
}
|
|
||||||
|
|
||||||
func toPresentable() -> AnyView {
|
|
||||||
AnyView(VideoPlayerScreen(context: viewModel.context))
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Private
|
|
||||||
|
|
||||||
private func configureAudioSession(_ session: AVAudioSession) {
|
|
||||||
do {
|
|
||||||
try session.setCategory(.playback,
|
|
||||||
mode: .default)
|
|
||||||
try session.setActive(true)
|
|
||||||
} catch {
|
|
||||||
MXLog.debug("Configure audio session failed: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func deconfigureAudioSession(_ session: AVAudioSession) {
|
|
||||||
do {
|
|
||||||
try session.setActive(false, options: .notifyOthersOnDeactivation)
|
|
||||||
} catch {
|
|
||||||
MXLog.debug("Deconfigure audio session failed: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +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 VideoPlayerViewModelAction {
|
|
||||||
case cancel
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VideoPlayerViewState: BindableState {
|
|
||||||
let videoURL: URL
|
|
||||||
let autoplay: Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
enum VideoPlayerViewAction {
|
|
||||||
case cancel
|
|
||||||
}
|
|
||||||
@@ -1,35 +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 SwiftUI
|
|
||||||
|
|
||||||
typealias VideoPlayerViewModelType = StateStoreViewModel<VideoPlayerViewState, VideoPlayerViewAction>
|
|
||||||
|
|
||||||
class VideoPlayerViewModel: VideoPlayerViewModelType, VideoPlayerViewModelProtocol {
|
|
||||||
var callback: ((VideoPlayerViewModelAction) -> Void)?
|
|
||||||
|
|
||||||
init(videoURL: URL, autoplay: Bool = true) {
|
|
||||||
super.init(initialViewState: VideoPlayerViewState(videoURL: videoURL,
|
|
||||||
autoplay: autoplay))
|
|
||||||
}
|
|
||||||
|
|
||||||
override func process(viewAction: VideoPlayerViewAction) async {
|
|
||||||
switch viewAction {
|
|
||||||
case .cancel:
|
|
||||||
callback?(.cancel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +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
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
protocol VideoPlayerViewModelProtocol {
|
|
||||||
var callback: ((VideoPlayerViewModelAction) -> Void)? { get set }
|
|
||||||
var context: VideoPlayerViewModelType.Context { get }
|
|
||||||
}
|
|
||||||
@@ -1,49 +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 AVKit
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct VideoPlayerScreen: View {
|
|
||||||
@ObservedObject var context: VideoPlayerViewModel.Context
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
VideoPlayer(player: player())
|
|
||||||
.ignoresSafeArea(.all, edges: [.horizontal, .bottom])
|
|
||||||
.navigationTitle(ElementL10n.a11yVideo)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func player() -> AVPlayer {
|
|
||||||
let player = AVPlayer(url: context.viewState.videoURL)
|
|
||||||
if context.viewState.autoplay {
|
|
||||||
player.play()
|
|
||||||
}
|
|
||||||
return player
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Previews
|
|
||||||
|
|
||||||
struct VideoPlayer_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
Group {
|
|
||||||
let viewModel = VideoPlayerViewModel(videoURL: URL(staticString: "https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"),
|
|
||||||
autoplay: false)
|
|
||||||
VideoPlayerScreen(context: viewModel.context)
|
|
||||||
}
|
|
||||||
.tint(.element.accent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -127,7 +127,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
if let videoURL = item.cachedVideoURL {
|
if let videoURL = item.cachedVideoURL {
|
||||||
return .displayVideo(videoURL: videoURL)
|
return .displayVideo(videoURL: videoURL, title: item.text)
|
||||||
}
|
}
|
||||||
return .none
|
return .none
|
||||||
case let item as FileRoomTimelineItem:
|
case let item as FileRoomTimelineItem:
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ enum RoomTimelineControllerCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum RoomTimelineControllerAction {
|
enum RoomTimelineControllerAction {
|
||||||
case displayVideo(videoURL: URL)
|
case displayVideo(videoURL: URL, title: String?)
|
||||||
case displayFile(fileURL: URL, title: String?)
|
case displayFile(fileURL: URL, title: String?)
|
||||||
case none
|
case none
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ final class MediaProviderTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func test_whenFileFromSourceWithSource_correctValuesAreReturned() throws {
|
func test_whenFileFromSourceWithSource_correctValuesAreReturned() throws {
|
||||||
let expectedURL = try XCTUnwrap(URL(string: "some_url"))
|
let expectedURL = URL(filePath: "/some/file/path")
|
||||||
fileCache.fileURLToReturn = expectedURL
|
fileCache.fileURLToReturn = expectedURL
|
||||||
let url = mediaProvider.fileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png")
|
let url = mediaProvider.fileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png")
|
||||||
XCTAssertEqual(fileCache.fileKey, "test1")
|
XCTAssertEqual(fileCache.fileKey, "test1")
|
||||||
@@ -177,7 +177,7 @@ final class MediaProviderTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func test_whenLoadFileFromSourceAndFileFromSourceExists_urlIsReturned() async throws {
|
func test_whenLoadFileFromSourceAndFileFromSourceExists_urlIsReturned() async throws {
|
||||||
let expectedURL = try XCTUnwrap(URL(string: "some_url"))
|
let expectedURL = URL(filePath: "/some/file/path")
|
||||||
let expectedResult: Result<URL, MediaProviderError> = .success(expectedURL)
|
let expectedResult: Result<URL, MediaProviderError> = .success(expectedURL)
|
||||||
fileCache.fileURLToReturn = expectedURL
|
fileCache.fileURLToReturn = expectedURL
|
||||||
let result = await mediaProvider.loadFileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png")
|
let result = await mediaProvider.loadFileFromSource(MediaSourceProxy(urlString: "test/test1"), fileExtension: "png")
|
||||||
@@ -185,7 +185,7 @@ final class MediaProviderTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func test_whenLoadFileFromSourceAndNoFileFromSourceExists_mediaLoadedFromSource() async throws {
|
func test_whenLoadFileFromSourceAndNoFileFromSourceExists_mediaLoadedFromSource() async throws {
|
||||||
let expectedURL = try XCTUnwrap(URL(string: "some_url"))
|
let expectedURL = URL(filePath: "/some/file/path")
|
||||||
let expectedResult: Result<URL, MediaProviderError> = .success(expectedURL)
|
let expectedResult: Result<URL, MediaProviderError> = .success(expectedURL)
|
||||||
mediaProxy.mediaContentData = try loadTestImage().pngData()
|
mediaProxy.mediaContentData = try loadTestImage().pngData()
|
||||||
fileCache.storeURLToReturn = expectedURL
|
fileCache.storeURLToReturn = expectedURL
|
||||||
@@ -217,14 +217,14 @@ final class MediaProviderTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func test_whenFileFromURLString_correctURLIsReturned() throws {
|
func test_whenFileFromURLString_correctURLIsReturned() throws {
|
||||||
let expectedURL = try XCTUnwrap(URL(string: "some_url"))
|
let expectedURL = URL(filePath: "/some/file/path")
|
||||||
fileCache.fileURLToReturn = expectedURL
|
fileCache.fileURLToReturn = expectedURL
|
||||||
let url = mediaProvider.fileFromURLString("test/test1", fileExtension: "png")
|
let url = mediaProvider.fileFromURLString("test/test1", fileExtension: "png")
|
||||||
XCTAssertEqual(url?.absoluteString, expectedURL.absoluteString)
|
XCTAssertEqual(url?.absoluteString, expectedURL.absoluteString)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenLoadFileFromURLString_correctURLIsReturned() async throws {
|
func test_whenLoadFileFromURLString_correctURLIsReturned() async throws {
|
||||||
let expectedURL = try XCTUnwrap(URL(string: "some_url"))
|
let expectedURL = URL(filePath: "/some/file/path")
|
||||||
let expectedResult: Result<URL, MediaProviderError> = .success(expectedURL)
|
let expectedResult: Result<URL, MediaProviderError> = .success(expectedURL)
|
||||||
fileCache.fileURLToReturn = expectedURL
|
fileCache.fileURLToReturn = expectedURL
|
||||||
let result = await mediaProvider.loadFileFromURLString("test/test1", fileExtension: "png")
|
let result = await mediaProvider.loadFileFromURLString("test/test1", fileExtension: "png")
|
||||||
|
|||||||
@@ -1,44 +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 XCTest
|
|
||||||
|
|
||||||
@testable import ElementX
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
class VideoPlayerScreenViewModelTests: XCTestCase {
|
|
||||||
var viewModel: VideoPlayerViewModelProtocol!
|
|
||||||
var context: VideoPlayerViewModelType.Context!
|
|
||||||
|
|
||||||
@MainActor override func setUpWithError() throws {
|
|
||||||
viewModel = VideoPlayerViewModel(videoURL: URL(staticString: "https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"), autoplay: true)
|
|
||||||
context = viewModel.context
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor func testCancel() async throws {
|
|
||||||
var correctResult = false
|
|
||||||
viewModel.callback = { result in
|
|
||||||
switch result {
|
|
||||||
case .cancel:
|
|
||||||
correctResult = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.send(viewAction: .cancel)
|
|
||||||
await Task.yield()
|
|
||||||
XCTAssert(correctResult)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Use QuickLook previews for video and present previews full screen (doesn't address gestures yet).
|
||||||
Reference in New Issue
Block a user