Problem: We currently fetch and store only activeWindowEvents which are snapshots of an app usage. When we want to display them in a timeline or show statistics we need fetch all of the relevant ones and compute on the client.
Solution: We will minimize the amount of data we fetch from the server and compute on the client.
ActiveWindowEvent- keep as source of truth
- only timestamp -> no end time
Data specific:
-
- canonical activity block used by UI
- contains start and end times
-
SlotActivity(internal; module-private)- per-slot accumulator for durations and eventIds
-
SlotActivityGroup(internal; module-private)- 10‑min bucket for slotting
- holds a main activity and an allActivities map
Presentational specific:
- [
VisualSegment]:- CanonicalBlock + startMinute/endMinute and percentages for layout (viewport‑agnostic)
DaySegment- presentation-specific: adds pixel coordinates (
top,height) - derived from
VisualSegmenton the client using timeline height
- presentation-specific: adds pixel coordinates (
- DashboardView fetches
activeWindowEventsDatausinggetEventsForDateRange - Creates
eventsWithParsedDates(just date parsing/formatting) - Creates
canonicalBlocksusinggenerateProcessedEventBlocks()→ProcessedEventBlock[]- Handles duration calculation, maps categories, skips system/uncategorized events
- Stores as
trackedProcessedEventsstate and passes to CalendarWidget - CalendarWidget converts to
trackedCanonicalBlocksusingconvertProcessedToTimeBlocks()- Simple mapping (system filtering already done in step 3)
- Passes
trackedCanonicalBlocksto DayTimeline - DayTimeline calls
getTimelineSegmentsForDay()→DaySegment[]
Problem: Raw events capture every window switch (VS Code → Slack → VS Code → Chrome in 2 minutes), creating visual noise.
Solution: 10-minute slots aggregate noisy activity:
SlotActivityGroup: Time bucket withmainActivity(dominant by duration) andallActivities(full breakdown for tooltips)SlotActivity: Per-activity data within slot (duration, eventIds, original block reference)
Example: In 10-min slot with VS Code (6min), Slack (3min), Chrome (1min) → shows "VS Code" but tooltip shows all three.
- Partition: Manual/calendar → direct mapping; activity blocks → slotting
- Build SlotActivityGroups: 10-min buckets, accumulate durations per activity, pick
mainActivityby max duration - Merge consecutive SlotActivityGroups with same
mainActivity - Convert to
DaySegment[]with pixel coordinates, preservingoriginalEventIds
Future: Server returns VisualSegment[] (percentages/minutes), client maps to pixel DaySegment[]