import SwiftUI @main struct MultiSimAdminApp: App { @StateObject private var themeStore = ThemeStore.shared @State private var tab: AppTab init() { let arguments = ProcessInfo.processInfo.arguments if arguments.contains("--tab-messages") { _tab = State(initialValue: .messages) } else if arguments.contains("--tab-settings") { _tab = State(initialValue: .settings) } else { _tab = State(initialValue: .fleet) } } var body: some Scene { WindowGroup { Group { switch tab { case .fleet: NavigationStack { FleetView().aiInlineTitle() } case .messages: NavigationStack { MessagesView().aiInlineTitle() } case .settings: NavigationStack { SettingsView().aiInlineTitle() } } } .safeAreaInset(edge: .bottom, spacing: 0) { AITabBar(selection: $tab) } .tint(AITheme.primary) .preferredColorScheme(themeStore.mode.colorScheme) #if os(iOS) .toolbarBackground(.ultraThinMaterial, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar) #endif } } } #if os(iOS) extension View { fileprivate func aiInlineTitle() -> some View { navigationBarTitleDisplayMode(.inline) } } #else extension View { fileprivate func aiInlineTitle() -> some View { self } } #endif enum AppTab: Hashable { case fleet case messages case settings } struct AITabBar: View { @Binding var selection: AppTab var body: some View { HStack(spacing: 0) { tab(.fleet, "节点", "server.rack") tab(.messages, "消息", "message") tab(.settings, "设置", "gearshape") } .frame(height: 62) .background { ZStack { Rectangle() .fill(.ultraThinMaterial) Rectangle() .fill(AITheme.chrome) } .ignoresSafeArea(edges: .bottom) } .overlay(alignment: .top) { Rectangle() .fill(AITheme.line) .frame(height: 1) } } private func tab(_ value: AppTab, _ title: String, _ systemImage: String) -> some View { let isSelected = selection == value return Button { selection = value } label: { VStack(spacing: 4) { Image(systemName: systemImage) .font(.system(size: 18, weight: .semibold)) Text(title) .font(.caption2.weight(.semibold)) } .foregroundStyle(isSelected ? AITheme.primary : AITheme.muted) .frame(maxWidth: .infinity, maxHeight: .infinity) } .buttonStyle(.plain) .accessibilityLabel(title) .accessibilityAddTraits(isSelected ? [.isSelected] : []) } }