import 'package:flutter/foundation.dart'; import 'parse.dart'; /// Settings as a component reported them, overlaid with the HUD's optimistic /// writes (plan P4, reused by the gimbal in P5). /// /// A pending value stands until the component reports that setting changed, /// the write fails, or the writer gives up waiting ([dropPending]) — so a /// value the component silently refused snaps back. mixin SettingsOverlay on ChangeNotifier { Map _reported = const {}; final Map _pending = {}; /// What the component reported, overlaid with pending writes. Map get settings => _pending.isEmpty ? _reported : {..._reported, ..._pending}; /// Only what the component itself reported. Map get reportedSettings => _reported; bool isPending(String id) => _pending.containsKey(id); Object? setting(String id) => settings[id]; /// Shows [values] ahead of the component's read-back. void setPending(Map values) { _pending.addAll(values); notifyListeners(); } /// Rolls [ids] back to what the component last reported. void dropPending(Iterable ids) { bool changed = false; for (final String id in ids) { changed = _pending.remove(id) != null || changed; } if (changed) notifyListeners(); } /// Takes a new report; a pending write is answered once its setting moves. /// Does not notify — the caller does, with its other fields. @protected void replaceReported(Map reported) { _pending.removeWhere((String id, _) => !deepEquals(_reported[id], reported[id])); _reported = reported; } @protected void clearSettings() { _reported = const {}; _pending.clear(); } }