- Initialize iOS project with 6-tab navigation structure - Configure custom Light/Dark themes and AppColors - Define SwiftData models for Tasks, Tags, Goals, and TrackingRecords - Setup relationships (Super/Sub tags) and cascade delete rules - Implement Observable TrackingEngine for real-time timer updates
63 lines
1.8 KiB
Swift
63 lines
1.8 KiB
Swift
import Foundation
|
|
import SwiftData
|
|
|
|
@MainActor
|
|
@Observable
|
|
final class TrackingEngine {
|
|
private(set) var activeSessions: [UUID: Date] = [:]
|
|
private(set) var elapsedTimes: [UUID: TimeInterval] = [:]
|
|
|
|
private var tickTask: Task<Void, Never>?
|
|
|
|
init() {
|
|
tickTask = Task {
|
|
while !Task.isCancelled {
|
|
try? await Task.sleep(for: .seconds(1))
|
|
self.tick()
|
|
}
|
|
}
|
|
}
|
|
|
|
private func tick() {
|
|
let now = Date.now
|
|
for (id, start) in activeSessions {
|
|
elapsedTimes[id] = now.timeIntervalSince(start)
|
|
}
|
|
}
|
|
|
|
func isRunning(_ task: TaskItem) -> Bool {
|
|
activeSessions[task.id] != nil
|
|
}
|
|
|
|
func elapsed(for task: TaskItem) -> TimeInterval {
|
|
elapsedTimes[task.id] ?? 0
|
|
}
|
|
|
|
func startTimer(for task: TaskItem, context: ModelContext) {
|
|
guard !isRunning(task) else { return }
|
|
let now = Date.now
|
|
let record = TrackingRecord(task: task, recordType: .timerSession, startTime: now)
|
|
context.insert(record)
|
|
task.trackingRecords.append(record)
|
|
activeSessions[task.id] = now
|
|
elapsedTimes[task.id] = 0
|
|
}
|
|
|
|
func stopTimer(for task: TaskItem, context: ModelContext) {
|
|
guard let startTime = activeSessions[task.id] else { return }
|
|
let now = Date.now
|
|
if let record = task.trackingRecords.first(where: { $0.isRunning }) {
|
|
record.endTime = now
|
|
record.duration = now.timeIntervalSince(startTime)
|
|
}
|
|
activeSessions.removeValue(forKey: task.id)
|
|
elapsedTimes.removeValue(forKey: task.id)
|
|
}
|
|
|
|
func incrementCounter(for task: TaskItem, context: ModelContext) {
|
|
let record = TrackingRecord(task: task, recordType: .countLog, timestamp: .now)
|
|
context.insert(record)
|
|
task.trackingRecords.append(record)
|
|
}
|
|
}
|