111 lines
3.5 KiB
Dart
111 lines
3.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../../providers/auth_provider.dart';
|
|
import '../../providers/note_refresh.dart';
|
|
import '../add/add_page.dart';
|
|
import '../assistant/assistant_page.dart';
|
|
import '../home/dashboard_page.dart';
|
|
import '../login/login_page.dart';
|
|
import '../mine/mine_page.dart';
|
|
|
|
/// 底部导航的四个 Tab 是四个「角色」,不是四个功能:
|
|
///
|
|
/// 首页 = 模块目录(卡片由 core/module/app_module.dart 生成)
|
|
/// 记录 = 全局录入入口
|
|
/// 助手 = AI(阶段 B 接入,现在是占位页)
|
|
/// 我的 = 账号、模块管理、设置
|
|
///
|
|
/// **具体模块不进 Tab** —— 记账、笔记都从首页卡片进。
|
|
/// 代价是打开 App 多一次点击才能看到账单,换来的是「以后加模块不用改这里」。
|
|
class MainShell extends ConsumerStatefulWidget {
|
|
const MainShell({super.key});
|
|
|
|
@override
|
|
ConsumerState<MainShell> createState() => _MainShellState();
|
|
}
|
|
|
|
class _MainShellState extends ConsumerState<MainShell>
|
|
with WidgetsBindingObserver {
|
|
int _index = 0; // 默认选中「首页」
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
// 监听前后台切换:在电脑上改完笔记 → 切回 App 时数据要是新的。
|
|
// 这类「绕过 App 的写操作」没有任何通知可听,只能靠这个时机对账。
|
|
WidgetsBinding.instance.addObserver(this);
|
|
// 兜底:未登录直接回登录页
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (!ref.read(authProvider).isLoggedIn) {
|
|
_goLogin();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
WidgetsBinding.instance.removeObserver(this);
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
|
// resumed 才是真正的「回到前台」;inactive/paused 是离开过程中的中间态,
|
|
// 那些时候对账没意义(用户正在离开),还会白白打请求。
|
|
if (state == AppLifecycleState.resumed) {
|
|
refreshNoteDataOnResume(ref);
|
|
}
|
|
}
|
|
|
|
void _goLogin() {
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
MaterialPageRoute(builder: (_) => const LoginPage()),
|
|
(route) => false,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// IndexedStack 保证四个页面常驻:写操作后各页的数据失效能立即重取,
|
|
// 用户切回时看到的就是最新数据。
|
|
const pages = [
|
|
DashboardPage(),
|
|
AddPage(),
|
|
AssistantPage(),
|
|
MinePage(),
|
|
];
|
|
return Scaffold(
|
|
body: IndexedStack(index: _index, children: pages),
|
|
bottomNavigationBar: NavigationBar(
|
|
selectedIndex: _index,
|
|
onDestinationSelected: (i) => setState(() => _index = i),
|
|
backgroundColor: Colors.white,
|
|
indicatorColor: const Color(0x33C8956E),
|
|
destinations: const [
|
|
NavigationDestination(
|
|
icon: Icon(Icons.home_outlined),
|
|
selectedIcon: Icon(Icons.home),
|
|
label: '首页',
|
|
),
|
|
NavigationDestination(
|
|
icon: Icon(Icons.add_circle_outline),
|
|
selectedIcon: Icon(Icons.add_circle),
|
|
label: '记录',
|
|
),
|
|
NavigationDestination(
|
|
icon: Icon(Icons.auto_awesome_outlined),
|
|
selectedIcon: Icon(Icons.auto_awesome),
|
|
label: '助手',
|
|
),
|
|
NavigationDestination(
|
|
icon: Icon(Icons.person_outline),
|
|
selectedIcon: Icon(Icons.person),
|
|
label: '我的',
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|