fix(phasen): Tageswechsel laedt Phasen-Stand der neuen Tour (Reset), alter Tag bleibt
Beim Datumswechsel im Kopf-Kalender blieben Beladen/Ausliefern des alten Tags 'erledigt': PhaseBloc._load brach bei bereits geladenem Auto ab und Home stiess den Load nur einmal pro Auto an - der In-Memory-Stand wurde beim Tour-/Token-Wechsel nie invalidiert. Die Persistenz ist bereits pro Tour-Token (syncedAt) getrennt, nur das Nachladen fehlte. - PhaseBloc: Guard tokenbewusst (_loadedTokenByCar); anderer Token laedt den persistierten Stand der neuen Tour nach (neuer Tag -> Eintrittsphase, Rueckkehr -> alter Stand wiederhergestellt) - Home._ensurePhaseLoaded: Guard auf carId|tourToken statt nur carId - Token-Ableitung zentral als TourState.phaseToken (tour_state.dart), genutzt von tourTokenResolver (app.dart) UND Home - eine Quelle statt Duplikat Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -43,6 +43,13 @@ class PhaseBloc extends Bloc<PhaseEvent, PhaseState> {
|
||||
/// Phasen an die aktuelle Tour-Version.
|
||||
final TourTokenResolver? tourTokenResolver;
|
||||
|
||||
/// Merkt sich pro Fahrzeug, unter welchem Tour-Token der In-Memory-Stand
|
||||
/// geladen wurde. Ändert sich der Token (Tageswechsel im Kopf-Kalender,
|
||||
/// neuer Sync), lädt der nächste [PhaseLoadForCar] den persistierten Stand
|
||||
/// der **neuen** Tour nach, statt den alten Tag weiterzuzeigen. Der alte
|
||||
/// Tag bleibt persistiert und wird bei Rückkehr wiederhergestellt.
|
||||
final Map<String, String> _loadedTokenByCar = {};
|
||||
|
||||
PhaseBloc({
|
||||
PhaseService? phaseService,
|
||||
this.carCountResolver,
|
||||
@ -77,11 +84,18 @@ class PhaseBloc extends Bloc<PhaseEvent, PhaseState> {
|
||||
|
||||
Future<void> _load(PhaseLoadForCar event, Emitter<PhaseState> emit) async {
|
||||
final current = _ensureReady();
|
||||
// Wenn bereits geladen, nichts tun — der Stepper-Tap entscheidet aktiv.
|
||||
if (current.phaseByCar.containsKey(event.carId)) return;
|
||||
final token = _token();
|
||||
// Bereits für GENAU diese Tour-Version geladen → nichts tun (der
|
||||
// Stepper-Tap entscheidet aktiv). Ein anderer Token (Tageswechsel, neuer
|
||||
// Sync) lädt den persistierten Stand der neuen Tour nach: ein neuer Tag
|
||||
// startet so wieder in der Eintrittsphase (Beladen/Ausliefern zurück),
|
||||
// der vorherige Tag behält seinen Stand für die Rückkehr.
|
||||
if (current.phaseByCar.containsKey(event.carId) &&
|
||||
_loadedTokenByCar[event.carId] == token) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final token = _token();
|
||||
final persisted = await phaseService.load(event.carId, token);
|
||||
final persistedMax = await phaseService.loadMax(event.carId, token);
|
||||
final phase = persisted ?? _entryPhase();
|
||||
@ -102,6 +116,7 @@ class PhaseBloc extends Bloc<PhaseEvent, PhaseState> {
|
||||
await phaseService.saveMax(event.carId, token, maxPhase);
|
||||
}
|
||||
|
||||
_loadedTokenByCar[event.carId] = token;
|
||||
add(PhaseLoaded(
|
||||
carId: event.carId,
|
||||
phase: phase,
|
||||
@ -111,6 +126,7 @@ class PhaseBloc extends Bloc<PhaseEvent, PhaseState> {
|
||||
debugPrint("PhaseBloc._load: $e $st");
|
||||
// Fail-soft: ohne Persistenz weiter, damit der Flow nicht hängen bleibt.
|
||||
final fallback = _entryPhase();
|
||||
_loadedTokenByCar[event.carId] = token;
|
||||
add(PhaseLoaded(
|
||||
carId: event.carId,
|
||||
phase: fallback,
|
||||
|
||||
@ -93,3 +93,22 @@ const Object _sentinel = Object();
|
||||
class TourEmpty extends TourState {
|
||||
const TourEmpty();
|
||||
}
|
||||
|
||||
/// Token, der die aktuell geladene **Tour-Version** identifiziert (aus
|
||||
/// `Tour.syncedAt`). Der `PhaseBloc` bindet die persistierten Phasen-Häkchen
|
||||
/// daran: ein Tageswechsel im Kopf-Kalender oder ein neuer Sync ergibt einen
|
||||
/// neuen Token und damit einen eigenen, getrennten Phasen-Stand. `null` =
|
||||
/// keine Tour geladen (z. B. `TourEmpty`).
|
||||
///
|
||||
/// **Einzige Quelle** für diese Ableitung — wird vom `tourTokenResolver` in
|
||||
/// `app.dart` UND von `Home._ensurePhaseLoaded` genutzt, damit beide Seiten
|
||||
/// garantiert denselben Token sehen und ein Tour-Wechsel zuverlässig als
|
||||
/// solcher erkannt wird.
|
||||
extension TourStatePhaseToken on TourState {
|
||||
String? get phaseToken {
|
||||
final s = this;
|
||||
return s is TourLoaded
|
||||
? s.details.tour.syncedAt.millisecondsSinceEpoch.toString()
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user