import Defaults import SwiftUI #if os(iOS) import Introspect #endif struct AppSidebarNavigation: View { @EnvironmentObject private var accounts @EnvironmentObject private var comments @EnvironmentObject private var instances @EnvironmentObject private var navigation @EnvironmentObject private var player @EnvironmentObject private var playlists @EnvironmentObject private var recents @EnvironmentObject private var search @EnvironmentObject private var subscriptions @EnvironmentObject private var thumbnailsModel @Default(.visibleSections) private var visibleSections #if os(iOS) @State private var didApplyPrimaryViewWorkAround = false #endif var body: some View { #if os(iOS) content.introspectViewController { viewController in // workaround for an empty supplementary view on launch // the supplementary view is determined by the default selection inside the // primary view, but the primary view is not loaded so its selection is not read // We work around that by showing the primary view if !didApplyPrimaryViewWorkAround, let splitVC = viewController.children.first as? UISplitViewController { UIView.performWithoutAnimation { splitVC.show(.primary) } didApplyPrimaryViewWorkAround = true } } #else content #endif } let sidebarMinWidth: Double = 280 var content: some View { NavigationView { Sidebar() .toolbar { toolbarContent } .frame(minWidth: sidebarMinWidth) VStack { PlayerControlsView { HStack(alignment: .center) { Spacer() Image(systemName: "play.tv") .renderingMode(.original) .font(.system(size: 60)) .foregroundColor(.accentColor) Spacer() } } } } #if os(iOS) .background( EmptyView().fullScreenCover(isPresented: $player.presentingPlayer) { videoPlayer .environment(\.navigationStyle, .sidebar) } ) #elseif os(macOS) .background( EmptyView().sheet(isPresented: $player.presentingPlayer) { videoPlayer .frame(minWidth: 1000, minHeight: 750) .environment(\.navigationStyle, .sidebar) } ) #endif .environment(\.navigationStyle, .sidebar) } private var videoPlayer: some View { VideoPlayerView() .environmentObject(accounts) .environmentObject(comments) .environmentObject(instances) .environmentObject(navigation) .environmentObject(player) .environmentObject(playlists) .environmentObject(recents) .environmentObject(subscriptions) .environmentObject(thumbnailsModel) } var toolbarContent: some ToolbarContent { Group { #if os(iOS) ToolbarItemGroup(placement: .navigationBarTrailing) { Button(action: { navigation.presentingSettings = true }) { Image(systemName: "gearshape.2") } } #endif ToolbarItem(placement: accountsMenuToolbarItemPlacement) { AccountsMenuView() .help( "Switch Instances and Accounts\n" + "Current Instance: \n" + "\(accounts.current?.url ?? "Not Set")\n" + "Current User: \(accounts.current?.description ?? "Not set")" ) } } } var accountsMenuToolbarItemPlacement: ToolbarItemPlacement { #if os(iOS) return .bottomBar #else return .automatic #endif } static func symbolSystemImage(_ name: String) -> String { let firstLetter = name.first?.lowercased() let regex = #"^[a-z0-9]$"# let symbolName = firstLetter?.range(of: regex, options: .regularExpression) != nil ? firstLetter! : "questionmark" return "\(symbolName).circle" } }