Commit Graph

97 Commits

Author SHA1 Message Date
irene 248053270b refactor: complete layered architecture migration
Delete old flat files, wire new DI in main.dart:
- Removed: gps_service.dart, config/, models/, providers/overlay_provider.dart,
  screens/, services/gps_data_manager.dart, services/overlay_service.dart
- Kept: settings_provider.dart (thin, correct), logger.dart (shared util)
- main.dart now wires: LocationRepository → SpeedometerViewModel → SpeedometerView
- overlay_provider.dart deferred, stub in ui/features/overlay/
- flutter analyze: 30 info-level constant_identifier_names warnings (project convention),
  zero errors, zero warnings — builds clean

New structure:
  lib/
    core/constants/     — gps, overlay, timing, speed_unit
    core/theme/         — color_themes
    data/
      models/           — LocationData (immutable domain model)
      services/         — GpsService (stateless wrapper), OverlayService (IPC)
      repositories/     — LocationRepository (business logic, ChangeNotifier)
    providers/          — SettingsProvider (thin, unchanged)
    ui/
      features/
        speedometer/    — SpeedometerViewModel + SpeedometerView
        overlay/        — Stub ViewModel + View (deferred)
      shared/           — SpeedDisplay widget
    services/           — Logger (shared util)
2026-08-23 17:32:29 +09:00
irene 6bba05efc8 refactor(data): move OverlayService to data/services/
- OverlayService was the only overlay-related file that should stay
- It is a stateless platform wrapper — fits in data/services/
- Will be used by future OverlayProvider when overlay is reimplemented
2026-08-23 17:27:42 +09:00
irene 1cc111bb76 feat(overlay): create stub ViewModel and View for deferred overlay feature
- Stub OverlayViewModel reserves abstraction point
- Stub OverlayView shows 'Overlay deferred' placeholder
- Original OverlayProvider (274 lines) was too tangled:
  mixed IPC, GPS forwarding, timers, foreground mgmt
- Will be reimplemented properly when overlay issues are resolved
2026-08-23 17:21:45 +09:00
irene 3c96571325 refactor(ui): create speedometer UI layer with ViewModel and shared widgets
- Create SpeedometerViewModel in ui/features/speedometer/
- Create thin SpeedometerView in ui/features/speedometer/
- Extract shared SpeedDisplay widget in ui/shared/
- Extract _CompassWidget from old speedometer screen
- Remove all business logic from UI layer
2026-08-23 17:21:09 +09:00
irene 44480eb969 refactor(data): create layered architecture with core/data/ui packages
- Move constants from lib/config/ to lib/core/constants/
- Move color themes to lib/core/theme/
- Create LocationData domain model in data/models/
- Create lightweight GpsService in data/services/
- Create LocationRepository in data/repositories/ consolidating
  GpsDataManager business logic (GPS stream, staleness, precision)
- Create shared SpeedDisplay widget in ui/shared/
- Defer overlay feature — stubs reserved in ui/features/overlay/
2026-08-23 17:16:43 +09:00
mikkeli 7a58483ba2 build(android): move to Flutter 3.47 template toolchain (Gradle 9.3.1 / AGP 9.1.0 / Kotlin 2.4.0)
The project pinned Gradle 8.12 / AGP 8.9.1 / Kotlin 2.1.0, all three below the
hard error floors that Flutter 3.47.1 enforces in DependencyVersionChecker.kt
(8.14.0 / 8.11.1 / 2.2.20). Nothing here had rotted; the SDK moved.

Targets Flutter's own template defaults rather than the lowest combo that
clears the floors, because Flutter promotes its warn floor to the error floor
in the very next release -- clearing only the hard floor buys one release of
runway. `flutter-android-preflight` on the host re-derives all of this from
the installed SDK.

Also:
- kotlinOptions{} -> kotlin{compilerOptions{}}: the old DSL is a script
  COMPILATION error under Kotlin >= 2.3, not a warning.
- Java/jvmTarget 11 -> 17, matching what the AndroidX artifacts now require.
- Drop android.enableJetifier (obsolete, removed outright in AGP 9); the
  Flutter migrator adds builtInKotlin/newDsl=false in its place. Keep them:
  builtInKotlin=true makes AGP 9.1.0 supply Kotlin 2.2.10, which is BELOW
  Flutter's own 2.2.20 floor, so Flutter rejects its own recommendation.
