import 'dart:async'; import 'package:flutter/material.dart'; import '../application/splash_ad_controller.dart'; import 'ad_media.dart'; enum SplashAdResult { clicked, skipped, completed } class SplashAdDialog extends StatefulWidget { const SplashAdDialog({ super.key, required this.entry, required this.onClick, required this.onShown, }); final SplashAdEntry entry; final Future Function() onClick; final VoidCallback onShown; @override State createState() => _SplashAdDialogState(); } class _SplashAdDialogState extends State { Timer? timer; late int remain; bool opening = false; @override void initState() { super.initState(); remain = widget.entry.ad.countdownSeconds.clamp(1, 5); WidgetsBinding.instance.addPostFrameCallback((_) { widget.onShown(); }); timer = Timer.periodic(const Duration(seconds: 1), (_) { if (remain <= 1) { Navigator.of(context).pop(SplashAdResult.completed); } else if (mounted) { setState(() => remain--); } }); } @override void dispose() { timer?.cancel(); super.dispose(); } Future open() async { if (opening) return; opening = true; timer?.cancel(); await widget.onClick(); if (mounted) Navigator.of(context).pop(SplashAdResult.clicked); } @override Widget build(BuildContext context) => Material( color: Colors.black, child: Stack( children: [ Positioned.fill( child: GestureDetector( onTap: open, child: AdMedia( ad: widget.entry.ad, assetPath: widget.entry.assetPath, ), ), ), Positioned( top: MediaQuery.paddingOf(context).top + 16, right: 18, child: FilledButton( onPressed: () => Navigator.of(context).pop(SplashAdResult.skipped), child: Text('跳过 ${remain}s'), ), ), ], ), ); }