// update_dialog.dart — 「发现新版本」更新提示弹窗。 // // 只做「展示 + 引导下载」:点「下载更新」用 url_launcher 打开对应平台的下载直链 // (浏览器下载),不做应用内静默安装/自动重启。force_update=true 时不可关闭 // (无「稍后」按钮、点遮罩/返回也关不掉)。 import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import '../l10n/app_text.dart'; import '../pangolin_theme.dart'; import '../state/update_provider.dart'; import 'pangolin_icons.dart'; /// 展示更新弹窗。调用方(设置页「检查更新」)在拿到 `info.hasUpdate == true` 时调用。 Future showUpdateDialog(BuildContext context, AppText t, AppUpdateInfo info) { return showDialog( context: context, barrierDismissible: !info.forceUpdate, builder: (ctx) => PopScope( canPop: !info.forceUpdate, child: _UpdateDialog(t: t, info: info), ), ); } class _UpdateDialog extends StatelessWidget { const _UpdateDialog({required this.t, required this.info}); final AppText t; final AppUpdateInfo info; @override Widget build(BuildContext context) { final c = context.pangolin; return AlertDialog( backgroundColor: c.surface, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(PangolinRadius.xl)), title: Row(children: [ Container( width: 34, height: 34, decoration: BoxDecoration(color: c.accentSubtle, shape: BoxShape.circle), child: Icon(PangolinIcons.zap, size: 18, color: c.accent), ), const SizedBox(width: 12), Expanded( child: Text( t.updateAvailableTitle(info.latestVersion), overflow: TextOverflow.ellipsis, style: PangolinText.body.copyWith(color: c.fg1, fontWeight: FontWeight.w700), ), ), ]), content: SingleChildScrollView( child: Text( info.releaseNotes.isEmpty ? t.updateNotesFallback : info.releaseNotes, style: PangolinText.sm.copyWith(color: c.fg2, height: 1.5), ), ), actions: [ if (!info.forceUpdate) TextButton( onPressed: () => Navigator.of(context).pop(), child: Text(t.updateLater, style: PangolinText.sm.copyWith(color: c.fg2, fontWeight: FontWeight.w600)), ), TextButton( onPressed: () async { final url = platformDownloadUrl(info.downloadUrls); if (url != null && url.isNotEmpty) { final uri = Uri.parse(url); if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } } if (context.mounted) Navigator.of(context).pop(); }, child: Text(t.updateDownload, style: PangolinText.sm.copyWith(color: c.accent, fontWeight: FontWeight.w700)), ), ], ); } }