- Force plugin subprojects to compileSdk 36 / minSdk 24. bg_launcher 0.1.0 is
  abandoned at compileSdk 31 and the AndroidX artifacts it resolves to refuse
  it. The override must be registered before evaluationDependsOn(":app"),
  which evaluates subprojects eagerly. Dropping bg_launcher is the real fix.

Verified: flutter build apk --debug and --release, as both mikkeli and hermes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dKAqFo9Uj3mPZWvDzj3G8
2026-08-23 11:56:45 +09:00
irene a9844e9665 docs: add MIT license (Mikkeli Matlock, 2026) 2026-08-23 02:26:23 +09:00
mikkeli c889defa2e chore/fix: added DIN1451 font asset and removed gitignore item - reason: moving to self-hosted gitea so copyright is less of a concern here - long term, need to find proper licensed fonts or reactivate gitignore 2026-08-22 21:28:00 +09:00
Mikkeli Matlock b22872cf2e updates 2026-02-18 19:54:01 +09:00
Mikkeli Matlock 5422c73400 feat: merge GPS manager architecture restructure (v2.3.0)
Complete restructure of monolithic main.dart into modular MVVM
architecture. All 4 phases executed across 8 plans (~0.77 hrs total).

- Phase 1: Foundation — directory structure, models, Logger utility
- Phase 2: Provider migration — GpsDataManager, SettingsProvider, OverlayProvider
- Phase 3: Overlay refactor — OverlayService, staleness detection, error surfacing
- Phase 4: GPS optimization — adaptive precision, lifecycle management, wake locks

