import 'dart:io'; import 'package:flutter/material.dart'; import '../../data/models/app_update_model.dart'; import '../../services/update_service.dart'; import 'toast_helper.dart'; class UpdatePrompt extends StatefulWidget { final Widget child; const UpdatePrompt({super.key, required this.child}); @override State createState() => _UpdatePromptState(); } class _UpdatePromptState extends State { static bool _checkedThisRun = false; bool _dialogVisible = false; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) => _checkUpdate()); } Future _checkUpdate() async { if (_checkedThisRun || _dialogVisible || !mounted) return; _checkedThisRun = true; final update = await UpdateService.instance.checkForUpdate(); if (update == null || !mounted) return; _dialogVisible = true; try { await _showUpdateDialog(update); } finally { _dialogVisible = false; } } Future _showUpdateDialog(AppUpdateInfo update) async { var downloading = false; var progress = 0.0; String? status; await showDialog( context: context, barrierDismissible: false, builder: (dialogContext) { return StatefulBuilder( builder: (context, setDialogState) { final canDownload = update.downloadUrl != null && (Platform.isAndroid || Platform.isWindows); Future startUpdate() async { if (downloading || !canDownload) return; setDialogState(() { downloading = true; progress = 0; status = '正在下载更新...'; }); try { final file = await UpdateService.instance.downloadUpdate( update, onProgress: (received, total) { if (!mounted || total <= 0) return; setDialogState(() { progress = received / total; }); }, ); if (file == null) return; setDialogState(() { progress = 1; status = '下载完成,正在打开安装包...'; }); await UpdateService.instance.openInstaller(file); if (dialogContext.mounted) Navigator.of(dialogContext).pop(); } catch (e) { setDialogState(() { downloading = false; status = '下载或打开安装包失败'; }); ToastHelper.failure('更新失败: $e'); } } return AlertDialog( title: Text('发现新版本 ${update.version}'), content: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(update.title), if ((update.description ?? '').isNotEmpty) ...[ const SizedBox(height: 12), Text( update.description!, maxLines: 6, overflow: TextOverflow.ellipsis, ), ], if (downloading) ...[ const SizedBox(height: 16), LinearProgressIndicator( value: progress == 0 ? null : progress, ), const SizedBox(height: 8), Text(status ?? ''), ], ], ), ), actions: [ TextButton( onPressed: downloading ? null : () => Navigator.of(dialogContext).pop(), child: const Text('稍后'), ), FilledButton( onPressed: downloading ? null : startUpdate, child: const Text('立即更新'), ), ], ); }, ); }, ); } @override Widget build(BuildContext context) => widget.child; }