7f8075b76d
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>
245 lines
11 KiB
Markdown
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>
|