WP-4a: menu-bar shell, AppModel, session strip per SPEC-A2b + integration contracts
This commit is contained in:
@@ -1,6 +1,75 @@
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
import ShotdeckCore
|
||||
|
||||
// WP-4 replaces this body with the real menu-bar UI.
|
||||
let application = NSApplication.shared
|
||||
application.setActivationPolicy(.accessory)
|
||||
application.run()
|
||||
// SwiftPM treats a file named main.swift as top-level code, which forbids `@main`.
|
||||
// App.main() is the equivalent entry point.
|
||||
ShotdeckApp.main()
|
||||
|
||||
struct ShotdeckApp: App {
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
|
||||
|
||||
var body: some Scene {
|
||||
MenuBarExtra {
|
||||
MenuBarView()
|
||||
.environment(appDelegate.model)
|
||||
} label: {
|
||||
let state = appDelegate.model.iconState
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: state.symbolName)
|
||||
if let count = state.countText {
|
||||
Text(count).font(.system(size: 11, weight: .semibold))
|
||||
}
|
||||
}
|
||||
.accessibilityLabel("Shotdeck")
|
||||
}
|
||||
.menuBarExtraStyle(.window)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
let model: AppModel
|
||||
|
||||
override init() {
|
||||
NSApplication.shared.setActivationPolicy(.accessory)
|
||||
model = AppDelegate.makeLaunchModel()
|
||||
super.init()
|
||||
}
|
||||
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
Task { await model.bootstrap() }
|
||||
}
|
||||
|
||||
private static func makeLaunchModel() -> AppModel {
|
||||
do {
|
||||
let paths = try FolderSettings.resolvedAppSupportPaths()
|
||||
return try makeModel(paths: paths)
|
||||
} catch {
|
||||
Log.ui.critical(
|
||||
"AppModel init failed: \(String(describing: error), privacy: .public)"
|
||||
)
|
||||
let tmp = FileManager.default.temporaryDirectory
|
||||
let fallbackRoot = tmp.appendingPathComponent("Shotdeck-fallback", isDirectory: true)
|
||||
// Safe: temp-dir creation for a path this process controls cannot legitimately fail.
|
||||
let fallback = try! AppSupportPaths(root: fallbackRoot, outbox: tmp, watchFolder: tmp)
|
||||
let model = try! makeModel(paths: fallback)
|
||||
model.setStatus("Shotdeck could not access its storage folder. Captures will not persist.")
|
||||
return model
|
||||
}
|
||||
}
|
||||
|
||||
private static func makeModel(paths: AppSupportPaths) throws -> AppModel {
|
||||
let ledger = try ReturnLedger(paths: paths)
|
||||
return AppModel(
|
||||
paths: paths,
|
||||
spool: try SpoolStore(paths: paths),
|
||||
composer: PDFComposer(),
|
||||
capturer: ScreenCapturer(),
|
||||
hotkeys: HotkeyCenter(),
|
||||
picker: RegionPickerController(),
|
||||
ledger: ledger,
|
||||
watcher: ReturnWatcher(paths: paths, ledger: ledger)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user