074a21ea2b
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
42 lines
1.1 KiB
Dart
42 lines
1.1 KiB
Dart
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(skipped: false);
|
|
}
|
|
|
|
Future<void> skip() async {
|
|
if (state == null) return;
|
|
await _finish(skipped: true);
|
|
}
|
|
|
|
Future<void> _finish({required bool skipped}) async {
|
|
state = null;
|
|
ref.read(analyticsProvider).tutorialFinished(skipped: skipped);
|
|
await ref.read(saveRepositoryProvider).markTutorialDone();
|
|
}
|
|
}
|