Key outcomes:
- SpeedometerScreen: 1075 lines → 493 lines (-54%)
- Zero setState for shared state (Provider/Consumer throughout)
- Speed-adaptive GPS precision (8/12 km/h hysteresis)
- Background GPS lifecycle awareness (7s grace period)
- Overlay staleness detection (3s dim, 10s dashes)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 08:09:26 +09:00
Mikkeli Matlock 26cdf24874 docs(04): complete phase 4 verification and roadmap
Mark Phase 4 complete in ROADMAP.md, add VERIFICATION.md (6/6
automated checks passed), and update phase 02 continue-here artifact.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 07:52:38 +09:00
Mikkeli Matlock 177e13a2f8 docs(04-02): complete UI integration plan
- Created 04-02-SUMMARY.md with execution details
- Updated STATE.md progress (Phase 4: 2/2 complete)
- Updated performance metrics (8 plans, 5.5 min avg)
- Added key decisions to accumulated context
- Marked Phase 4 as complete
2026-02-12 09:12:43 +09:00
Mikkeli Matlock 75d58c08ed chore(04-02): remove grace period placeholder from OverlayProvider
- Remove _gracePeriodTimer field and all grace period logic
- Grace period management now handled by GpsDataManager
- Overlay provider wiring completed in Task 1 (SpeedometerScreen initState)
- GPS_GRACE_PERIOD constant remains in TimingConfig (deprecated, unused)
2026-02-12 09:10:18 +09:00
Mikkeli Matlock 1dcfe60b4d feat(04-02): add staleness detection to main speed display
- Add staleness check timer (1s interval) with proper disposal
- Speed/heading dim at 3s, show dashes at 10s (matching overlay)
- Apply staleness opacity to both speed and heading displays
- Remove WakelockPlus management (now in GpsDataManager)
- Remove WidgetsBindingObserver (now in GpsDataManager)
- Simplify background heartbeat (removed _isInBackground check)
- Wire overlay provider into GpsDataManager via initState
- Add haptic feedback to theme/unit cycling
- Update _buildSpeedDisplay to accept opacity parameter
2026-02-12 09:09:10 +09:00
Mikkeli Matlock 8bc1e392a5 docs(04-01): complete core GPS engine plan
- Created SUMMARY.md documenting lifecycle-aware GPS engine implementation
- Updated STATE.md to Phase 4 Plan 1 of 2 complete (70% progress)
- Added 6 key decisions to STATE.md decisions table
- Updated performance metrics: 7 plans, 4.9 min average for Phase 4
- Updated session continuity and blockers sections
- Documented self-check results: all files and commits verified

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 09:04:59 +09:00
Mikkeli Matlock 1618cfeb26 feat(04-01): implement lifecycle-aware GPS engine with precision switching
- Add WidgetsBindingObserver mixin for app lifecycle tracking
- Add overlay provider reference for background decision-making
- Add state tracking: current accuracy, first-fix status, foreground/GPS active state
- Fix default ProcessedGpsData to non-const with timestamp
- Register lifecycle observer in initialize(), remove in dispose()
- Set first-fix state and time after initial GPS fix
- Update position handler to include timestamp in ProcessedGpsData
- Implement precision switching with hysteresis (8/12 km/h thresholds)
- Gate precision switching until 5s after first fix
- Implement lifecycle handlers: paused (7s grace period) and resumed (restart GPS)
- Add grace period expiration with race condition protection (re-check overlay)
- Add GPS stop/restart methods preserving last known data
- Implement conditional wake lock: GPS active AND (overlay OR foreground)
- Cancel all timers in dispose() including background grace period
- Remove unnecessary flutter/foundation import (widgets provides ChangeNotifier)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 09:02:33 +09:00
Mikkeli Matlock c4d4032b6b feat(04-01): add timestamp to ProcessedGpsData and precision/lifecycle constants
- Add timestamp field to ProcessedGpsData with copyWith support
- Add precision switching thresholds: 3.33 m/s (12 km/h) up, 2.22 m/s (8 km/h) down
- Add PRECISION_SWITCH_FIRST_FIX_DELAY (5s) to prevent early switching
- Add BACKGROUND_GRACE_PERIOD (7s) for lifecycle-aware GPS management
- Mark GPS_GRACE_PERIOD as deprecated in favor of BACKGROUND_GRACE_PERIOD
- Change GpsService.positionStream to createPositionStream() with dynamic accuracy
- Keep deprecated positionStream getter for backward compatibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 09:00:10 +09:00
Mikkeli Matlock 40c74677be docs(04): create phase plan for GPS & power optimization
2 plans in 2 waves: core GPS engine (precision switching, lifecycle,
wake lock) then UI integration (main app staleness, screen cleanup,
provider wiring).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 08:50:46 +09:00
Mikkeli Matlock 1dd3511047 docs(04): complete phase research 2026-02-12 08:43:40 +09:00
Mikkeli Matlock 7fe6168106 docs(04): capture phase context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 00:39:35 +09:00
Mikkeli Matlock d0427219a2 docs(03): complete overlay refactor phase
Phase 3 verified: 9/9 must-haves, 6/6 OVRL requirements satisfied.
OverlayService wrapper, staleness detection, error surfacing all verified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:35:15 +09:00
Mikkeli Matlock 9fb91f6e3f chore(03): update lockfile for retry dependency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:27:22 +09:00
Mikkeli Matlock 0976b76f44 docs(03-02): complete overlay integration plan
Tasks completed: 2/2
- Task 1: Integrated OverlayService into OverlayProvider with error callbacks and GPS grace period
- Task 2: Added staleness detection to overlay screen and error surfacing to SpeedometerScreen

SUMMARY: .planning/phases/03-overlay-refactor/03-02-SUMMARY.md
2026-02-11 19:26:26 +09:00
Mikkeli Matlock cc11a3d31a feat(03-02): add staleness detection to overlay screen and error surfacing to SpeedometerScreen
Overlay screen staleness:
- Add _lastUpdateTime field to track GPS data freshness
- Add _stalenessCheckTimer for periodic staleness monitoring (1s interval)
- Update _lastUpdateTime from message.timestamp in _listenToMainAppMessages
- Start staleness monitoring in initState, cancel in dispose
- Calculate staleness opacity in build() (0.5 alpha after 3s)
- Apply staleness dimming to speed text, unit text, heading icon, and heading text
- Show "--" for speed after 10s of no data (setState in timer callback)
- Immediate snap-back when fresh data arrives (no AnimatedOpacity)

