Update Neon colors and show color circles in theme picker
- Update NeonMoodTint to use synthwave colors matching Neon voting style (cyan, lime, yellow, orange, magenta) - Replace text label with 5 color circles in theme preview Colors row - Remove unused textColor customization code and picker views - Add .id(moodTint) to Month/Year views for color refresh - Clean up various unused color-related code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,4 +38,70 @@ extension DataController {
|
||||
}
|
||||
save()
|
||||
}
|
||||
|
||||
/// Get ALL entries for a specific date (not just the first one)
|
||||
func getAllEntries(byDate date: Date) -> [MoodEntryModel] {
|
||||
let startDate = Calendar.current.startOfDay(for: date)
|
||||
let endDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate)!
|
||||
|
||||
let descriptor = FetchDescriptor<MoodEntryModel>(
|
||||
predicate: #Predicate { entry in
|
||||
entry.forDate >= startDate && entry.forDate <= endDate
|
||||
},
|
||||
sortBy: [SortDescriptor(\.forDate, order: .forward)]
|
||||
)
|
||||
|
||||
return (try? modelContext.fetch(descriptor)) ?? []
|
||||
}
|
||||
|
||||
/// Delete ALL entries for a specific date
|
||||
func deleteAllEntries(forDate date: Date) {
|
||||
let entries = getAllEntries(byDate: date)
|
||||
for entry in entries {
|
||||
modelContext.delete(entry)
|
||||
}
|
||||
save()
|
||||
}
|
||||
|
||||
/// Find and remove duplicate entries, keeping only the most recent for each date
|
||||
/// Returns the number of duplicates removed
|
||||
@discardableResult
|
||||
func removeDuplicates() -> Int {
|
||||
let allEntries = getData(startDate: Date(timeIntervalSince1970: 0), endDate: Date(), includedDays: [])
|
||||
|
||||
// Group by day
|
||||
var entriesByDay = [Date: [MoodEntryModel]]()
|
||||
let calendar = Calendar.current
|
||||
|
||||
for entry in allEntries {
|
||||
let dayStart = calendar.startOfDay(for: entry.forDate)
|
||||
entriesByDay[dayStart, default: []].append(entry)
|
||||
}
|
||||
|
||||
var duplicatesRemoved = 0
|
||||
|
||||
for (_, dayEntries) in entriesByDay where dayEntries.count > 1 {
|
||||
// Sort by timestamp (most recent first), preferring non-missing moods
|
||||
let sorted = dayEntries.sorted { a, b in
|
||||
// Prefer non-missing moods
|
||||
if a.mood != .missing && b.mood == .missing { return true }
|
||||
if a.mood == .missing && b.mood != .missing { return false }
|
||||
// Then by timestamp (most recent first)
|
||||
return a.timestamp > b.timestamp
|
||||
}
|
||||
|
||||
// Keep the first (best) entry, delete the rest
|
||||
for entry in sorted.dropFirst() {
|
||||
modelContext.delete(entry)
|
||||
duplicatesRemoved += 1
|
||||
}
|
||||
}
|
||||
|
||||
if duplicatesRemoved > 0 {
|
||||
saveAndRunDataListeners()
|
||||
AppLogger.general.info("Removed \(duplicatesRemoved) duplicate entries")
|
||||
}
|
||||
|
||||
return duplicatesRemoved
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user