import Foundation import Libbox import Library import SwiftUI @MainActor public struct ActiveDashboardView: View { @Environment(\.scenePhase) private var scenePhase @EnvironmentObject private var environments: ExtensionEnvironments @EnvironmentObject private var profile: ExtensionProfile @StateObject private var coordinator = DashboardCoordinator() @State private var cardConfigurationVersion = 0 #if os(iOS) || os(tvOS) @State private var showCardManagement = false @State private var showGroups = false @State private var showConnections = false @State private var buttonState = ButtonVisibilityState() #endif private let externalCardConfigurationVersion: Int? public init(externalCardConfigurationVersion: Int? = nil) { self.externalCardConfigurationVersion = externalCardConfigurationVersion } public var body: some View { if coordinator.isLoading { ProgressView() .onAppear { coordinator.onEmptyProfilesChange = { environments.emptyProfiles = $0 } Task { await coordinator.reload() } } } else { content .onAppear { guard !ApplicationLibrary.inPreview else { return } Task { await coordinator.reloadSystemProxy() } } .onChangeCompat(of: profile.status) { status in guard !ApplicationLibrary.inPreview, status == .connected else { return } Task { await coordinator.reloadSystemProxy() } } } } @ViewBuilder private var content: some View { overviewPage #if os(iOS) || os(tvOS) .toolbar { toolbar } .sheet(isPresented: $showGroups) { groupsSheetContent } .sheet(isPresented: $showConnections) { connectionsSheetContent } #endif .onAppear { if ApplicationLibrary.inPreview { environments.commandClient.connect() } else { environments.connect() } } .onChangeCompat(of: scenePhase) { phase in guard phase == .active else { return } environments.connect() } .onChangeCompat(of: profile.status) { status in guard status.isConnected else { return } environments.connect() } .onReceive(environments.profileUpdate) { _ in Task { await coordinator.reload() } } .onReceive(environments.selectedProfileUpdate) { _ in Task { await coordinator.updateSelectedProfile() if profile.status.isConnected { await coordinator.reloadSystemProxy() } } } #if os(iOS) || os(tvOS) .onReceive(environments.commandClient.$groups) { _ in updateButtonVisibility() } .onReceive(environments.commandClient.$connections) { _ in updateButtonVisibility() } .onReceive(profile.$status) { _ in updateButtonVisibility() } .onAppear { updateButtonVisibility() } #endif .alertBinding($coordinator.alert) } @ViewBuilder private var overviewPage: some View { OverviewView( $coordinator.profileList, $coordinator.selectedProfileID, $coordinator.systemProxyAvailable, $coordinator.systemProxyEnabled, cardConfigurationVersion: externalCardConfigurationVersion ?? cardConfigurationVersion ) } #if os(iOS) || os(tvOS) private func updateButtonVisibility() { buttonState.update(profile: profile, commandClient: environments.commandClient) } @ToolbarContentBuilder private var toolbar: some ToolbarContent { ToolbarItem(placement: .topBarLeading) { #if os(iOS) if #available(iOS 26.0, *), !Variant.debugNoIOS26 { EmptyView() } else { navigationButtons } #else navigationButtons #endif } ToolbarItem(placement: .topBarTrailing) { if #available(iOS 16.0, tvOS 17.0, *) { cardManagementButton } } ToolbarItem(placement: .topBarTrailing) { #if os(iOS) if #available(iOS 26.0, *), !Variant.debugNoIOS26 { EmptyView() } else { HStack(spacing: 12) { Divider() StartStopButton() } } #else HStack(spacing: 12) { Divider() StartStopButton() } #endif } } private var navigationButtons: some View { NavigationButtonsView( showGroupsButton: buttonState.showGroupsButton, showConnectionsButton: buttonState.showConnectionsButton, groupsCount: buttonState.groupsCount, connectionsCount: buttonState.connectionsCount, onGroupsTap: { showGroups = true }, onConnectionsTap: { showConnections = true } ) } #endif #if os(iOS) || os(tvOS) private var groupsSheetContent: some View { GroupsSheetContent() } private var connectionsSheetContent: some View { ConnectionsSheetContent() } @available(iOS 16.0, tvOS 17.0, *) @ViewBuilder private var cardManagementButton: some View { Menu { Button { showCardManagement = true } label: { Label("Dashboard Items", systemImage: "square.grid.2x2") } } label: { Label("Others", systemImage: "ellipsis.circle") } .sheet(isPresented: $showCardManagement) { CardManagementSheet(configurationVersion: $cardConfigurationVersion) .presentationDetents([.large]) .presentationDragIndicator(.visible) } } #endif }