SpeedometerScreen error surfacing:
- Import permission_handler for openAppSettings
- Register error callback on OverlayProvider in initState postFrameCallback
- Implement _handleOverlayError to show snackbars for overlay errors
- Permission error: snackbar with "Settings" action button that opens app settings
- Creation failure: snackbar with error message (no action button)
- Communication degraded: snackbar with error message (no action button)
- Clean up error callback in dispose (try-catch for disposed provider)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:24:05 +09:00
Mikkeli Matlock 66bdd35995 feat(03-02): integrate OverlayService into OverlayProvider with error callbacks and GPS grace period
- Add OverlayError enum (permission, creationFailed, communicationDegraded)
- Add OverlayService dependency via constructor injection
- Add onError callback field for error surfacing (set by SpeedometerScreen)
- Refactor showOverlay to check permission before showing overlay
- Refactor showOverlay to verify overlay creation via isActive check
- Only set _isOverlayActive after verification succeeds
- Replace all FlutterOverlayWindow calls with OverlayService methods
- Add GPS grace period timer (30s) in _handleOverlayClose
- Cancel grace period if overlay reopens within 30s
- Register OverlayService in MultiProvider before OverlayProvider
- Inject OverlayService into OverlayProvider constructor

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:21:58 +09:00
Mikkeli Matlock acfbeb85a2 docs(03-01): complete overlay foundation plan
Tasks completed: 2/2
- Task 1: Create OverlayService and add retry dependency
- Task 2: Add timestamp field to OverlayMessage model

SUMMARY: .planning/phases/03-overlay-refactor/03-01-SUMMARY.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:16:21 +09:00
Mikkeli Matlock 9e3decc91a feat(03-01): add timestamp field to OverlayMessage model
- Add timestamp field with auto-population via DateTime.now()
- Update all factory constructors to include timestamp
- Serialize timestamp as millisecondsSinceEpoch in toMap()
- Deserialize with fallback to DateTime.now() in fromMap()
- Add timestamp parameter to copyWith() method
- Remove const modifiers to allow DateTime.now() runtime values

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:13:39 +09:00
Mikkeli Matlock 505219c858 feat(03-01): create OverlayService and add retry dependency
- Add retry package (^3.1.2) for robust platform operations
- Create OverlayService wrapper for all FlutterOverlayWindow calls
- Implement showOverlay/closeOverlay with 3-attempt retry logic
- Add shareData fire-and-forget with warn-level logging
- Add isActive, overlayListener, checkPermission helpers
- Define staleness constants: 3s dim, 10s dash, 0.5 opacity, 1s check
- Define GPS_GRACE_PERIOD constant (30 seconds)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:12:23 +09:00
Mikkeli Matlock c58183b4fb docs(03): create phase plan for overlay refactor
Phase 3: Overlay Refactor
- 2 plan(s) in 2 wave(s)
- Sequential execution (Plan 02 depends on Plan 01)
- Ready for execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:00:39 +09:00
Mikkeli Matlock 07d446d912 docs(03): research overlay communication and staleness patterns
Phase 3: Overlay Refactor
- Standard stack identified: flutter_overlay_window 0.5.0, retry package, permission_handler
- Architecture patterns documented: OverlayService wrapper, timestamp-based staleness, error surfacing
- Pitfalls catalogued: communication blackhole, permission race conditions, opacity performance
- User decisions integrated: 3s dim threshold, 10s dashes, no recovery animation, 30s grace period

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 18:54:38 +09:00
Mikkeli Matlock 9001a42196 docs(03): capture phase context
Phase 03: Overlay Refactor
- Implementation decisions documented
- Phase boundary established

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 23:14:45 +09:00
Mikkeli Matlock a27e6b7f3e docs(02): complete provider migration phase
- Phase 2 verified: 20/20 must-haves passed
- STATE-01 through STATE-07 marked Complete in REQUIREMENTS.md
- VERIFICATION.md confirms codebase matches all success criteria
- ROADMAP.md and STATE.md updated for phase completion
2026-02-10 22:28:42 +09:00
Mikkeli Matlock 66320e122b chore(02): update lockfile and generated plugin registrant
- pubspec.lock updated for provider and shared_preferences dependencies
- macOS plugin registrant regenerated by Flutter toolchain
2026-02-10 22:21:48 +09:00
Mikkeli Matlock 09c80011b8 docs(02-02): complete MultiProvider wiring and screen migration plan
Tasks completed: 2/2
- Task 1: Wire MultiProvider in main.dart with async SharedPreferences
- Task 2: Migrate SpeedometerScreen from setState to Provider

