Files
ten31-transcripts/Ten31Transcripts/Settings/AppSettings.swift
T
Grant Gilliam b2ae3a62b9 Phase 0: menu-bar scaffold, permissions, backend health check
Native SwiftUI menu-bar app (LSUIElement, macOS 13+), generated from project.yml
via XcodeGen. Includes:
- PermissionsManager (Microphone / Screen Recording / Accessibility) + UI
- SparkControlHealth: GET /api/status over self-signed TLS (InsecureTrustDelegate)
- AppSettings persistence (host, TLS-skip, output folder, adapter toggles)
- Menu-bar panel + Settings, app sandbox & hardened runtime off (LAN tool)
2026-06-05 19:33:53 -05:00

67 lines
2.2 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Foundation
import Combine
/// User-facing settings, persisted to `UserDefaults`.
///
/// Phase 0 scope: backend host + TLS-skip, output folder, and adapter toggles.
/// The adapter toggles persist but do nothing yet (adapters arrive in Phase 34).
@MainActor
final class AppSettings: ObservableObject {
/// Adapters the app will eventually run, in display order.
static let adapterKeys: [(key: String, label: String)] = [
("zoom", "Zoom"),
("teams", "Microsoft Teams"),
("signal", "Signal"),
("meet", "Google Meet"),
]
@Published var backendBaseURL: String {
didSet { defaults.set(backendBaseURL, forKey: Keys.backendBaseURL) }
}
@Published var skipTLSVerification: Bool {
didSet { defaults.set(skipTLSVerification, forKey: Keys.skipTLS) }
}
@Published var outputFolderPath: String {
didSet { defaults.set(outputFolderPath, forKey: Keys.outputFolder) }
}
@Published var adapterEnabled: [String: Bool] {
didSet { defaults.set(adapterEnabled, forKey: Keys.adapterEnabled) }
}
/// Output folder as a resolved file URL (expands a leading `~`).
var outputFolderURL: URL {
URL(fileURLWithPath: (outputFolderPath as NSString).expandingTildeInPath,
isDirectory: true)
}
private let defaults: UserDefaults
init(defaults: UserDefaults = .standard) {
self.defaults = defaults
self.backendBaseURL = defaults.string(forKey: Keys.backendBaseURL)
?? "https://your-spark-backend.local:62419"
self.skipTLSVerification = defaults.object(forKey: Keys.skipTLS) as? Bool ?? true
self.outputFolderPath = defaults.string(forKey: Keys.outputFolder)
?? "~/Ten31Transcripts"
let stored = defaults.dictionary(forKey: Keys.adapterEnabled) as? [String: Bool]
self.adapterEnabled = stored ?? Dictionary(
uniqueKeysWithValues: Self.adapterKeys.map { ($0.key, true) }
)
}
private enum Keys {
static let backendBaseURL = "backendBaseURL"
static let skipTLS = "skipTLSVerification"
static let outputFolder = "outputFolderPath"
static let adapterEnabled = "adapterEnabled"
}
}