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

52 lines
1.5 KiB
Swift

import Foundation
/// A text-expansion snippet: type a short trigger, get a longer expansion.
struct Snippet: Codable, Identifiable, Equatable {
var id = UUID()
var trigger: String
var expansion: String
}
/// Local store for text-expansion snippets (a paid feature). Persisted to disk;
/// snippet contents never leave the device.
@MainActor
final class SnippetStore: ObservableObject {
@Published private(set) var snippets: [Snippet]
private let key = "GrammarGem.snippets"
private let d = UserDefaults.standard
init() {
if let raw = d.data(forKey: key),
let decoded = try? JSONDecoder().decode([Snippet].self, from: raw) {
snippets = decoded
} else {
snippets = []
}
}
func add(trigger: String, expansion: String) {
let t = trigger.trimmingCharacters(in: .whitespaces)
let e = expansion.trimmingCharacters(in: .whitespacesAndNewlines)
guard !t.isEmpty, !e.isEmpty else { return }
snippets.append(Snippet(trigger: t, expansion: e))
persist()
}
func remove(_ snippet: Snippet) {
snippets.removeAll { $0.id == snippet.id }
persist()
}
/// Resolve a trigger to its expansion (used by the snippet hotkey path).
func expansion(for trigger: String) -> String? {
snippets.first { $0.trigger == trigger }?.expansion
}
private func persist() {
if let raw = try? JSONEncoder().encode(snippets) {
d.set(raw, forKey: key)
}
}
}