feat: timer engine + full-screen timer UI

Implement the core timer feature following the src/features/ architecture:

- useTimerEngine hook: drift-free Date.now() delta countdown (100ms tick),
  explicit state machine (IDLE → GET_READY → WORK → REST → COMPLETE),
  event emitter for external consumers (PHASE_CHANGED, ROUND_COMPLETED,
  COUNTDOWN_TICK, SESSION_COMPLETE), auto-pause on AppState interruption
  (phone calls, background), expo-keep-awake during session
- TimerDisplay component: full-screen animated UI with 600ms color
  transitions between phases, pulse animation on countdown, flash red
  on last 3 seconds, round progress dots, IDLE/active/COMPLETE views
- TimerControls component: stop/pause-resume/skip buttons with Ionicons
- Timer route (app/timer.tsx): fullScreenModal wiring hook → display
- Home screen: dark theme with START button navigating to /timer
- Project docs: CLAUDE.md (constitution), PRD v1.1, skill files
- Shared constants: PHASE_COLORS, TIMER_DEFAULTS, formatTime utility
- Types: TimerPhase, TimerState, TimerConfig, TimerActions, TimerEvent

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Millian Lamiaux
2026-02-17 19:05:25 +01:00
parent 5cefe864ec
commit 31bdb1586f
19 changed files with 3256 additions and 90 deletions

View File

@@ -0,0 +1,7 @@
export const PHASE_COLORS = {
IDLE: '#1E1E2E',
GET_READY: '#EAB308',
WORK: '#F97316',
REST: '#3B82F6',
COMPLETE: '#22C55E',
} as const

View File

@@ -0,0 +1,10 @@
export const TIMER_DEFAULTS = {
WORK_DURATION: 20,
REST_DURATION: 10,
ROUNDS: 8,
GET_READY_DURATION: 10,
CYCLES: 1,
CYCLE_PAUSE_DURATION: 60,
} as const
export const TICK_INTERVAL_MS = 100