feat(app): wire up appearance setting and app menu commands
AppAppearance (System/Light/Dark) applies via NSApp.appearance directly rather than .preferredColorScheme(nil) — the latter doesn't reliably reset a macOS window back to "follow system" after an explicit override. App menu gets About/Log Out commands and the About/Keyboard Shortcuts/Preferences windows registered as scenes.
This commit is contained in:
+70
-14
@@ -6,27 +6,83 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import SwiftData
|
|
||||||
|
#if os(macOS)
|
||||||
|
import AppKit
|
||||||
|
#endif
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct OutpostApp: App {
|
struct OutpostApp: App {
|
||||||
var sharedModelContainer: ModelContainer = {
|
@State private var session = SessionStore()
|
||||||
let schema = Schema([
|
@AppStorage("outpost.appearance") private var appearance: AppAppearance = .system
|
||||||
Item.self,
|
|
||||||
])
|
|
||||||
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
|
|
||||||
|
|
||||||
do {
|
#if os(macOS)
|
||||||
return try ModelContainer(for: schema, configurations: [modelConfiguration])
|
@Environment(\.openWindow) private var openWindow
|
||||||
} catch {
|
@State private var isShowingLogoutConfirmation = false
|
||||||
fatalError("Could not create ModelContainer: \(error)")
|
#endif
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
RootView()
|
||||||
|
.environment(session)
|
||||||
|
#if os(iOS)
|
||||||
|
.preferredColorScheme(appearance.colorScheme)
|
||||||
|
#endif
|
||||||
|
#if os(macOS)
|
||||||
|
.onAppear { applyMacAppearance() }
|
||||||
|
.onChange(of: appearance) { _, _ in applyMacAppearance() }
|
||||||
|
.logoutConfirmationDialog(isPresented: $isShowingLogoutConfirmation, session: session)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
.modelContainer(sharedModelContainer)
|
#if os(macOS)
|
||||||
|
.commands {
|
||||||
|
CommandGroup(replacing: .appInfo) {
|
||||||
|
Button("About Outpost") {
|
||||||
|
openWindow(id: "about")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CommandGroup(after: .appSettings) {
|
||||||
|
Divider()
|
||||||
|
Button("Log Out…") {
|
||||||
|
isShowingLogoutConfirmation = true
|
||||||
|
}
|
||||||
|
.disabled(!session.isSignedIn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
Window("About Outpost", id: "about") {
|
||||||
|
AboutView()
|
||||||
|
}
|
||||||
|
.windowResizability(.contentSize)
|
||||||
|
|
||||||
|
Window("Keyboard Shortcuts", id: "keyboard-shortcuts") {
|
||||||
|
KeyboardShortcutsView()
|
||||||
|
}
|
||||||
|
.windowResizability(.contentSize)
|
||||||
|
|
||||||
|
Settings {
|
||||||
|
PreferencesView()
|
||||||
|
.environment(session)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
/// `.preferredColorScheme(nil)` doesn't reliably reset the window's real
|
||||||
|
/// `NSAppearance` back to "follow system" after an explicit override — this
|
||||||
|
/// sets the actual AppKit-level appearance directly instead, which every
|
||||||
|
/// window (present and future) inherits.
|
||||||
|
private func applyMacAppearance() {
|
||||||
|
switch appearance {
|
||||||
|
case .system:
|
||||||
|
NSApp.appearance = nil
|
||||||
|
case .light:
|
||||||
|
NSApp.appearance = NSAppearance(named: .aqua)
|
||||||
|
case .dark:
|
||||||
|
NSApp.appearance = NSAppearance(named: .darkAqua)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
enum AppAppearance: String, CaseIterable, Identifiable {
|
||||||
|
case system, light, dark
|
||||||
|
|
||||||
|
var id: String { rawValue }
|
||||||
|
|
||||||
|
var label: String {
|
||||||
|
switch self {
|
||||||
|
case .system: return "System"
|
||||||
|
case .light: return "Light"
|
||||||
|
case .dark: return "Dark"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var colorScheme: ColorScheme? {
|
||||||
|
switch self {
|
||||||
|
case .system: return nil
|
||||||
|
case .light: return .light
|
||||||
|
case .dark: return .dark
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user