Files
pangolin/client/lib/shell/home_shell.dart
T
wangjia 0b86138b55
Deploy Client / build-windows (push) Successful in 1m47s
Deploy Client / build-android (push) Has been cancelled
Deploy Client / build-macos (push) Has been cancelled
Deploy Client / build-ios (push) Has been cancelled
Deploy Client / release-deploy (push) Has been cancelled
feat(client/update): 更新提示改 jiu 式顶部横条(非强制不再弹窗)
按需求去掉居中弹窗,改成不打断的顶部 banner(对照 jiu 黄条):
- 非强制更新 → home_shell 顶部 UpdateBanner「发现新版本 vX + 立即更新 + ×」;
  「立即更新」App 内下载安装,「×」忽略此版本(banner 隐藏,更新版本会重现)
- 强制更新(force_update)→ 仍走不可关闭弹窗 showUpdateDialog
- 忽略状态改 dismissedUpdateVersionProvider(按版本号,响应式);去掉 notifier
  的 _dismissed
- 设置页「检查更新」有更新时:清忽略版本→banner 显示 + toast,不再弹窗
- 新增 6 语「立即更新」文案。flutter analyze 仅 2 个既有 withOpacity info

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
2026-07-07 19:19:05 +08:00

58 lines
2.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// home_shell.dart — 主框架分发器(按 formFactor 选三端外壳)
//
// desktop → 侧栏 6 项 + 顶栏(对照 ui_kits/desktop
// tablet → 暂用 MobileShellTODO: TabletShell 侧栏双栏,对照 ui_kits/tablet
// mobile → 底 Tab + 滑动(对照 ui_kits/mobile
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/responsive/form_factor.dart';
import '../pangolin_theme.dart';
import '../state/app_providers.dart';
import '../state/update_provider.dart';
import '../widgets/update_dialog.dart';
import 'desktop_shell.dart';
import 'mobile_shell.dart';
import 'tablet_shell.dart';
class HomeShell extends ConsumerWidget {
const HomeShell({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final c = context.pangolin;
// 启动自动检查更新:watch 惰性拉起 updateProvider(延迟 3s→查→1h 轮询)。
// 非强制更新 → 顶部 banner(见下,不打断);强制更新 → 不可关闭弹窗。
ref.listen<AsyncValue<AppUpdateInfo?>>(updateProvider, (prev, next) {
final info = next.valueOrNull;
if (info != null && info.hasUpdate && info.forceUpdate) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (context.mounted) {
showUpdateDialog(context, ref.read(appTextProvider), info);
}
});
}
});
final info = ref.watch(updateProvider).valueOrNull;
final dismissedVer = ref.watch(dismissedUpdateVersionProvider);
final showBanner = info != null &&
info.hasUpdate &&
!info.forceUpdate &&
dismissedVer != info.latestVersion;
final Widget body = switch (context.formFactor) {
FormFactor.desktop => const DesktopShell(),
FormFactor.tablet => const TabletShell(),
FormFactor.mobile => const MobileShell(),
};
return Scaffold(
backgroundColor: c.bg,
body: showBanner
? Column(children: [UpdateBanner(info: info), Expanded(child: body)])
: body,
);
}
}