Files
yattee/Shared/Navigation/ContentView.swift
Arkadiusz Fal 0fcdf2398e Fix video player overlay to respect window fullscreen state on iOS
Change edgesIgnoringSafeArea from .all to conditional based on
Constants.isWindowFullscreen to properly handle safe areas when
not in fullscreen mode.
2025-11-15 11:30:30 +01:00

213 lines
7.0 KiB
Swift

import AVFAudio
import Defaults
import MediaPlayer
import SDWebImage
import SDWebImagePINPlugin
import SDWebImageWebPCoder
import Siesta
import SwiftUI
struct ContentView: View {
@ObservedObject private var navigation = NavigationModel.shared
@ObservedObject private var player = PlayerModel.shared
#if os(iOS)
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
#endif
@Default(.avPlayerUsesSystemControls) private var avPlayerUsesSystemControls
var body: some View {
GeometryReader { proxy in
Group {
#if os(iOS)
Group {
if Constants.isIPhone {
AppTabNavigation()
} else {
if horizontalSizeClass == .compact {
AppTabNavigation()
} else {
AppSidebarNavigation()
}
}
}
#elseif os(macOS)
AppSidebarNavigation()
#elseif os(tvOS)
TVNavigationView()
#endif
}
#if !os(macOS)
.onAppear {
SafeAreaModel.shared.safeArea = proxy.safeAreaInsets
}
.onChange(of: proxy.safeAreaInsets) { newValue in
SafeAreaModel.shared.safeArea = newValue
}
#endif
}
#if os(iOS)
.overlay(videoPlayer.edgesIgnoringSafeArea(Constants.isWindowFullscreen ? .init() : .all))
.sheet(isPresented: $navigation.presentingShareSheet) {
if let shareURL = navigation.shareURL {
ShareSheet(activityItems: [shareURL])
}
}
#endif
// iOS 14 has problem with multiple sheets in one view
// but it's ok when it's in background
.background(
EmptyView().sheet(isPresented: $navigation.presentingWelcomeScreen) {
WelcomeScreen()
}
)
#if os(tvOS)
.fullScreenCover(isPresented: $navigation.presentingSettings) {
SettingsView()
}
#else
.background(
EmptyView().sheet(isPresented: $navigation.presentingSettings) {
SettingsView()
}
)
#endif
.modifier(ImportSettingsSheetViewModifier(isPresented: $navigation.presentingSettingsImportSheet, settingsFile: $navigation.settingsImportURL))
#if os(tvOS)
.fullScreenCover(isPresented: $navigation.presentingAccounts) {
AccountsView()
}
#else
.background(
EmptyView().sheet(isPresented: $navigation.presentingAccounts) {
AccountsView()
}
)
#endif
.background(
EmptyView().sheet(isPresented: $navigation.presentingHomeSettings) {
#if os(macOS)
VStack(alignment: .leading) {
Button("Done") {
navigation.presentingHomeSettings = false
}
.padding()
.keyboardShortcut(.cancelAction)
HomeSettings()
}
.frame(width: 500, height: 800)
#else
NavigationView {
HomeSettings()
#if os(iOS)
.toolbar {
ToolbarItem(placement: .navigation) {
Button {
navigation.presentingHomeSettings = false
} label: {
Text("Done")
}
}
}
#endif
}
#endif
}
)
#if !os(tvOS)
.fileImporter(
isPresented: $navigation.presentingFileImporter,
allowedContentTypes: [.audiovisualContent],
allowsMultipleSelection: true
) { result in
do {
let selectedFiles = try result.get()
let urlsToOpen = selectedFiles.map { url in
if let bookmarkURL = URLBookmarkModel.shared.loadBookmark(url) {
return bookmarkURL
}
if url.startAccessingSecurityScopedResource() {
URLBookmarkModel.shared.saveBookmark(url)
}
return url
}
OpenVideosModel.shared.openURLs(urlsToOpen)
} catch {
NavigationModel.shared.presentAlert(title: "Could not open Files")
}
NavigationModel.shared.presentingOpenVideos = false
}
.background(
EmptyView().sheet(isPresented: $navigation.presentingAddToPlaylist) {
AddToPlaylistView(video: navigation.videoToAddToPlaylist)
}
)
.background(
EmptyView().sheet(isPresented: $navigation.presentingPlaylistForm) {
PlaylistFormView(playlist: $navigation.editedPlaylist)
}
)
#endif
#if os(iOS)
.background(
EmptyView().sheet(isPresented: $navigation.presentingPlaybackSettings) {
PlaybackSettings()
}
)
#endif
.background(
EmptyView().sheet(isPresented: $navigation.presentingOpenVideos) {
OpenVideosView()
}
)
#if !os(macOS)
.background(
EmptyView().sheet(isPresented: $navigation.presentingChannelSheet) {
NavigationView {
ChannelVideosView(channel: navigation.channelPresentedInSheet, showCloseButton: true)
}
}
)
#endif
.alert(isPresented: $navigation.presentingAlert) { navigation.alert }
#if os(iOS)
.statusBarHidden(player.playingFullScreen)
#endif
#if os(macOS)
.frame(minWidth: 1200, minHeight: 600)
#endif
}
@ViewBuilder var videoPlayer: some View {
if player.presentingPlayer {
playerView
.transition(.asymmetric(insertion: .identity, removal: .opacity))
.zIndex(3)
} else if player.activeBackend == .appleAVPlayer,
avPlayerUsesSystemControls || player.avPlayerBackend.isStartingPiP
{
#if os(iOS)
AppleAVPlayerLayerView().offset(y: UIScreen.main.bounds.height)
#endif
}
}
var playerView: some View {
VideoPlayerView()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.injectFixtureEnvironmentObjects()
}
}