f48fd5c3d8
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
79 lines
2.4 KiB
Swift
79 lines
2.4 KiB
Swift
import Foundation
|
|
|
|
struct LearnedRecord: Codable {
|
|
let word: Word
|
|
var learnedAt: Date
|
|
var count: Int = 1
|
|
}
|
|
|
|
final class LearnedStore {
|
|
static let shared = LearnedStore()
|
|
private let key = "learned_records"
|
|
|
|
private(set) var records: [LearnedRecord] {
|
|
didSet {
|
|
guard let data = try? JSONEncoder().encode(records) else { return }
|
|
UserDefaults.standard.set(data, forKey: key)
|
|
}
|
|
}
|
|
|
|
private init() {
|
|
if let data = UserDefaults.standard.data(forKey: key),
|
|
let decoded = try? JSONDecoder().decode([LearnedRecord].self, from: data) {
|
|
records = decoded
|
|
} else {
|
|
records = []
|
|
}
|
|
}
|
|
|
|
func record(_ word: Word) {
|
|
if let index = records.firstIndex(where: { $0.word.id == word.id }) {
|
|
records[index].learnedAt = Date()
|
|
records[index].count += 1
|
|
} else {
|
|
records.append(LearnedRecord(word: word, learnedAt: Date()))
|
|
}
|
|
}
|
|
|
|
func isRecorded(_ word: Word) -> Bool {
|
|
records.contains { $0.word.id == word.id }
|
|
}
|
|
|
|
var sectioned: [(title: String, items: [LearnedRecord])] {
|
|
let sorted = records.sorted { $0.learnedAt > $1.learnedAt }
|
|
let formatter = DateFormatter()
|
|
formatter.locale = Locale(identifier: "zh_CN")
|
|
formatter.dateFormat = "yyyy-MM-dd"
|
|
|
|
var groups: [(String, [LearnedRecord])] = []
|
|
var seen: Set<String> = []
|
|
for record in sorted {
|
|
let dateStr = formatter.string(from: record.learnedAt)
|
|
let title = sectionTitle(dateStr)
|
|
if !seen.contains(title) {
|
|
groups.append((title, []))
|
|
seen.insert(title)
|
|
}
|
|
if let index = groups.firstIndex(where: { $0.0 == title }) {
|
|
groups[index].1.append(record)
|
|
}
|
|
}
|
|
return groups
|
|
}
|
|
|
|
private func sectionTitle(_ dateStr: String) -> String {
|
|
let today = DateFormatter()
|
|
today.locale = Locale(identifier: "zh_CN")
|
|
today.dateFormat = "yyyy-MM-dd"
|
|
let todayStr = today.string(from: Date())
|
|
if dateStr == todayStr { return "今天" }
|
|
|
|
let calendar = Calendar.current
|
|
if let yesterday = calendar.date(byAdding: .day, value: -1, to: Date()) {
|
|
let yesterdayStr = today.string(from: yesterday)
|
|
if dateStr == yesterdayStr { return "昨天" }
|
|
}
|
|
return dateStr
|
|
}
|
|
}
|