SSO: web_launch.openWebUserCenter → POST /v1/auth/web-ticket → 打开 app.yanmeiai.com/sso?t=…; 设置页加「用户中心(网页)」入口。自动更新: update_provider 查 /version 语义比对 + update_dialog 「发现新版本」;设置页「检查更新」由空 onTap 接上。加 url_launcher(原缺)。flutter analyze 通过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// 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<void> showUpdateDialog(BuildContext context, AppText t, AppUpdateInfo info) {
|
||||
return showDialog<void>(
|
||||
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)),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user