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) .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() } ) .background( EmptyView().sheet(isPresented: $navigation.presentingSettings) { SettingsView() } ) .modifier(ImportSettingsSheetViewModifier(isPresented: $navigation.presentingSettingsImportSheet, settingsFile: $navigation.settingsImportURL)) .background( EmptyView().sheet(isPresented: $navigation.presentingAccounts) { AccountsView() } ) .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() } }