187 lines
5.7 KiB
Dart
187 lines
5.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
/// Selectable tactical map base tile styles for MOB-06 / MAP-02.
|
|
enum TacticalMapStyle {
|
|
tacticalDark,
|
|
satellite4K,
|
|
elevation3D,
|
|
}
|
|
|
|
extension TacticalMapStyleExtension on TacticalMapStyle {
|
|
String get displayName {
|
|
switch (this) {
|
|
case TacticalMapStyle.tacticalDark:
|
|
return 'Tactical Dark';
|
|
case TacticalMapStyle.satellite4K:
|
|
return 'Satellite 4K';
|
|
case TacticalMapStyle.elevation3D:
|
|
return '3D Topo Elevation';
|
|
}
|
|
}
|
|
|
|
String get subtitle {
|
|
switch (this) {
|
|
case TacticalMapStyle.tacticalDark:
|
|
return 'Vector with highlighted twisty passes';
|
|
case TacticalMapStyle.satellite4K:
|
|
return 'Esri / AWS aerial satellite imagery';
|
|
case TacticalMapStyle.elevation3D:
|
|
return 'Mountain contours & elevation shading';
|
|
}
|
|
}
|
|
|
|
IconData get icon {
|
|
switch (this) {
|
|
case TacticalMapStyle.tacticalDark:
|
|
return Icons.dark_mode_outlined;
|
|
case TacticalMapStyle.satellite4K:
|
|
return Icons.satellite_alt_outlined;
|
|
case TacticalMapStyle.elevation3D:
|
|
return Icons.terrain_outlined;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Tactical layer and overlay preferences for the motorcycle map HUD.
|
|
class MapLayerSettings {
|
|
final TacticalMapStyle style;
|
|
final bool showPoliceTraps;
|
|
final bool showPackBlips;
|
|
final bool showTwistyHighlights;
|
|
final bool offlineOnly;
|
|
|
|
const MapLayerSettings({
|
|
this.style = TacticalMapStyle.tacticalDark,
|
|
this.showPoliceTraps = true,
|
|
this.showPackBlips = true,
|
|
this.showTwistyHighlights = true,
|
|
this.offlineOnly = false,
|
|
});
|
|
|
|
MapLayerSettings copyWith({
|
|
TacticalMapStyle? style,
|
|
bool? showPoliceTraps,
|
|
bool? showPackBlips,
|
|
bool? showTwistyHighlights,
|
|
bool? offlineOnly,
|
|
}) {
|
|
return MapLayerSettings(
|
|
style: style ?? this.style,
|
|
showPoliceTraps: showPoliceTraps ?? this.showPoliceTraps,
|
|
showPackBlips: showPackBlips ?? this.showPackBlips,
|
|
showTwistyHighlights: showTwistyHighlights ?? this.showTwistyHighlights,
|
|
offlineOnly: offlineOnly ?? this.offlineOnly,
|
|
);
|
|
}
|
|
|
|
@override
|
|
bool operator ==(Object other) =>
|
|
identical(this, other) ||
|
|
other is MapLayerSettings &&
|
|
runtimeType == other.runtimeType &&
|
|
style == other.style &&
|
|
showPoliceTraps == other.showPoliceTraps &&
|
|
showPackBlips == other.showPackBlips &&
|
|
showTwistyHighlights == other.showTwistyHighlights &&
|
|
offlineOnly == other.offlineOnly;
|
|
|
|
@override
|
|
int get hashCode =>
|
|
style.hashCode ^
|
|
showPoliceTraps.hashCode ^
|
|
showPackBlips.hashCode ^
|
|
showTwistyHighlights.hashCode ^
|
|
offlineOnly.hashCode;
|
|
}
|
|
|
|
class MapLayerSettingsNotifier extends StateNotifier<MapLayerSettings> {
|
|
static const String _prefKeyStyle = 'tactical_map_style';
|
|
static const String _prefKeyTraps = 'tactical_show_police_traps';
|
|
static const String _prefKeyPack = 'tactical_show_pack_blips';
|
|
static const String _prefKeyTwisty = 'tactical_show_twisty';
|
|
static const String _prefKeyOffline = 'tactical_offline_only';
|
|
|
|
MapLayerSettingsNotifier() : super(const MapLayerSettings()) {
|
|
_loadFromPrefs();
|
|
}
|
|
|
|
Future<void> _loadFromPrefs() async {
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final styleStr = prefs.getString(_prefKeyStyle);
|
|
final style = styleStr != null
|
|
? TacticalMapStyle.values.firstWhere(
|
|
(s) => s.name == styleStr,
|
|
orElse: () => TacticalMapStyle.tacticalDark,
|
|
)
|
|
: TacticalMapStyle.tacticalDark;
|
|
state = MapLayerSettings(
|
|
style: style,
|
|
showPoliceTraps: prefs.getBool(_prefKeyTraps) ?? true,
|
|
showPackBlips: prefs.getBool(_prefKeyPack) ?? true,
|
|
showTwistyHighlights: prefs.getBool(_prefKeyTwisty) ?? true,
|
|
offlineOnly: prefs.getBool(_prefKeyOffline) ?? false,
|
|
);
|
|
} catch (_) {}
|
|
}
|
|
|
|
Future<void> setStyle(TacticalMapStyle style) async {
|
|
state = state.copyWith(style: style);
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString(_prefKeyStyle, style.name);
|
|
} catch (_) {}
|
|
}
|
|
|
|
Future<void> togglePoliceTraps(bool val) async {
|
|
state = state.copyWith(showPoliceTraps: val);
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setBool(_prefKeyTraps, val);
|
|
} catch (_) {}
|
|
}
|
|
|
|
Future<void> togglePackBlips(bool val) async {
|
|
state = state.copyWith(showPackBlips: val);
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setBool(_prefKeyPack, val);
|
|
} catch (_) {}
|
|
}
|
|
|
|
Future<void> toggleTwistyHighlights(bool val) async {
|
|
state = state.copyWith(showTwistyHighlights: val);
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setBool(_prefKeyTwisty, val);
|
|
} catch (_) {}
|
|
}
|
|
|
|
Future<void> toggleOfflineOnly(bool val) async {
|
|
state = state.copyWith(offlineOnly: val);
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setBool(_prefKeyOffline, val);
|
|
} catch (_) {}
|
|
}
|
|
|
|
Future<void> resetToDefaults() async {
|
|
state = const MapLayerSettings();
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.remove(_prefKeyStyle);
|
|
await prefs.remove(_prefKeyTraps);
|
|
await prefs.remove(_prefKeyPack);
|
|
await prefs.remove(_prefKeyTwisty);
|
|
await prefs.remove(_prefKeyOffline);
|
|
} catch (_) {}
|
|
}
|
|
}
|
|
|
|
final mapLayerSettingsProvider =
|
|
StateNotifierProvider<MapLayerSettingsNotifier, MapLayerSettings>((ref) {
|
|
return MapLayerSettingsNotifier();
|
|
});
|