acfbeb85a2
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>
256 lines
10 KiB
Markdown
256 lines
10 KiB
Markdown
---
|
|
phase: 03-overlay-refactor
|
|
plan: 01
|
|
subsystem: overlay-infrastructure
|
|
tags: [service-layer, ipc, staleness-detection, retry-logic]
|
|
|
|
requires:
|
|
- 02-02: Provider pattern infrastructure for overlay state management
|
|
|
|
provides:
|
|
- OverlayService wrapper isolating all flutter_overlay_window platform calls
|
|
- Timestamp tracking in OverlayMessage for staleness detection
|
|
- Staleness threshold constants (3s dim, 10s dash) for UI feedback
|
|
- GPS grace period constant (30s) for background GPS lifecycle
|
|
|
|
affects:
|
|
- 03-02: OverlayProvider will use OverlayService instead of direct FlutterOverlayWindow calls
|
|
- 03-02: Overlay screen will consume staleness constants for visual feedback
|
|
- 03-02: SpeedometerScreen will use GPS_GRACE_PERIOD for background GPS management
|
|
|
|
tech-stack:
|
|
added:
|
|
- retry: ^3.1.2
|
|
patterns:
|
|
- Service wrapper pattern for platform channel isolation
|
|
- Exponential backoff retry (3 attempts, 200ms delay factor)
|
|
- Fire-and-forget with warn-level logging for non-critical failures
|
|
- Timestamp-based staleness detection via millisecondsSinceEpoch serialization
|
|
|
|
key-files:
|
|
created:
|
|
- lib/services/overlay_service.dart
|
|
modified:
|
|
- lib/models/overlay_message.dart
|
|
- lib/config/overlay_constants.dart
|
|
- lib/config/timing_constants.dart
|
|
- pubspec.yaml
|
|
|
|
decisions:
|
|
- id: OVL-01
|
|
choice: OverlayService wraps all FlutterOverlayWindow calls
|
|
rationale: Isolate platform-specific code, centralize retry logic and error handling
|
|
status: implemented
|
|
- id: OVL-02
|
|
choice: showOverlay verifies overlay opened via isActive() call
|
|
rationale: Platform channel may succeed but overlay fail to appear - explicit verification required
|
|
status: implemented
|
|
- id: OVL-03
|
|
choice: shareData is fire-and-forget with warn-level logging
|
|
rationale: User decision - send every GPS tick, staleness detection handles drops, no retry needed
|
|
status: implemented
|
|
- id: OVL-04
|
|
choice: Staleness thresholds are 3s dim, 10s dash (NOT 2s/10s)
|
|
rationale: User specified 3 seconds for dim threshold in plan
|
|
status: implemented
|
|
- id: OVL-05
|
|
choice: Timestamp auto-populated by DateTime.now() in factories
|
|
rationale: Timestamp is metadata, not user data - automatic population prevents caller errors
|
|
status: implemented
|
|
- id: OVL-06
|
|
choice: Remove const from OverlayMessage constructors
|
|
rationale: DateTime.now() is runtime value, cannot be const - necessary for timestamp field
|
|
status: implemented
|
|
|
|
metrics:
|
|
duration: 4.0 minutes
|
|
completed: 2026-02-11
|
|
---
|
|
|
|
# Phase 03 Plan 01: Overlay Foundation Infrastructure Summary
|
|
|
|
**One-liner:** OverlayService wrapper with retry logic, timestamp-enhanced OverlayMessage, and staleness constants (3s dim, 10s dash, 30s GPS grace period).
|
|
|
|
## Objective Achieved
|
|
|
|
Created the foundation building blocks for overlay refactor by:
|
|
1. Isolating all flutter_overlay_window platform calls behind OverlayService with retry logic
|
|
2. Adding timestamp tracking to OverlayMessage for staleness detection
|
|
3. Defining staleness thresholds (3s dim, 10s dash) and GPS grace period (30s) as named constants
|
|
|
|
These components provide the service layer, enhanced model, and constants that Plan 02 will integrate into OverlayProvider, overlay screen, and SpeedometerScreen.
|
|
|
|
## Tasks Completed
|
|
|
|
| Task | Description | Commit | Files Modified |
|
|
|------|-------------|--------|----------------|
|
|
| 1 | Create OverlayService and add retry dependency | 505219c | overlay_service.dart, overlay_constants.dart, timing_constants.dart, pubspec.yaml |
|
|
| 2 | Add timestamp field to OverlayMessage model | 9e3decc | overlay_message.dart |
|
|
|
|
## Implementation Details
|
|
|
|
### OverlayService Architecture
|
|
|
|
**Platform Channel Wrapper:**
|
|
- `showOverlay({width, height})` - Retry logic with post-verification via isActive()
|
|
- `closeOverlay()` - Retry logic for robust cleanup
|
|
- `shareData(Map)` - Fire-and-forget with warn-level logging (no retry)
|
|
- `isActive()` - Error-safe overlay status check
|
|
- `overlayListener` - Direct stream delegation
|
|
- `checkPermission()` - Permission status helper
|
|
|
|
**Retry Configuration:**
|
|
- 3 attempts maximum
|
|
- 200ms delay factor (exponential backoff)
|
|
- Removed unnecessary `retryIf` checks (analyzer warnings fixed)
|
|
|
|
**Error Handling Strategy:**
|
|
- showOverlay/closeOverlay: Logger.error after exhausted retries, return false
|
|
- shareData: Logger.warn on failure, no retry (staleness detection handles drops)
|
|
- isActive: Logger.error + return false on exception
|
|
|
|
### OverlayMessage Enhancements
|
|
|
|
**Timestamp Field:**
|
|
- Auto-populated via `DateTime.now()` in all factory constructors
|
|
- No manual timestamp passing required from callers
|
|
- Serialized as `millisecondsSinceEpoch` (int) in toMap()
|
|
- Deserialized with fallback to `DateTime.now()` in fromMap() for backward compatibility
|
|
|
|
**Breaking Change Mitigation:**
|
|
- Removed `const` modifiers (DateTime.now() is runtime value)
|
|
- Added timestamp to copyWith() for completeness
|
|
- All existing factory APIs unchanged (timestamp is additive metadata)
|
|
|
|
### Constants Configuration
|
|
|
|
**Staleness Thresholds (overlay_constants.dart):**
|
|
- `STALENESS_DIM_THRESHOLD`: 3 seconds (dim speed display)
|
|
- `STALENESS_DASH_THRESHOLD`: 10 seconds (show dashes instead of speed)
|
|
- `STALENESS_DIM_OPACITY`: 0.5 (dimmed state opacity)
|
|
- `STALENESS_CHECK_INTERVAL`: 1 second (check frequency)
|
|
|
|
**GPS Grace Period (timing_constants.dart):**
|
|
- `GPS_GRACE_PERIOD`: 30 seconds (continue GPS after overlay close when backgrounded)
|
|
|
|
## Verification Results
|
|
|
|
**flutter pub get:**
|
|
- retry package (^3.1.2) installed successfully
|
|
- All dependencies resolved
|
|
|
|
**flutter analyze:**
|
|
- 26 info-level warnings (SCREAMING_SNAKE constants - expected per project convention)
|
|
- 0 errors or warnings in new code
|
|
- Fixed 2 unnecessary type check warnings in OverlayService retry logic
|
|
|
|
**Code Quality:**
|
|
- OverlayService: 93 lines with comprehensive error handling
|
|
- OverlayMessage timestamp integration: 15 lines added across all methods
|
|
- All must-have requirements satisfied
|
|
|
|
## Deviations from Plan
|
|
|
|
None - plan executed exactly as written.
|
|
|
|
## Decisions Made
|
|
|
|
**OVL-01: Service Wrapper Pattern**
|
|
- All flutter_overlay_window calls isolated in OverlayService
|
|
- Benefits: Centralized retry logic, single error handling point, easier testing
|
|
- Impact: Plan 02 will migrate OverlayProvider to use OverlayService
|
|
|
|
**OVL-02: Post-Verification in showOverlay**
|
|
- Added isActive() verification after FlutterOverlayWindow.showOverlay() completes
|
|
- Addresses: Platform channel may report success but overlay fails to appear
|
|
- Prevents: False positive overlay status in OverlayProvider
|
|
|
|
**OVL-03: Fire-and-Forget shareData**
|
|
- No retry logic for data sharing (user decision: forward every tick)
|
|
- Staleness detection handles dropped messages via timestamp tracking
|
|
- Warn-level logging prevents error log noise from expected occasional failures
|
|
|
|
**OVL-04: Staleness Timing**
|
|
- 3 seconds for dim (NOT 2 seconds as in some research notes)
|
|
- 10 seconds for dashes (consistent across all references)
|
|
- User explicitly specified 3s in plan MUST_HAVES
|
|
|
|
**OVL-05: Automatic Timestamp Population**
|
|
- DateTime.now() called in factory constructors, not passed by callers
|
|
- Prevents caller errors (forgetting timestamp, using wrong time source)
|
|
- Ensures consistency (all timestamps from same clock source)
|
|
|
|
**OVL-06: Remove const Modifiers**
|
|
- Required to allow DateTime.now() runtime values
|
|
- Trade-off: Lose compile-time const optimization for timestamp functionality
|
|
- Impact: Negligible (OverlayMessage instances are short-lived IPC data)
|
|
|
|
## Technical Debt
|
|
|
|
**None identified.**
|
|
|
|
All code follows project conventions:
|
|
- SCREAMING_SNAKE for behavioral constants
|
|
- Logger with caller tags for all logging
|
|
- Error handling with graceful degradation
|
|
- Type-safe OverlayMessage serialization
|
|
|
|
## Integration Readiness
|
|
|
|
**Ready for Plan 02:**
|
|
- OverlayService provides all needed platform operations
|
|
- OverlayMessage timestamp field ready for staleness calculation
|
|
- Constants defined and accessible for UI feedback logic
|
|
|
|
**Migration Path for Plan 02:**
|
|
1. Replace FlutterOverlayWindow.showOverlay in OverlayProvider with OverlayService.showOverlay
|
|
2. Replace FlutterOverlayWindow.closeOverlay with OverlayService.closeOverlay
|
|
3. Replace FlutterOverlayWindow.shareData with OverlayService.shareData
|
|
4. Add staleness detection timer in overlay screen using STALENESS_CHECK_INTERVAL
|
|
5. Implement dim/dash logic using STALENESS_DIM_THRESHOLD and STALENESS_DASH_THRESHOLD
|
|
6. Add GPS grace period logic in SpeedometerScreen using GPS_GRACE_PERIOD
|
|
|
|
## Artifacts Generated
|
|
|
|
**Service Layer:**
|
|
- `lib/services/overlay_service.dart` (93 lines)
|
|
|
|
**Enhanced Model:**
|
|
- `lib/models/overlay_message.dart` (+18 lines, -3 lines)
|
|
|
|
**Configuration:**
|
|
- `lib/config/overlay_constants.dart` (+12 lines)
|
|
- `lib/config/timing_constants.dart` (+3 lines)
|
|
|
|
**Dependencies:**
|
|
- `pubspec.yaml` (+3 lines - retry package)
|
|
|
|
## Next Steps
|
|
|
|
Plan 02 will:
|
|
1. Integrate OverlayService into OverlayProvider
|
|
2. Add staleness detection timer and UI feedback in overlay screen
|
|
3. Implement GPS grace period logic in SpeedometerScreen
|
|
4. Replace all direct FlutterOverlayWindow calls with OverlayService methods
|
|
|
|
**Estimated complexity:** Medium (refactor existing OverlayProvider and overlay screen)
|
|
|
|
**Blockers:** None - all foundation infrastructure complete
|
|
|
|
## Commits
|
|
|
|
1. **505219c** - feat(03-01): create OverlayService and add retry dependency
|
|
- Added retry package (^3.1.2)
|
|
- Created OverlayService wrapper with showOverlay, closeOverlay, shareData, isActive, overlayListener, checkPermission
|
|
- Implemented 3-attempt retry with 200ms exponential backoff
|
|
- Added staleness constants: 3s dim, 10s dash, 0.5 opacity, 1s check interval
|
|
- Added GPS_GRACE_PERIOD constant (30 seconds)
|
|
|
|
2. **9e3decc** - feat(03-01): add timestamp field to OverlayMessage model
|
|
- Added timestamp field with auto-population via DateTime.now()
|
|
- Updated all factory constructors (updateDisplay, longPressClose, overlayClosed)
|
|
- Serialized timestamp as millisecondsSinceEpoch in toMap()
|
|
- Deserialized with fallback to DateTime.now() in fromMap()
|
|
- Added timestamp parameter to copyWith()
|
|
- Removed const modifiers for runtime timestamp values
|