feat(01-01): extract models and move config files to new structure
- Move SpeedUnit enum to config/speed_unit.dart - Move ColorTheme/ColorThemes classes to config/color_themes.dart - Extract ProcessedGpsData model from gps_data_manager to models/ - Create OverlayMessage typed class for overlay IPC (replaces raw Maps) - Create ThemeModel with palette rotation and state management
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
/// Typed message class for overlay IPC communication
|
||||
/// Replaces unvalidated Map data with type-safe serialization
|
||||
class OverlayMessage {
|
||||
final String action;
|
||||
final String? speedText;
|
||||
final String? unitText;
|
||||
final String? headingText;
|
||||
final double? heading;
|
||||
final int? unitIndex;
|
||||
final int? themeIndex;
|
||||
final double? overlayWidth;
|
||||
final double? overlayHeight;
|
||||
|
||||
const OverlayMessage({
|
||||
required this.action,
|
||||
this.speedText,
|
||||
this.unitText,
|
||||
this.headingText,
|
||||
this.heading,
|
||||
this.unitIndex,
|
||||
this.themeIndex,
|
||||
this.overlayWidth,
|
||||
this.overlayHeight,
|
||||
});
|
||||
|
||||
/// Factory constructor for display update messages
|
||||
factory OverlayMessage.updateDisplay({
|
||||
required String speedText,
|
||||
required String unitText,
|
||||
required String headingText,
|
||||
required double heading,
|
||||
required int unitIndex,
|
||||
required int themeIndex,
|
||||
double? overlayWidth,
|
||||
double? overlayHeight,
|
||||
}) {
|
||||
return OverlayMessage(
|
||||
action: 'updateDisplay',
|
||||
speedText: speedText,
|
||||
unitText: unitText,
|
||||
headingText: headingText,
|
||||
heading: heading,
|
||||
unitIndex: unitIndex,
|
||||
themeIndex: themeIndex,
|
||||
overlayWidth: overlayWidth,
|
||||
overlayHeight: overlayHeight,
|
||||
);
|
||||
}
|
||||
|
||||
/// Factory constructor for long press close signal
|
||||
factory OverlayMessage.longPressClose() {
|
||||
return const OverlayMessage(action: 'longPressClose');
|
||||
}
|
||||
|
||||
/// Factory constructor for overlay closed notification
|
||||
factory OverlayMessage.overlayClosed() {
|
||||
return const OverlayMessage(action: 'overlayClosed');
|
||||
}
|
||||
|
||||
/// Serialize to Map for overlay IPC
|
||||
Map<String, dynamic> toMap() {
|
||||
final map = <String, dynamic>{'action': action};
|
||||
if (speedText != null) map['speedText'] = speedText;
|
||||
if (unitText != null) map['unitText'] = unitText;
|
||||
if (headingText != null) map['headingText'] = headingText;
|
||||
if (heading != null) map['heading'] = heading;
|
||||
if (unitIndex != null) map['unitIndex'] = unitIndex;
|
||||
if (themeIndex != null) map['themeIndex'] = themeIndex;
|
||||
if (overlayWidth != null) map['overlayWidth'] = overlayWidth;
|
||||
if (overlayHeight != null) map['overlayHeight'] = overlayHeight;
|
||||
return map;
|
||||
}
|
||||
|
||||
/// Deserialize from Map received via overlay IPC
|
||||
factory OverlayMessage.fromMap(Map<dynamic, dynamic> map) {
|
||||
return OverlayMessage(
|
||||
action: map['action'] as String? ?? 'unknown',
|
||||
speedText: map['speedText'] as String?,
|
||||
unitText: map['unitText'] as String?,
|
||||
headingText: map['headingText'] as String?,
|
||||
heading: (map['heading'] as num?)?.toDouble(),
|
||||
unitIndex: map['unitIndex'] as int?,
|
||||
themeIndex: map['themeIndex'] as int?,
|
||||
overlayWidth: (map['overlayWidth'] as num?)?.toDouble(),
|
||||
overlayHeight: (map['overlayHeight'] as num?)?.toDouble(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create a copy with updated fields
|
||||
OverlayMessage copyWith({
|
||||
String? action,
|
||||
String? speedText,
|
||||
String? unitText,
|
||||
String? headingText,
|
||||
double? heading,
|
||||
int? unitIndex,
|
||||
int? themeIndex,
|
||||
double? overlayWidth,
|
||||
double? overlayHeight,
|
||||
}) {
|
||||
return OverlayMessage(
|
||||
action: action ?? this.action,
|
||||
speedText: speedText ?? this.speedText,
|
||||
unitText: unitText ?? this.unitText,
|
||||
headingText: headingText ?? this.headingText,
|
||||
heading: heading ?? this.heading,
|
||||
unitIndex: unitIndex ?? this.unitIndex,
|
||||
themeIndex: themeIndex ?? this.themeIndex,
|
||||
overlayWidth: overlayWidth ?? this.overlayWidth,
|
||||
overlayHeight: overlayHeight ?? this.overlayHeight,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
class ProcessedGpsData {
|
||||
final double speed; // Raw speed in m/s
|
||||
final double heading; // Raw heading in degrees
|
||||
final String displaySpeed; // Formatted speed text (with -- logic)
|
||||
final String displayHeading; // Formatted heading text
|
||||
final bool isSpeedValid; // True if from recent GPS
|
||||
final bool isHeadingValid; // True if from recent GPS
|
||||
|
||||
const ProcessedGpsData({
|
||||
required this.speed,
|
||||
required this.heading,
|
||||
required this.displaySpeed,
|
||||
required this.displayHeading,
|
||||
required this.isSpeedValid,
|
||||
required this.isHeadingValid,
|
||||
});
|
||||
|
||||
ProcessedGpsData copyWith({
|
||||
double? speed,
|
||||
double? heading,
|
||||
String? displaySpeed,
|
||||
String? displayHeading,
|
||||
bool? isSpeedValid,
|
||||
bool? isHeadingValid,
|
||||
}) {
|
||||
return ProcessedGpsData(
|
||||
speed: speed ?? this.speed,
|
||||
heading: heading ?? this.heading,
|
||||
displaySpeed: displaySpeed ?? this.displaySpeed,
|
||||
displayHeading: displayHeading ?? this.displayHeading,
|
||||
isSpeedValid: isSpeedValid ?? this.isSpeedValid,
|
||||
isHeadingValid: isHeadingValid ?? this.isHeadingValid,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import '../config/color_themes.dart';
|
||||
|
||||
/// Theme model that wraps ColorThemes with rotation and state management.
|
||||
/// Holds all possible color palettes via delegation, exposing only the current set.
|
||||
class ThemeModel {
|
||||
final int _currentIndex;
|
||||
|
||||
const ThemeModel({int currentIndex = 0}) : _currentIndex = currentIndex;
|
||||
|
||||
/// Get the current active color theme
|
||||
ColorTheme get current => ColorThemes.getTheme(_currentIndex);
|
||||
|
||||
/// Get the name of the current theme
|
||||
String get currentSetName => current.name;
|
||||
|
||||
/// Get the current theme index
|
||||
int get currentIndex => _currentIndex;
|
||||
|
||||
/// Rotate to the next theme (circular)
|
||||
ThemeModel rotate() {
|
||||
return ThemeModel(
|
||||
currentIndex: ColorThemes.getNextThemeIndex(_currentIndex),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create a copy with an updated theme index
|
||||
ThemeModel copyWith({int? currentIndex}) {
|
||||
return ThemeModel(
|
||||
currentIndex: currentIndex ?? _currentIndex,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user