import 'package:flutter/material.dart'; import '../../game/models/objective.dart'; import '../../state/game_session_notifier.dart'; class HudWidget extends StatelessWidget { const HudWidget({super.key, required this.view}); final GameViewState view; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: !view.endless, maintainSize: true, maintainAnimation: true, maintainState: true, child: _movesChip(theme), ), AnimatedSwitcher( duration: const Duration(milliseconds: 200), transitionBuilder: (child, anim) => ScaleTransition(scale: anim, child: child), child: Text( '${view.score}', key: ValueKey(view.score), style: theme.textTheme.headlineMedium ?.copyWith(fontWeight: FontWeight.w800), ), ), _comboChip(theme), ], ), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ for (final obj in view.objectives) ...[ _objectiveChip(theme, obj), const SizedBox(width: 12), ], ], ), ], ); } Widget _movesChip(ThemeData theme) { return Chip( avatar: const Icon(Icons.swipe, size: 18), label: Text('${view.movesLeft}'), labelStyle: theme.textTheme.titleMedium, ); } Widget _comboChip(ThemeData theme) { final visible = view.comboStreak >= 2; return AnimatedOpacity( duration: const Duration(milliseconds: 150), opacity: visible ? 1 : 0, child: Chip( avatar: const Icon(Icons.local_fire_department, size: 18, color: Colors.deepOrange), label: Text('x${view.comboStreak}'), labelStyle: theme.textTheme.titleMedium, ), ); } Widget _objectiveChip(ThemeData theme, Objective obj) { final (icon, color) = switch (obj) { ClearGemsObjective() => (Icons.diamond, const Color(0xFF7CF5FF)), ReachScoreObjective() => (Icons.star, Colors.amber), ClearLinesObjective() => (Icons.table_rows, Colors.lightGreen), }; final done = obj.isComplete; return Chip( avatar: Icon(done ? Icons.check_circle : icon, size: 18, color: color), label: Text('${obj.current.clamp(0, obj.target)}/${obj.target}'), labelStyle: theme.textTheme.titleSmall, ); } }