grammargem/Sources/GrammarGem/AI/CustomModesStore.swift
BigMarc e5b0977abf f
2026-06-18 16:49:59 +02:00

72 lines
2.3 KiB
Swift

import Foundation
/// User-created Writing Modes (paid) plus per-app Mode overrides for App-Aware
/// switching. Persisted locally; the built-in modes live in `ModeRegistry`.
@MainActor
final class CustomModesStore: ObservableObject {
@Published private(set) var customModes: [WritingMode]
/// bundleID -> mode id (overrides the default App-Aware mapping).
@Published private(set) var appOverrides: [String: String]
private let modesKey = "GrammarGem.customModes"
private let mapKey = "GrammarGem.appModeOverrides"
private let d = UserDefaults.standard
init() {
if let raw = d.data(forKey: modesKey),
let decoded = try? JSONDecoder().decode([WritingMode].self, from: raw) {
customModes = decoded
} else {
customModes = []
}
appOverrides = (d.dictionary(forKey: mapKey) as? [String: String]) ?? [:]
}
/// Built-in + custom modes (custom ones are always paid).
func allModes() -> [WritingMode] { ModeRegistry.all + customModes }
func addCustom(name: String, prompt: String) {
let trimmed = name.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return }
let mode = WritingMode(
id: "custom-\(UUID().uuidString.prefix(8))",
name: trimmed,
systemPrompt: prompt.trimmingCharacters(in: .whitespacesAndNewlines),
isPaid: true,
lengthCap: nil,
autoFormat: "Custom"
)
customModes.append(mode)
persistModes()
}
func removeCustom(id: String) {
customModes.removeAll { $0.id == id }
appOverrides = appOverrides.filter { $0.value != id }
persistModes()
persistMap()
}
func setOverride(bundleID: String, modeID: String) {
let b = bundleID.trimmingCharacters(in: .whitespaces)
guard !b.isEmpty else { return }
appOverrides[b] = modeID
persistMap()
}
func clearOverride(bundleID: String) {
appOverrides.removeValue(forKey: bundleID)
persistMap()
}
private func persistModes() {
if let raw = try? JSONEncoder().encode(customModes) {
d.set(raw, forKey: modesKey)
}
}
private func persistMap() {
d.set(appOverrides, forKey: mapKey)
}
}