feat(mobile-app): 非强制更新时下载完成后让用户选择是否安装

- 强制更新:下载完成后自动安装
- 非强制更新:下载完成后显示"稍后安装"和"立即安装"按钮
- 更新提示对话框中"稍后"改为"暂时不更新"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-27 20:20:47 -08:00
parent fe593714ae
commit 9c7dc6f511
1 changed files with 68 additions and 7 deletions

View File

@ -1,3 +1,4 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../version_checker.dart';
@ -202,7 +203,7 @@ class SelfHostedUpdater {
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(
'稍后',
'暂时不更新',
style: TextStyle(
fontSize: 14.sp,
color: const Color(0xFF78716C),
@ -240,6 +241,7 @@ class SelfHostedUpdater {
builder: (context) => _DownloadProgressDialog(
versionInfo: versionInfo,
downloadManager: downloadManager,
forceUpdate: versionInfo.forceUpdate,
),
);
}
@ -254,10 +256,12 @@ class SelfHostedUpdater {
class _DownloadProgressDialog extends StatefulWidget {
final VersionInfo versionInfo;
final DownloadManager downloadManager;
final bool forceUpdate;
const _DownloadProgressDialog({
required this.versionInfo,
required this.downloadManager,
required this.forceUpdate,
});
@override
@ -270,6 +274,8 @@ class _DownloadProgressDialogState extends State<_DownloadProgressDialog> {
String _statusText = '准备下载...';
bool _isDownloading = true;
bool _hasError = false;
bool _downloadCompleted = false;
File? _downloadedApkFile;
@override
void initState() {
@ -282,6 +288,7 @@ class _DownloadProgressDialogState extends State<_DownloadProgressDialog> {
_statusText = '正在下载...';
_isDownloading = true;
_hasError = false;
_downloadCompleted = false;
});
final apkFile = await widget.downloadManager.downloadApk(
@ -312,13 +319,34 @@ class _DownloadProgressDialogState extends State<_DownloadProgressDialog> {
return;
}
_downloadedApkFile = apkFile;
//
//
if (widget.forceUpdate) {
setState(() {
_statusText = '下载完成,准备安装...';
});
await Future.delayed(const Duration(milliseconds: 500));
await _installApk();
} else {
setState(() {
_statusText = '下载完成';
_isDownloading = false;
_downloadCompleted = true;
});
}
}
Future<void> _installApk() async {
if (_downloadedApkFile == null) return;
setState(() {
_statusText = '下载完成,准备安装...';
_statusText = '正在安装...';
_isDownloading = true;
});
await Future.delayed(const Duration(milliseconds: 500));
final installed = await ApkInstaller.installApk(apkFile);
final installed = await ApkInstaller.installApk(_downloadedApkFile!);
if (!mounted) return;
@ -344,11 +372,20 @@ class _DownloadProgressDialogState extends State<_DownloadProgressDialog> {
@override
Widget build(BuildContext context) {
String title;
if (_downloadCompleted && !_hasError) {
title = '下载完成';
} else if (_hasError) {
title = '更新失败';
} else {
title = '正在更新';
}
return PopScope(
canPop: !_isDownloading,
canPop: !_isDownloading && !widget.forceUpdate,
child: AlertDialog(
title: Text(
'正在更新',
title,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
@ -423,6 +460,30 @@ class _DownloadProgressDialogState extends State<_DownloadProgressDialog> {
),
),
],
//
if (_downloadCompleted && !_hasError) ...[
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(
'稍后安装',
style: TextStyle(
fontSize: 14.sp,
color: const Color(0xFF78716C),
),
),
),
ElevatedButton(
onPressed: _installApk,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFD4A84B),
foregroundColor: Colors.white,
),
child: Text(
'立即安装',
style: TextStyle(fontSize: 14.sp),
),
),
],
],
),
);