feat: tutorial step state machine with persistence

Adds TutorialNotifier (dragPiece → clearLine → explainHud → null) backed
by SaveRepository.markTutorialDone(); out-of-order events are silently
ignored. Registers tutorialProvider in providers.dart.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 22:50:49 +09:00
parent f97b4faad7
commit 3d1f3b30c7
3 changed files with 105 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'providers.dart';
enum TutorialStep { dragPiece, clearLine, explainHud }
/// First-play guided tutorial. State null = inactive. Events arriving in the
/// wrong step are ignored, so engine wiring can fire them unconditionally.
class TutorialNotifier extends Notifier<TutorialStep?> {
@override
TutorialStep? build() => null;
void start() {
if (ref.read(saveRepositoryProvider).tutorialDone) return;
state = TutorialStep.dragPiece;
}
void onPlaced() {
if (state == TutorialStep.dragPiece) state = TutorialStep.clearLine;
}
void onLineCleared() {
if (state == TutorialStep.clearLine) state = TutorialStep.explainHud;
}
Future<void> dismissHud() async {
if (state != TutorialStep.explainHud) return;
await _finish();
}
Future<void> skip() async {
if (state == null) return;
await _finish();
}
Future<void> _finish() async {
state = null;
await ref.read(saveRepositoryProvider).markTutorialDone();
}
}