diff --git a/IceCubesApp/App/Main/IceCubesApp+Scene.swift b/IceCubesApp/App/Main/IceCubesApp+Scene.swift index d9ec12d1..6e314187 100644 --- a/IceCubesApp/App/Main/IceCubesApp+Scene.swift +++ b/IceCubesApp/App/Main/IceCubesApp+Scene.swift @@ -100,6 +100,7 @@ extension IceCubesApp { } } .withEnvironments() + .environment(\.isCatalystWindow, true) .environment(RouterPath()) .withModelContainer() .applyTheme(theme) @@ -121,6 +122,7 @@ extension IceCubesApp { .withEnvironments() .withModelContainer() .applyTheme(theme) + .environment(\.isCatalystWindow, true) .frame(minWidth: 300, minHeight: 400) } .defaultSize(width: 1200, height: 1000) diff --git a/Packages/Env/Sources/Env/CustomEnvValues.swift b/Packages/Env/Sources/Env/CustomEnvValues.swift index cbf4cda7..c4826b96 100644 --- a/Packages/Env/Sources/Env/CustomEnvValues.swift +++ b/Packages/Env/Sources/Env/CustomEnvValues.swift @@ -6,6 +6,7 @@ extension EnvironmentValues { @Entry public var extraLeadingInset: CGFloat = 0 @Entry public var isCompact: Bool = false @Entry public var isMediaCompact: Bool = false + @Entry public var isCatalystWindow: Bool = false @Entry public var isModal: Bool = false @Entry public var isInCaptureMode: Bool = false @Entry public var isSupporter: Bool = false diff --git a/Packages/MediaUI/Sources/MediaUI/MediaUIAttachmentVideoView.swift b/Packages/MediaUI/Sources/MediaUI/MediaUIAttachmentVideoView.swift index b23a11b9..b023209a 100644 --- a/Packages/MediaUI/Sources/MediaUI/MediaUIAttachmentVideoView.swift +++ b/Packages/MediaUI/Sources/MediaUI/MediaUIAttachmentVideoView.swift @@ -83,6 +83,7 @@ import SwiftUI public struct MediaUIAttachmentVideoView: View { @Environment(\.openWindow) private var openWindow @Environment(\.scenePhase) private var scenePhase + @Environment(\.isCatalystWindow) private var isCatalystWindow @Environment(\.isMediaCompact) private var isCompact @Environment(UserPreferences.self) private var preferences @Environment(Theme.self) private var theme @@ -96,6 +97,28 @@ public struct MediaUIAttachmentVideoView: View { public var body: some View { videoView + .overlay(content: { + if isCatalystWindow { + EmptyView() + } else { + HStack { } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .contentShape(Rectangle()) + .onTapGesture { + if !preferences.autoPlayVideo && !viewModel.isPlaying { + viewModel.play() + return + } + #if targetEnvironment(macCatalyst) + viewModel.pause() + let attachement = MediaAttachment.videoWith(url: viewModel.url) + openWindow(value: WindowDestinationMedia.mediaViewer(attachments: [attachement], selectedAttachment: attachement)) + #else + isFullScreen = true + #endif + } + } + }) .onAppear { viewModel.preparePlayer(autoPlay: isFullScreen ? true : preferences.autoPlayVideo, isCompact: isCompact) @@ -104,59 +127,8 @@ public struct MediaUIAttachmentVideoView: View { .onDisappear { viewModel.stop() } - .onTapGesture { - if !preferences.autoPlayVideo && !viewModel.isPlaying { - viewModel.play() - return - } - #if targetEnvironment(macCatalyst) - viewModel.pause() - let attachement = MediaAttachment.videoWith(url: viewModel.url) - openWindow(value: WindowDestinationMedia.mediaViewer(attachments: [attachement], selectedAttachment: attachement)) - #else - isFullScreen = true - #endif - } .fullScreenCover(isPresented: $isFullScreen) { - NavigationStack { - videoView - .toolbar { - ToolbarItem(placement: .topBarLeading) { - Button { isFullScreen.toggle() } label: { - Image(systemName: "xmark.circle") - } - } - QuickLookToolbarItem(itemUrl: viewModel.url) - } - } - .onAppear { - DispatchQueue.global().async { - try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) - try? AVAudioSession.sharedInstance().setCategory(.playback, options: .duckOthers) - try? AVAudioSession.sharedInstance().setActive(true) - } - viewModel.preventSleep(true) - viewModel.mute(false) - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { - if isCompact || !preferences.autoPlayVideo { - viewModel.play() - } else { - viewModel.resume() - } - } - } - .onDisappear { - if isCompact || !preferences.autoPlayVideo { - viewModel.pause() - } - viewModel.preventSleep(false) - viewModel.mute(preferences.muteVideo) - DispatchQueue.global().async { - try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) - try? AVAudioSession.sharedInstance().setCategory(.ambient, options: .mixWithOthers) - try? AVAudioSession.sharedInstance().setActive(true) - } - } + modalPreview } .cornerRadius(4) .onChange(of: scenePhase) { _, newValue in @@ -172,6 +144,48 @@ public struct MediaUIAttachmentVideoView: View { } } } + + private var modalPreview: some View { + NavigationStack { + videoView + .toolbar { + ToolbarItem(placement: .topBarLeading) { + Button { isFullScreen.toggle() } label: { + Image(systemName: "xmark.circle") + } + } + QuickLookToolbarItem(itemUrl: viewModel.url) + } + } + .onAppear { + DispatchQueue.global().async { + try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) + try? AVAudioSession.sharedInstance().setCategory(.playback, options: .duckOthers) + try? AVAudioSession.sharedInstance().setActive(true) + } + viewModel.preventSleep(true) + viewModel.mute(false) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + if isCompact || !preferences.autoPlayVideo { + viewModel.play() + } else { + viewModel.resume() + } + } + } + .onDisappear { + if isCompact || !preferences.autoPlayVideo { + viewModel.pause() + } + viewModel.preventSleep(false) + viewModel.mute(preferences.muteVideo) + DispatchQueue.global().async { + try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) + try? AVAudioSession.sharedInstance().setCategory(.ambient, options: .mixWithOthers) + try? AVAudioSession.sharedInstance().setActive(true) + } + } + } private var videoView: some View { VideoPlayer(player: viewModel.player, videoOverlay: { @@ -194,5 +208,6 @@ public struct MediaUIAttachmentVideoView: View { } }) .accessibilityAddTraits(.startsMediaSession) + .ignoresSafeArea() } }