import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'virtual_sticks.dart' show StickMode; /// The video overlay grid (camera menu → Other, and the rail's GRID button). enum GridStyle { off('Off'), thirds('Grid'), diagonals('Grid + diagonals'); const GridStyle(this.label); final String label; } /// What a long press on the live view does (GO 4's "Long Press" setting); a /// single tap always focuses, or meters on fixed-focus cameras. enum LongPressAction { meter('Spot meter'), focus('Focus'), off('Nothing'); const LongPressAction(this.label); final String label; } /// Device-local switches for the flight screen, persisted across launches. abstract final class FlyPrefs { static const String _classicKey = 'fly.classicHud'; static const String _perfKey = 'fly.perfOverlay'; static const String _gridKey = 'fly.grid'; static const String _centerKey = 'fly.centerPoint'; static const String _longPressKey = 'fly.longPress'; static const String _routeKey = 'fly.showRoute'; static const String _termsKey = 'fly.modeTerms'; static const String _radarKey = 'fly.radar'; static const String _stickModeKey = 'fly.stickMode'; static const String _sticksRealKey = 'fly.sticksRealFlight'; /// Open the pre-P2 `FlightControlPage` instead of the HUD v2 — kept /// reachable until P3's safety flows pass their simulator run (plan P2/P3). static final ValueNotifier classicHud = ValueNotifier(false); /// Flutter's performance overlay on the flight screen, for the P2 "no jank at /// 10 Hz" check. static final ValueNotifier perfOverlay = ValueNotifier(false); static final ValueNotifier grid = ValueNotifier(GridStyle.off); static final ValueNotifier centerPoint = ValueNotifier(true); static final ValueNotifier longPress = ValueNotifier(LongPressAction.meter); /// Draw the flown trail on the map (settings → General). static final ValueNotifier showRoute = ValueNotifier(true); /// Intelligent flight modes whose first-use terms the pilot accepted (plan P7), by name. static final ValueNotifier> acceptedModeTerms = ValueNotifier>({}); /// Draw the vision radar on the video (GO 4's "Display Radar Chart", plan P8). static final ValueNotifier showRadar = ValueNotifier(true); /// What each on-screen stick does (plan P8); matches the remote's stick mode by default. static final ValueNotifier stickMode = ValueNotifier(StickMode.mode2); /// Developer switch: allow on-screen sticks outside the simulator on aircraft /// that have a remote. Off by default (plan P8: simulator first). static final ValueNotifier sticksInRealFlight = ValueNotifier(false); static SharedPreferences? _prefs; static Future load() async { try { _prefs = await SharedPreferences.getInstance(); classicHud.value = _prefs!.getBool(_classicKey) ?? false; perfOverlay.value = _prefs!.getBool(_perfKey) ?? false; grid.value = _byName(GridStyle.values, _prefs!.getString(_gridKey)) ?? GridStyle.off; centerPoint.value = _prefs!.getBool(_centerKey) ?? true; longPress.value = _byName(LongPressAction.values, _prefs!.getString(_longPressKey)) ?? LongPressAction.meter; showRoute.value = _prefs!.getBool(_routeKey) ?? true; acceptedModeTerms.value = (_prefs!.getStringList(_termsKey) ?? const []).toSet(); showRadar.value = _prefs!.getBool(_radarKey) ?? true; stickMode.value = _byName(StickMode.values, _prefs!.getString(_stickModeKey)) ?? StickMode.mode2; sticksInRealFlight.value = _prefs!.getBool(_sticksRealKey) ?? false; } catch (_) { // Storage unavailable: run on the defaults. } } static Future setClassicHud(bool on) async { classicHud.value = on; await _prefs?.setBool(_classicKey, on); } static Future setPerfOverlay(bool on) async { perfOverlay.value = on; await _prefs?.setBool(_perfKey, on); } static Future setGrid(GridStyle g) async { grid.value = g; await _prefs?.setString(_gridKey, g.name); } static Future setCenterPoint(bool on) async { centerPoint.value = on; await _prefs?.setBool(_centerKey, on); } static Future setLongPress(LongPressAction a) async { longPress.value = a; await _prefs?.setString(_longPressKey, a.name); } static Future setShowRoute(bool on) async { showRoute.value = on; await _prefs?.setBool(_routeKey, on); } static Future acceptModeTerms(String mode) async { if (acceptedModeTerms.value.contains(mode)) return; acceptedModeTerms.value = {...acceptedModeTerms.value, mode}; await _prefs?.setStringList(_termsKey, acceptedModeTerms.value.toList()..sort()); } static Future setShowRadar(bool on) async { showRadar.value = on; await _prefs?.setBool(_radarKey, on); } static Future setStickMode(StickMode m) async { stickMode.value = m; await _prefs?.setString(_stickModeKey, m.name); } static Future setSticksInRealFlight(bool on) async { sticksInRealFlight.value = on; await _prefs?.setBool(_sticksRealKey, on); } static T? _byName(List values, String? name) { for (final T v in values) { if (v.name == name) return v; } return null; } }