TimeRecord Model
Definition
struct TimeRecord: Identifiable, Codable {
let id: UUID
var startTime: Date
var endTime: Date? // nil = running timer
var tagId: UUID? // nil = untagged
var comment: String?
var images: [String] // filenames of attached images
} Storage Format
Each record is persisted as a binary Automerge document (CRDT), one file per record. The fields above map directly to Automerge map keys, so concurrent edits from multiple devices merge automatically (last-writer-wins per field). Legacy JSON records (.json) are read-only and auto-migrated to Automerge.
Conceptually, a record holds:
id : uuid
startTime : 2024-01-15T09:30:00Z
endTime : 2024-01-15T11:45:00Z // absent = running timer
tagId : uuid // absent = untagged
comment : "Working on feature X"
images : ["uuid-string_0.jpg", "uuid-string_1.jpg"] Note: The images field is optional for backward compatibility. Old records without the field decode with an empty array.
File Naming
YYYY-MM-DD_HHmmss.automerge based on startTime
Storage Path
records/YYYY/MM/YYYY-MM-DD_HHmmss.automerge
Business Rules
- Multiple concurrent running timers allowed
- Overlapping records are valid
- tagId is optional (untagged records valid)
- endTime is optional (nil = running)
- images array is optional (old records without images field decode with empty array)
Image Storage
Images are stored in the same directory as the record document:
- Path:
records/YYYY/MM/(same as the record’s.automergefile) - Naming:
{record-id}_{index}.{ext}- Example:
550e8400-e29b-41d4-a716-446655440000_0.jpg
- Example:
- Supported formats: JPEG, PNG, HEIF
- Processing: Resized to max 1920px width/height, compressed to 80% JPEG quality
- When a record is deleted, all its images are automatically deleted
Related
Data
- 201-tag - Tag reference for categorization
Services
- 301-file-storage - CRUD and image operations
- 303-time-tracking - Timer start/stop, record updates
UI
- 406-record-editor - Edit record fields and images
- 407-history-section - Record listing with filtering
- 412-deletion-toast - Soft delete with undo
Reports
- 306-report - ReportRecordItem, ReportCommentItem
- 309-comments-section - Comment and image display