import 'dart:async'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../common/router/app_router.dart'; import '../data/ads_api_client.dart'; import '../presentation/splash_ad_dialog.dart'; import 'splash_ad_controller.dart'; final startupAdResolvedProvider = StateProvider((_) => false); abstract final class StartupAdService { static Future? _running; static Future showIfAvailable(BuildContext context, WidgetRef ref) => _running ??= _show(context, ref); static Future _show(BuildContext context, WidgetRef ref) async { final controller = ref.read(splashAdControllerProvider); try { final entry = await controller.coldLaunchDecision(); if (entry != null && context.mounted) { final result = await showGeneralDialog( context: context, useRootNavigator: true, barrierDismissible: false, barrierColor: Colors.black, pageBuilder: (ctx, _, _) => SplashAdDialog( entry: entry, onShown: () => unawaited(controller.markShown(entry)), onClick: () async { final id = ref.read(adsApiClientProvider).newClickId(); final uri = entry.ad.clickUri(id); if (uri != null) { unawaited( ref .read(adsApiClientProvider) .report(entry.ad, 'ad_click', clickId: id), ); if (entry.ad.openMode == AdOpenMode.inApp) { context.push( '${AppRoutes.web}?url=${Uri.encodeComponent(uri.toString())}', ); } else { await launchUrl(uri, mode: LaunchMode.externalApplication); } } }, ), ); if (result == SplashAdResult.skipped) unawaited(controller.skip(entry)); } } finally { ref.read(startupAdResolvedProvider.notifier).state = true; unawaited(controller.refresh()); } } }