feat(mining-app): 启动和切回前台自动检测升级
MainShell 从 StatelessWidget 转为 StatefulWidget + WidgetsBindingObserver, 参考 mobile-app HomeShellPage 模式,实现: - initState 首帧后自动检查更新 - didChangeAppLifecycleState(resumed) 从后台恢复时自动检查 - 90-300秒随机冷却间隔防止频繁请求(static 变量跨 rebuild 保持) - 延迟3秒启动检查,避免干扰用户操作 - 有更新时弹出 SelfHostedUpdater 对话框(支持强制更新) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
f0c7cee94e
commit
53a2e64cad
|
|
@ -1,19 +1,82 @@
|
|||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../core/router/routes.dart';
|
||||
import '../../core/constants/app_colors.dart';
|
||||
import '../../core/updater/update_service.dart';
|
||||
import '../../core/updater/channels/self_hosted_updater.dart';
|
||||
|
||||
class MainShell extends StatelessWidget {
|
||||
class MainShell extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const MainShell({super.key, required this.child});
|
||||
|
||||
@override
|
||||
State<MainShell> createState() => _MainShellState();
|
||||
}
|
||||
|
||||
class _MainShellState extends State<MainShell> with WidgetsBindingObserver {
|
||||
/// 下次允许检查更新的时间(static 防止 widget rebuild 重置)
|
||||
static DateTime? _nextCheckAllowedTime;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_checkForUpdateIfNeeded();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
_checkForUpdateIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _checkForUpdateIfNeeded() async {
|
||||
final now = DateTime.now();
|
||||
|
||||
// 如果从未检查过,或者已过冷却时间,则检查
|
||||
if (_nextCheckAllowedTime == null || now.isAfter(_nextCheckAllowedTime!)) {
|
||||
// 设置下次允许检查时间(90-300秒随机间隔)
|
||||
final randomSeconds = 90 + Random().nextInt(211);
|
||||
_nextCheckAllowedTime = now.add(Duration(seconds: randomSeconds));
|
||||
|
||||
// 延迟3秒,避免启动时干扰用户
|
||||
await Future.delayed(const Duration(seconds: 3));
|
||||
if (!mounted) return;
|
||||
|
||||
try {
|
||||
final result = await UpdateService.instance.checkForUpdate();
|
||||
if (!mounted) return;
|
||||
|
||||
if (result.hasUpdate && result.versionInfo != null) {
|
||||
await SelfHostedUpdater.show(
|
||||
context,
|
||||
versionInfo: result.versionInfo!,
|
||||
isForceUpdate: result.versionInfo!.isForceUpdate,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('[MainShell] 检查更新失败: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isDark = AppColors.isDark(context);
|
||||
|
||||
return Scaffold(
|
||||
body: child,
|
||||
body: widget.child,
|
||||
bottomNavigationBar: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.cardOf(context),
|
||||
|
|
|
|||
Loading…
Reference in New Issue