Optimize automatic updates

This commit is contained in:
2026-05-31 09:32:32 +08:00
parent 8dfc22691a
commit 61ad85f6fc
4 changed files with 175 additions and 98 deletions
+43 -86
View File
@@ -1,5 +1,3 @@
import 'dart:io';
import 'package:flutter/material.dart';
import '../../data/models/app_update_model.dart';
@@ -31,6 +29,8 @@ class _UpdatePromptState extends State<UpdatePrompt> {
final update = await UpdateService.instance.checkForUpdate();
if (update == null || !mounted) return;
final shouldShow = await UpdateService.instance.shouldShowPrompt(update);
if (!shouldShow || !mounted) return;
_dialogVisible = true;
try {
@@ -41,98 +41,55 @@ class _UpdatePromptState extends State<UpdatePrompt> {
}
Future<void> _showUpdateDialog(AppUpdateInfo update) async {
var downloading = false;
var progress = 0.0;
String? status;
await showDialog<void>(
context: context,
barrierDismissible: false,
builder: (dialogContext) {
return StatefulBuilder(
builder: (context, setDialogState) {
final canDownload =
update.downloadUrl != null &&
(Platform.isAndroid || Platform.isWindows);
Future<void> openDownloadsPage() async {
try {
await UpdateService.instance.openDownloadsPage();
if (dialogContext.mounted) Navigator.of(dialogContext).pop();
} catch (e) {
ToastHelper.failure('打开下载页面失败: $e');
}
}
Future<void> startUpdate() async {
if (downloading || !canDownload) return;
Future<void> skipPrompt() async {
await UpdateService.instance.skipPromptForFiveDays(update);
if (dialogContext.mounted) Navigator.of(dialogContext).pop();
}
setDialogState(() {
downloading = true;
progress = 0;
status = '正在下载更新...';
});
final releaseNotes = (update.description ?? '').trim();
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 ?? ''),
],
],
),
return AlertDialog(
title: Text('发现新版本 ${update.version}'),
content: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 420, maxHeight: 360),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('新版本号:${update.version}'),
const SizedBox(height: 12),
Text(
'版本日志',
style: Theme.of(dialogContext).textTheme.titleSmall,
),
const SizedBox(height: 6),
Text(releaseNotes.isEmpty ? update.title : releaseNotes),
],
),
actions: [
TextButton(
onPressed: downloading
? null
: () => Navigator.of(dialogContext).pop(),
child: const Text('稍后'),
),
FilledButton(
onPressed: downloading ? null : startUpdate,
child: const Text('立即更新'),
),
],
);
},
),
),
actions: [
TextButton(onPressed: skipPrompt, child: const Text('跳过')),
TextButton(
onPressed: () => Navigator.of(dialogContext).pop(),
child: const Text('取消'),
),
FilledButton(onPressed: openDownloadsPage, child: const Text('更新')),
],
);
},
);