139 lines
4.1 KiB
Swift
139 lines
4.1 KiB
Swift
import SwiftUI
|
|
import Cocoa
|
|
|
|
enum ThemeMode: String, CaseIterable {
|
|
case auto = "auto"
|
|
case dark = "dark"
|
|
case light = "light"
|
|
|
|
var label: String {
|
|
switch self {
|
|
case .auto: return "Auto"
|
|
case .dark: return "Dark"
|
|
case .light: return "Light"
|
|
}
|
|
}
|
|
}
|
|
|
|
enum LineIndicatorMode: String, CaseIterable {
|
|
case on = "on"
|
|
case off = "off"
|
|
case vim = "vim"
|
|
|
|
var label: String {
|
|
switch self {
|
|
case .on: return "On"
|
|
case .off: return "Off"
|
|
case .vim: return "Vim"
|
|
}
|
|
}
|
|
}
|
|
|
|
struct SettingsView: View {
|
|
@State private var themeMode: String = ConfigManager.shared.themeMode
|
|
@State private var lineIndicatorMode: String = ConfigManager.shared.lineIndicatorMode
|
|
@State private var autoSaveDir: String = ConfigManager.shared.autoSaveDirectory
|
|
|
|
var body: some View {
|
|
let palette = Theme.current
|
|
Form {
|
|
Section("Theme") {
|
|
Picker("Mode", selection: $themeMode) {
|
|
ForEach(ThemeMode.allCases, id: \.rawValue) { mode in
|
|
Text(mode.label).tag(mode.rawValue)
|
|
}
|
|
}
|
|
.pickerStyle(.segmented)
|
|
}
|
|
|
|
Section("Line Numbers") {
|
|
Picker("Mode", selection: $lineIndicatorMode) {
|
|
ForEach(LineIndicatorMode.allCases, id: \.rawValue) { mode in
|
|
Text(mode.label).tag(mode.rawValue)
|
|
}
|
|
}
|
|
.pickerStyle(.segmented)
|
|
}
|
|
|
|
Section("Auto-Save") {
|
|
HStack {
|
|
TextField("Directory", text: $autoSaveDir)
|
|
.textFieldStyle(.roundedBorder)
|
|
Button("Choose...") {
|
|
let panel = NSOpenPanel()
|
|
panel.canChooseFiles = false
|
|
panel.canChooseDirectories = true
|
|
panel.allowsMultipleSelection = false
|
|
if panel.runModal() == .OK, let url = panel.url {
|
|
autoSaveDir = url.path
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.formStyle(.grouped)
|
|
.frame(width: 400, height: 260)
|
|
.background(Color(ns: palette.base))
|
|
.onChange(of: themeMode) {
|
|
ConfigManager.shared.themeMode = themeMode
|
|
DispatchQueue.main.async {
|
|
applyThemeAppearance()
|
|
NotificationCenter.default.post(name: .settingsChanged, object: nil)
|
|
}
|
|
}
|
|
.onChange(of: lineIndicatorMode) {
|
|
ConfigManager.shared.lineIndicatorMode = lineIndicatorMode
|
|
DispatchQueue.main.async {
|
|
NotificationCenter.default.post(name: .settingsChanged, object: nil)
|
|
}
|
|
}
|
|
.onChange(of: autoSaveDir) {
|
|
ConfigManager.shared.autoSaveDirectory = autoSaveDir
|
|
}
|
|
}
|
|
}
|
|
|
|
func applyThemeAppearance() {
|
|
let mode = ConfigManager.shared.themeMode
|
|
switch mode {
|
|
case "dark":
|
|
NSApp.appearance = NSAppearance(named: .darkAqua)
|
|
case "light":
|
|
NSApp.appearance = NSAppearance(named: .aqua)
|
|
default:
|
|
NSApp.appearance = nil
|
|
}
|
|
}
|
|
|
|
extension Notification.Name {
|
|
static let settingsChanged = Notification.Name("settingsChanged")
|
|
}
|
|
|
|
class SettingsWindowController {
|
|
private static var window: NSWindow?
|
|
|
|
static func show() {
|
|
if let existing = window, existing.isVisible {
|
|
existing.makeKeyAndOrderFront(nil)
|
|
return
|
|
}
|
|
|
|
let settingsView = SettingsView()
|
|
let hostingView = NSHostingView(rootView: settingsView)
|
|
hostingView.frame = NSRect(x: 0, y: 0, width: 400, height: 280)
|
|
|
|
let w = NSWindow(
|
|
contentRect: NSRect(x: 0, y: 0, width: 400, height: 280),
|
|
styleMask: [.titled, .closable],
|
|
backing: .buffered,
|
|
defer: false
|
|
)
|
|
w.title = "Settings"
|
|
w.contentView = hostingView
|
|
w.center()
|
|
w.isReleasedWhenClosed = false
|
|
w.makeKeyAndOrderFront(nil)
|
|
window = w
|
|
}
|
|
}
|