SUMMARY: .planning/phases/02-provider-migration/02-02-SUMMARY.md
2026-02-10 22:21:04 +09:00
Mikkeli Matlock 7d111ca202 feat(02-02): migrate SpeedometerScreen from setState to Provider
- Remove all shared state variables (unit, theme, GPS data, overlay status)
- Keep only local widget state (_errorMessage, _isInBackground, timer)
- Replace GPS initialization with context.read<GpsDataManager>().initialize()
- Replace overlay show/close/toggle with OverlayProvider methods
- Replace theme/unit cycling with SettingsProvider.cycleTheme/Unit()
- Remove isOverlayMode parameter (not used, overlay runs in separate isolate)
- Wrap build with Selector<SettingsProvider, ColorTheme> for scaffold background
- Use Selector<GpsDataManager, double> for speed display (rebuilds only on speed change)
- Use Selector<SettingsProvider, String> for unit label (rebuilds only on unit change)
- Use Selector<GpsDataManager, (heading, displayHeading)> for compass (rebuilds only on heading change)
- Use context.read<> for event handlers (non-rebuilding access)
- Simplify dispose() - only cancel background heartbeat timer and disable wakelock
- Background heartbeat uses OverlayProvider.pushCurrentData() instead of inline logic
- setState remains ONLY for _errorMessage (purely local error UI state)
- Remove unused imports (speed_unit.dart, processed_gps_data.dart)
- Portrait and landscape layouts both use Provider pattern
2026-02-10 22:18:34 +09:00
Mikkeli Matlock 9867fe8c46 feat(02-02): wire MultiProvider with pre-initialized SharedPreferences
- Make main() async with WidgetsFlutterBinding.ensureInitialized()
- Pre-initialize SharedPreferences before runApp() to eliminate flash of defaults
- Wire MultiProvider with 4 providers in dependency order:
  1. Provider.value(SharedPreferences) - pre-initialized dependency
  2. ChangeNotifierProvider(SettingsProvider) - theme + unit state
  3. ChangeNotifierProvider(GpsDataManager) - GPS data stream
  4. ChangeNotifierProxyProvider2(OverlayProvider) - depends on GPS + Settings
- Remove isOverlayMode parameter from SpeedoApp (unused, overlay runs in separate isolate)
- Keep overlayMain() unchanged (separate isolate entry point)
2026-02-10 22:15:31 +09:00
Mikkeli Matlock 3c5ce89ded docs(02-01): complete provider infrastructure plan
Tasks completed: 3/3
- Task 1: Add provider dependencies and refactor GpsDataManager to ChangeNotifier
- Task 2: Create SettingsProvider for theme and unit state
- Task 3: Create OverlayProvider for overlay lifecycle and messaging

