Files
gps-speedo/.planning/phases/01-foundation/01-02-PLAN.md
T
Mikkeli Matlock 7f8075b76d docs(01): create phase plan
Phase 01: Foundation
- 2 plan(s) in 2 wave(s)
- 2 autonomous, 0 checkpoint-only
- Ready for execution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:08:34 +09:00

245 lines
11 KiB
Markdown

---
phase: 01-foundation
plan: 02
type: execute
wave: 2
depends_on: ["01-01"]
files_modified:
- lib/screens/speedometer_screen.dart
- lib/screens/overlay_screen.dart
- lib/main.dart
autonomous: true
must_haves:
truths:
- "App compiles with flutter analyze showing zero errors"
- "main.dart contains only entry points (main, overlayMain), SpeedoApp widget, and imports — under 60 lines"
- "SpeedometerScreen lives in screens/speedometer_screen.dart with all its state and methods intact"
- "OverlaySpeedometer lives in screens/overlay_screen.dart with all its state and methods intact"
- "All existing functionality preserved — speed display, heading, themes, units, overlay, haptics, lifecycle all work identically"
artifacts:
- path: "lib/screens/speedometer_screen.dart"
provides: "Main speedometer screen widget and state"
contains: "class SpeedometerScreen"
- path: "lib/screens/overlay_screen.dart"
provides: "Overlay floating window widget and state"
contains: "class OverlaySpeedometer"
- path: "lib/main.dart"
provides: "App entry points and SpeedoApp widget only"
min_lines: 15
key_links:
- from: "lib/main.dart"
to: "lib/screens/speedometer_screen.dart"
via: "import and use as MaterialApp home"
pattern: "import.*screens/speedometer_screen"
- from: "lib/main.dart"
to: "lib/screens/overlay_screen.dart"
via: "import and use in overlayMain()"
pattern: "import.*screens/overlay_screen"
- from: "lib/screens/speedometer_screen.dart"
to: "lib/services/gps_data_manager.dart"
via: "GPS data subscription and display"
pattern: "import.*services/gps_data_manager"
- from: "lib/screens/speedometer_screen.dart"
to: "lib/models/overlay_message.dart"
via: "Overlay IPC messaging"
pattern: "import.*models/overlay_message"
- from: "lib/screens/overlay_screen.dart"
to: "lib/config/color_themes.dart"
via: "Theme rendering in overlay"
pattern: "import.*config/color_themes"
---
<objective>
Extract SpeedometerScreen and OverlaySpeedometer from the monolithic main.dart into dedicated screen files, leaving main.dart as a slim entry point.
Purpose: Completes the Phase 1 code organization by splitting the 1133-line main.dart into focused, single-responsibility files. This is the final structural change — after this, ORG-07 and ORG-08 are satisfied and the foundation phase is complete.
Output: speedometer_screen.dart (~780 lines), overlay_screen.dart (~240 lines), slimmed main.dart (~50 lines).
</objective>
<execution_context>
@C:\Users\SKSup\.claude/get-shit-done/workflows/execute-plan.md
@C:\Users\SKSup\.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-foundation/01-CONTEXT.md
@.planning/phases/01-foundation/01-01-SUMMARY.md
Source files (post Plan 01):
@lib/main.dart
</context>
<tasks>
<task type="auto">
<name>Task 1: Extract SpeedometerScreen to screens/speedometer_screen.dart</name>
<files>
lib/screens/speedometer_screen.dart
lib/main.dart
</files>
<action>
1. Create `lib/screens/speedometer_screen.dart` by extracting the `SpeedometerScreen` widget class and its `_SpeedometerScreenState` class from main.dart.
**What to move (everything from the SpeedometerScreen class through end of _SpeedometerScreenState):**
- `class SpeedometerScreen extends StatefulWidget` and its state
- All state variables, methods, build methods, layout builders
- The `_getOverlaySize()` method
- All timer management, lifecycle observer, overlay messaging, GPS subscription
- The `_buildSpeedDisplay()`, `_buildPortraitLayout()`, `_buildLandscapeLayout()` methods
**Imports needed in the new file** (derive from what SpeedometerScreen actually uses):
```dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; // HapticFeedback
import 'dart:async';
import 'dart:math' as math;
import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:flutter_overlay_window/flutter_overlay_window.dart';
import 'package:bg_launcher/bg_launcher.dart';
import '../config/speed_unit.dart';
import '../config/color_themes.dart';
import '../config/timing_constants.dart';
import '../config/overlay_constants.dart';
import '../models/overlay_message.dart';
import '../models/processed_gps_data.dart';
import '../services/gps_data_manager.dart';
import '../services/logger.dart';
```
**Do NOT include** in this file:
- `void main()` — stays in main.dart
- `void overlayMain()` — stays in main.dart
- `class SpeedoApp` — stays in main.dart
- `class OverlaySpeedometer` — goes to overlay_screen.dart in Task 2
**Critical: preserve ALL business logic, method signatures, and widget structure exactly.** This is a pure file move, not a refactor. Every line of SpeedometerScreen code must appear in the new file unchanged (except import paths).
2. Remove SpeedometerScreen class and _SpeedometerScreenState from main.dart. Leave only: imports, main(), overlayMain(), SpeedoApp, and OverlaySpeedometer (OverlaySpeedometer will be moved in Task 2).
3. Update main.dart imports to add:
```dart
import 'screens/speedometer_screen.dart';
```
4. Verify main.dart still references SpeedometerScreen correctly in SpeedoApp.build().
</action>
<verify>
- Run `flutter analyze` — zero errors
- Verify SpeedometerScreen class exists in lib/screens/speedometer_screen.dart
- Verify SpeedometerScreen class does NOT exist in lib/main.dart
- Verify main.dart still has SpeedoApp referencing SpeedometerScreen
</verify>
<done>
SpeedometerScreen fully extracted to screens/speedometer_screen.dart with all state, methods, and layout builders. main.dart imports it correctly. App compiles.
</done>
</task>
<task type="auto">
<name>Task 2: Extract OverlaySpeedometer to screens/overlay_screen.dart and slim down main.dart</name>
<files>
lib/screens/overlay_screen.dart
lib/main.dart
</files>
<action>
1. Create `lib/screens/overlay_screen.dart` by extracting the `OverlaySpeedometer` widget class and its `_OverlaySpeedometerState` class from main.dart.
**What to move:**
- `class OverlaySpeedometer extends StatefulWidget` and its state
- All state variables: _speedText, _unitText, _headingText, _heading, _currentThemeIndex, _systemScreenWidth, _overlayWidth, _overlayHeight
- All methods: _getSystemScreenSize(), _listenToMainAppMessages(), build()
- The entire gesture detection layer and overlay UI
**Imports needed in the new file:**
```dart
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:flutter_overlay_window/flutter_overlay_window.dart';
import '../config/color_themes.dart';
import '../config/overlay_constants.dart';
import '../models/overlay_message.dart';
import '../services/logger.dart';
```
**Critical: preserve ALL widget structure, gesture handling, and overlay communication exactly.** Pure file move.
2. Remove OverlaySpeedometer class and _OverlaySpeedometerState from main.dart.
3. Update main.dart to add import and reference overlay_screen.dart in overlayMain():
```dart
import 'screens/overlay_screen.dart';
```
4. **Clean up main.dart** to be a slim entry point. After extraction, main.dart should contain ONLY:
- Package imports (flutter/material.dart, flutter/foundation.dart)
- Local imports (screens/speedometer_screen.dart, screens/overlay_screen.dart, services/logger.dart)
- `void main()` function
- `@pragma("vm:entry-point") void overlayMain()` function
- `class SpeedoApp extends StatelessWidget`
The file should be approximately 40-55 lines. Remove any now-unused imports (dart:async, wakelock_plus, bg_launcher, speed_units, color_themes, gps_data_manager, dart:math, flutter/services.dart — these are all used by SpeedometerScreen which is now in its own file).
5. Verify the overlayMain() function references OverlaySpeedometer correctly.
</action>
<verify>
- Run `flutter analyze` — zero errors
- Verify OverlaySpeedometer class exists in lib/screens/overlay_screen.dart
- Verify OverlaySpeedometer class does NOT exist in lib/main.dart
- Verify main.dart is under 60 lines
- Verify main.dart contains only: main(), overlayMain(), SpeedoApp class
- Grep for `class ` in main.dart — should find only SpeedoApp
</verify>
<done>
OverlaySpeedometer fully extracted to screens/overlay_screen.dart. main.dart slimmed to ~50 lines containing only entry points and SpeedoApp widget. All imports correct. App compiles with zero errors.
</done>
</task>
<task type="checkpoint:human-verify" gate="non-blocking">
<what-built>Complete Phase 1 restructure: monolithic main.dart split into modular file structure with extracted models, typed overlay messages, centralized constants, and proper logger.</what-built>
<how-to-verify>
1. Build and run the app on a physical Android device: `flutter run`
2. Verify speed display works (shows current GPS speed or '--' when stationary)
3. Tap the speed number to cycle through themes (Yuzuki, Yuuparo, Yuzuki Light, Yuuparo Light)
4. Tap the unit label to cycle units (km/h, mph, kts)
5. Tap the compass/navigation area to launch the floating overlay window
6. Verify overlay shows speed and heading data
7. Long-press the overlay to close it
8. Rotate device to verify landscape layout works
9. Check debug console for Logger output format (colored tags, timestamps, caller names)
</how-to-verify>
<resume-signal>Type "approved" if all functionality works identically to before restructure, or describe any issues.</resume-signal>
</task>
</tasks>
<verification>
After both tasks complete:
1. `flutter analyze` returns zero errors
2. main.dart is under 60 lines, containing only entry points and SpeedoApp
3. SpeedometerScreen lives in lib/screens/speedometer_screen.dart
4. OverlaySpeedometer lives in lib/screens/overlay_screen.dart
5. No widget classes remain in main.dart except SpeedoApp
6. All imports resolve correctly (no "Target of URI doesn't exist" errors)
7. Grep for `class SpeedometerScreen` — found only in screens/speedometer_screen.dart
8. Grep for `class OverlaySpeedometer` — found only in screens/overlay_screen.dart
Requirements coverage: ORG-07 (SpeedometerScreen extracted), ORG-08 (OverlaySpeedometer extracted), ORG-01 (complete — all directories populated)
</verification>
<success_criteria>
- App compiles cleanly with `flutter analyze` showing zero errors
- main.dart is a slim entry point under 60 lines
- All screen widgets live in dedicated files under screens/
- Combined with Plan 01, ALL Phase 1 requirements (ORG-01 through ORG-08) are satisfied
- App runs on physical device with identical behavior to pre-restructure
</success_criteria>
<output>
After completion, create `.planning/phases/01-foundation/01-02-SUMMARY.md`
</output>