import 'dart:ui'; import 'package:flutter/material.dart'; typedef RewardAddTimeHandler = Future Function(void Function(int sec) grant); class ResultModal extends StatefulWidget { final bool visible; final String status; final int score; final int bestScore; final bool hasNext; final VoidCallback onRetry; final VoidCallback onNext; final bool showAddTime; final int addTimeSeconds; final RewardAddTimeHandler? onRequestRewardAddTime; const ResultModal({ super.key, required this.visible, required this.status, required this.score, required this.bestScore, required this.hasNext, required this.onRetry, required this.onNext, this.showAddTime = false, this.addTimeSeconds = 30, this.onRequestRewardAddTime, }); @override State createState() => _ResultModalState(); } class _ResultModalState extends State { String? toast; bool rewardLoading = false; void showToast(String msg) { setState(() => toast = msg); Future.delayed(const Duration(milliseconds: 1800), () { if (mounted && toast == msg) { setState(() => toast = null); } }); } Future _handleRewardAddTime() async { if (rewardLoading) return; setState(() => rewardLoading = true); try { if (widget.onRequestRewardAddTime != null) { await widget.onRequestRewardAddTime!((_) {}); } } catch (_) { showToast('Rewarded ad failed to load. Please try again.'); } finally { if (mounted) { setState(() => rewardLoading = false); } } } @override Widget build(BuildContext context) { if (!widget.visible) return const SizedBox.shrink(); final isWin = widget.status == 'won'; final showNext = isWin && widget.hasNext; final showAddTime = !isWin && widget.showAddTime; return Positioned.fill( child: Material( color: Colors.transparent, child: Stack( children: [ Positioned.fill( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8), child: Container(color: const Color.fromRGBO(0, 0, 0, 0.35)), ), ), Center( child: Container( width: MediaQuery.of(context).size.width.clamp(0, 520).toDouble(), margin: const EdgeInsets.symmetric(horizontal: 16), child: AspectRatio( aspectRatio: 0.67, child: Stack( fit: StackFit.expand, children: [ Positioned.fill( child: Image.asset( isWin ? 'assets/images/settlement/win.png' : 'assets/images/settlement/lose.png', fit: BoxFit.fill, ), ), Positioned.fill( child: Padding( padding: const EdgeInsets.fromLTRB(34, 168, 34, 32), child: Column( children: [ Text( 'Best Score', style: TextStyle( fontSize: isWin ? 22 : 20, fontWeight: FontWeight.w900, color: isWin ? const Color(0xFFB944D7) : const Color(0xFF4F6BDE), ), ), const SizedBox(height: 16), Image.asset( 'assets/images/settlement/gold.png', width: 118, height: 118, ), const SizedBox(height: 12), Text( '${widget.bestScore}', textAlign: TextAlign.center, style: TextStyle( fontSize: isWin ? 38 : 34, fontWeight: FontWeight.w900, color: isWin ? const Color(0xFFFF6CA8) : const Color(0xFF4F6BDE), letterSpacing: 1, ), ), const Spacer(), Row( children: [ if (showNext) ...[ Expanded( child: _ActionImageButton( asset: 'assets/images/settlement/next.png', onTap: widget.onNext, ), ), const SizedBox(width: 14), ], if (showAddTime) ...[ Expanded( child: _ActionImageButton( asset: 'assets/images/settlement/addTime.png', onTap: widget.onRequestRewardAddTime == null ? null : _handleRewardAddTime, ), ), const SizedBox(width: 14), ], Expanded( child: _ActionImageButton( asset: 'assets/images/settlement/retry.png', onTap: widget.onRetry, ), ), ], ), if (toast != null) ...[ const SizedBox(height: 12), Text( toast!, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w700, ), textAlign: TextAlign.center, ), ], ], ), ), ), ], ), ), ), ), ], ), ), ); } } class _ActionImageButton extends StatelessWidget { const _ActionImageButton({ required this.asset, required this.onTap, }); final String asset; final VoidCallback? onTap; @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Opacity( opacity: onTap == null ? 0.55 : 1, child: SizedBox( height: 56, child: Image.asset(asset, fit: BoxFit.fill), ), ), ); } }