SUMMARY: .planning/phases/02-provider-migration/02-01-SUMMARY.md
2026-02-10 22:11:49 +09:00
Mikkeli Matlock 6b8bba8686 feat(02-01): create OverlayProvider for overlay lifecycle and messaging
- Created lib/providers/overlay_provider.dart
- Extends ChangeNotifier for reactive overlay state management
- Centralizes ALL overlay operations: show, close, toggle, status monitoring, messaging
- updateDependencies() called by ProxyProvider when GPS or Settings change
- Subscribes to GpsDataManager.dataStream on first update (persist subscription)
- Skips overlay sends when inactive (if-check, not unsubscribe)
- _isDisposed guards on all async-accessible methods
- showOverlay() sends initial data with overlay size info
- _pushDataToOverlay() sends GPS data with current theme/unit
- _startListeningToOverlayMessages() handles overlay→main IPC
- _startOverlayStatusCheck() polls overlay status at 1s interval
- _handleOverlayClose() manages cleanup and optional bring-to-front
- pushCurrentData() public method for background heartbeat usage
- dispose() cancels 4 subscriptions/timers, calls super.dispose() last
2026-02-10 22:05:39 +09:00
Mikkeli Matlock 1961651151 feat(02-01): create SettingsProvider for theme and unit state
- Created lib/providers/settings_provider.dart
- Extends ChangeNotifier for reactive state management
- Constructor accepts pre-initialized SharedPreferences instance
- Loads theme index and speed unit synchronously from SharedPreferences
- cycleTheme() and cycleUnit() methods with haptic feedback
- Persists settings to SharedPreferences on every change
- Both cycle methods call notifyListeners() for reactive UI updates
- No notifyListeners() in constructor (runs before first build)
2026-02-10 22:04:00 +09:00
Mikkeli Matlock f458b62eea chore(02-01): add provider dependencies and refactor GpsDataManager
- Added provider ^6.1.2 and shared_preferences ^2.3.4 to pubspec.yaml
- Removed singleton pattern from GpsDataManager (deleted _instance and instance getter)
- Changed GpsDataManager._internal() to public GpsDataManager() constructor
- Extended ChangeNotifier to enable reactive state updates
- Added _isDisposed guard field to prevent disposed notifications
- Updated _updateData() to call notifyListeners() after stream emission
- Added _isDisposed guards to _onGpsError() and _handleStaleDataTimeout()
- Updated dispose() to set _isDisposed, call super.dispose() last, removed _isInitialized reset
2026-02-10 22:03:13 +09:00
Mikkeli Matlock ee73a1a48d docs(02): phase 2 planned, paused before execution
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 11:31:42 +09:00
Mikkeli Matlock 755c4b7b06 fix(02): revise plans based on checker feedback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 11:17:01 +09:00
Mikkeli Matlock 630cf1c578 docs(02): create phase plan
Phase 02: Provider Migration
- 2 plan(s) in 2 wave(s)
- Wave 1: Create providers (GpsDataManager + SettingsProvider + OverlayProvider)
- Wave 2: Wire MultiProvider and migrate SpeedometerScreen
- Ready for execution
2026-02-10 11:13:29 +09:00
Mikkeli Matlock 8ff74b36e1 docs(02): research phase domain
Phase 02: Provider Migration
- Standard stack identified (provider v6.1.5+1)
- Architecture patterns documented (ChangeNotifier, Consumer, Selector)
- Pitfalls catalogued (7 common errors with solutions)
- Migration strategy validated against context decisions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 11:05:17 +09:00
Mikkeli Matlock 919b239c6e docs(02): capture phase context
Phase 02: Provider Migration
- Implementation decisions documented
- Phase boundary established
2026-02-10 10:58:15 +09:00
Mikkeli Matlock 5c9f3d225e wip: foundation complete, paused before phase 2
Phase 1 fully executed and verified (9/9 must-haves).
Ready to resume with Phase 2 (Provider Migration).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:58:56 +09:00
Mikkeli Matlock 8e3ad7f00c docs(01): complete foundation phase
Phase 1: Foundation - 2 plans executed in 19.6 minutes
- 01-01: Infrastructure, Logger, Constants, Models (12.8 min)
- 01-02: Screen extraction (6.8 min)
- Verification: 9/9 must-haves passed
- Requirements ORG-01 through ORG-08 marked Complete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:55:01 +09:00
Mikkeli Matlock c3865b318a docs(01-02): complete screen extraction plan
Tasks completed: 2/2
- SpeedometerScreen extracted to screens/speedometer_screen.dart (802 lines)
- OverlaySpeedometer extracted to screens/overlay_screen.dart (303 lines)
- main.dart slimmed to 39 lines (entry points only)

Phase 1 Foundation: COMPLETE (2/2 plans, 19.6 min total)

SUMMARY: .planning/phases/01-foundation/01-02-SUMMARY.md
2026-02-09 21:48:38 +09:00
Mikkeli Matlock ad077d1f32 feat(01-02): extract OverlaySpeedometer to screens/overlay_screen.dart
- Created lib/screens/overlay_screen.dart with OverlaySpeedometer and _OverlaySpeedometerState
- All state, methods, gesture handling preserved exactly
- main.dart imports screens/overlay_screen.dart
- OverlaySpeedometer removed from main.dart
- main.dart slimmed to 39 lines (under 60 line target)
- main.dart now contains only: main(), overlayMain(), SpeedoApp class
- Zero analyzer errors (except intentional SCREAMING_SNAKE warnings)
2026-02-09 21:45:56 +09:00
Mikkeli Matlock bc36076134 feat(01-02): extract SpeedometerScreen to screens/speedometer_screen.dart
- Created lib/screens/speedometer_screen.dart with SpeedometerScreen and _SpeedometerScreenState
- All state, methods, layout builders preserved exactly
- main.dart imports screens/speedometer_screen.dart
- SpeedometerScreen removed from main.dart
- Zero analyzer errors (except intentional SCREAMING_SNAKE warnings)
2026-02-09 21:43:41 +09:00