108 lines
3.9 KiB
Dart
108 lines
3.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
/// 强制更新页:检测到新版本时的全屏阻塞页。
|
|
/// PopScope 禁返回(Android 系统返回 / iOS 边缘滑动均不可退出)。
|
|
/// 2026-09-03 改为浏览器下载:App 内 PackageInstaller 会话安装在小米等
|
|
/// ROM 上点系统确认框后失败(下载/写入正常但最终安装被拒),而系统浏览器
|
|
/// 下载 APK 后经通知栏走 ROM 自己的安装器可正常完成,故下载链接改由浏览器
|
|
/// 打开,不再 App 内下载/安装。仅点「立即更新」按钮时打开浏览器,不自动
|
|
/// 跳转;安装完成(versionName 追上服务器)后下次启动不再提示。
|
|
class UpdateScreen extends StatefulWidget {
|
|
final String version;
|
|
final String url;
|
|
final String notes;
|
|
|
|
const UpdateScreen({
|
|
super.key,
|
|
required this.version,
|
|
required this.url,
|
|
this.notes = '',
|
|
});
|
|
|
|
@override
|
|
State<UpdateScreen> createState() => _UpdateScreenState();
|
|
}
|
|
|
|
class _UpdateScreenState extends State<UpdateScreen> {
|
|
String? _message;
|
|
|
|
Future<void> _openBrowser() async {
|
|
final uri = Uri.tryParse(widget.url);
|
|
if (uri == null) {
|
|
setState(() => _message = '下载链接无效,请联系管理员');
|
|
return;
|
|
}
|
|
try {
|
|
final ok = await launchUrl(uri, mode: LaunchMode.externalApplication);
|
|
if (!mounted) return;
|
|
setState(() {
|
|
_message = ok ? '已打开浏览器下载,完成后点击通知栏的安装提示即可更新' : '打开浏览器失败,请点「立即更新」重试';
|
|
});
|
|
} catch (_) {
|
|
if (!mounted) return;
|
|
setState(() => _message = '打开浏览器失败,请点「立即更新」重试');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final theme = Theme.of(context);
|
|
return PopScope(
|
|
canPop: false,
|
|
child: Scaffold(
|
|
body: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(32),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(Icons.system_update_alt,
|
|
size: 64, color: theme.colorScheme.primary),
|
|
const SizedBox(height: 16),
|
|
Text('发现新版本 ${widget.version}',
|
|
style: theme.textTheme.headlineSmall),
|
|
const SizedBox(height: 12),
|
|
if (widget.notes.isNotEmpty)
|
|
Text(widget.notes,
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(height: 1.6)),
|
|
const SizedBox(height: 24),
|
|
FilledButton.icon(
|
|
onPressed: _openBrowser,
|
|
icon: const Icon(Icons.open_in_browser),
|
|
label: const Text('立即更新'),
|
|
style: FilledButton.styleFrom(
|
|
minimumSize: const Size(200, 48),
|
|
textStyle: const TextStyle(fontSize: 16),
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
'新版本需在浏览器下载 APK 后手动安装\n安装完成后请重新打开应用',
|
|
textAlign: TextAlign.center,
|
|
style: theme.textTheme.bodySmall
|
|
?.copyWith(color: theme.colorScheme.error),
|
|
),
|
|
if (_message != null) ...[
|
|
const SizedBox(height: 12),
|
|
Text(
|
|
_message!,
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(
|
|
height: 1.5,
|
|
color: _message!.startsWith('已打开')
|
|
? Colors.green
|
|
: theme.colorScheme.error,
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|