import 'package:flutter/material.dart'; import '../../state/game_session_notifier.dart'; import 'board_painter.dart'; /// The board with clear-flash and combo-text effects. Pure display: drag /// orchestration lives in the game screen. class BoardWidget extends StatefulWidget { const BoardWidget({super.key, required this.view, required this.ghost}); final GameViewState view; final GhostSpec? ghost; @override State createState() => _BoardWidgetState(); } class _BoardWidgetState extends State with SingleTickerProviderStateMixin { late final AnimationController _flash = AnimationController( vsync: this, duration: const Duration(milliseconds: 350), ); List _flashRows = const []; List _flashCols = const []; @override void didUpdateWidget(BoardWidget old) { super.didUpdateWidget(old); final placement = widget.view.lastPlacement; if (widget.view.fxTick != old.view.fxTick && placement != null && placement.linesCleared > 0) { _flashRows = placement.clearedRows; _flashCols = placement.clearedCols; _flash.forward(from: 0); } } @override void dispose() { _flash.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AspectRatio( aspectRatio: 1, child: AnimatedBuilder( animation: _flash, builder: (context, _) { final fading = _flash.isAnimating ? 1 - _flash.value : 0.0; return Stack( fit: StackFit.expand, children: [ CustomPaint( painter: BoardPainter( grid: widget.view.grid, ghost: widget.ghost, flashProgress: fading, flashRows: _flashRows, flashCols: _flashCols, ), ), ], ); }, ), ); } }