Files
multi-simadmin/apps/ios/Sources/MultiSimAdmin/MultiSimAdminApp.swift
T
chick 0f2866a853 feat(ios): refine native interface and app icon
Unify bottom actions, selection controls, navigation structure, spacing, and theme colors across iOS pages. Replace the app icon with a higher-contrast native-style asset and include its source SVG.
2026-09-12 14:09:02 +08:00

115 lines
2.9 KiB
Swift

import SwiftUI
@main
struct MultiSimAdminApp: App {
@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-notifications") {
_tab = State(initialValue: .notifications)
} else if arguments.contains("--tab-logs") {
_tab = State(initialValue: .logs)
} else if arguments.contains("--tab-settings") {
_tab = State(initialValue: .settings)
} else {
_tab = State(initialValue: .fleet)
}
}
var body: some Scene {
WindowGroup {
VStack(spacing: 0) {
switch tab {
case .fleet:
NavigationStack { FleetView().aiInlineTitle() }
case .messages:
NavigationStack { MessagesView().aiInlineTitle() }
case .notifications:
NavigationStack { NotificationsView().aiInlineTitle() }
case .logs:
NavigationStack { LogsView().aiInlineTitle() }
case .settings:
NavigationStack { SettingsView().aiInlineTitle() }
}
AITabBar(selection: $tab)
}
.tint(AITheme.primary)
#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 notifications
case logs
case settings
}
struct AITabBar: View {
@Binding var selection: AppTab
var body: some View {
HStack(spacing: 0) {
tab(.fleet, "节点", "server.rack")
tab(.messages, "消息", "message")
tab(.notifications, "通知", "bell")
tab(.logs, "日志", "doc.text")
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] : [])
}
}