mirror of
https://github.com/carey314/mio-plugin-clipper.git
synced 2026-08-10 07:44:32 +00:00
61 lines
1.9 KiB
Swift
61 lines
1.9 KiB
Swift
|
|
//
|
||
|
|
// HistoryStore.swift
|
||
|
|
// 划词侠 plugin
|
||
|
|
//
|
||
|
|
// Persists last 20 actions in UserDefaults under a single JSON key.
|
||
|
|
// Cheap, durable, no external deps. Records actionLabel + input
|
||
|
|
// preview + output preview + timestamp.
|
||
|
|
//
|
||
|
|
|
||
|
|
import Foundation
|
||
|
|
|
||
|
|
struct HistoryEntry: Codable, Identifiable, Equatable {
|
||
|
|
var id: UUID
|
||
|
|
var actionLabel: String // e.g. "翻译·中文" / "总结" / "改语气·正式"
|
||
|
|
var inputPreview: String // truncated to 80 chars
|
||
|
|
var outputPreview: String // truncated to 120 chars
|
||
|
|
var timestamp: Date
|
||
|
|
|
||
|
|
init(id: UUID = UUID(),
|
||
|
|
actionLabel: String,
|
||
|
|
inputPreview: String,
|
||
|
|
outputPreview: String,
|
||
|
|
timestamp: Date = Date()) {
|
||
|
|
self.id = id
|
||
|
|
self.actionLabel = actionLabel
|
||
|
|
self.inputPreview = inputPreview
|
||
|
|
self.outputPreview = outputPreview
|
||
|
|
self.timestamp = timestamp
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
enum HistoryStore {
|
||
|
|
private static let key = "com.mioisland.plugin.clipper.history.v1"
|
||
|
|
private static let maxEntries = 20
|
||
|
|
|
||
|
|
static func load() -> [HistoryEntry] {
|
||
|
|
guard let data = UserDefaults.standard.data(forKey: key) else { return [] }
|
||
|
|
return (try? JSONDecoder().decode([HistoryEntry].self, from: data)) ?? []
|
||
|
|
}
|
||
|
|
|
||
|
|
static func save(_ entries: [HistoryEntry]) {
|
||
|
|
guard let data = try? JSONEncoder().encode(entries) else { return }
|
||
|
|
UserDefaults.standard.set(data, forKey: key)
|
||
|
|
}
|
||
|
|
|
||
|
|
static func append(_ entry: HistoryEntry) -> [HistoryEntry] {
|
||
|
|
var list = load()
|
||
|
|
list.insert(entry, at: 0)
|
||
|
|
if list.count > maxEntries { list = Array(list.prefix(maxEntries)) }
|
||
|
|
save(list)
|
||
|
|
return list
|
||
|
|
}
|
||
|
|
|
||
|
|
static func truncate(_ s: String, max: Int) -> String {
|
||
|
|
let collapsed = s.replacingOccurrences(of: "\n", with: " ")
|
||
|
|
if collapsed.count <= max { return collapsed }
|
||
|
|
let i = collapsed.index(collapsed.startIndex, offsetBy: max)
|
||
|
|
return String(collapsed[..<i]) + "…"
|
||
|
|
}
|
||
|
|
}
|