Files
BlockSeasons/lib/state/season_flow_notifier.dart
T
airkjw bf7720ebd3 fix: clear season flow when starting Classic so tutorial/theme can't leak
- Add SeasonFlowNotifier.clear() to null out the flow state
- Call clear() in HomeScreen's Classic button before startStage()
- Broaden tutorial-end guard to next.phase != GamePhase.playing (covers stuck)
- Add regression test: clear() resets flow to null

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 07:33:41 +09:00

49 lines
1.4 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../game/models/season.dart';
import '../game/models/stage.dart';
import 'providers.dart';
class SeasonFlow {
const SeasonFlow({required this.pack, required this.index});
final SeasonPack pack;
final int index;
StageConfig get stage => pack.stages[index];
bool get hasNext => index + 1 < pack.stages.length;
}
/// Orchestrates which season stage is being played: starting stages,
/// recording wins, advancing to the next stage.
class SeasonFlowNotifier extends Notifier<SeasonFlow?> {
@override
SeasonFlow? build() => null;
void startSeasonStage(SeasonPack pack, int index) {
state = SeasonFlow(pack: pack, index: index);
ref.read(gameSessionProvider.notifier).startStage(pack.stages[index]);
}
Future<void> recordWin({required int stars, required int score}) async {
final flow = state;
if (flow == null) return;
await ref.read(progressProvider.notifier).record(
seasonId: flow.pack.seasonId,
stageId: flow.stage.id,
stars: stars,
score: score,
);
}
void nextStage() {
final flow = state;
if (flow == null || !flow.hasNext) return;
startSeasonStage(flow.pack, flow.index + 1);
}
/// Leaving season play (e.g. starting a Classic run) clears the flow so
/// stale stage context can't leak into other modes.
void clear() => state = null;
}