gcx/frontend/genex-mobile/lib/app/main_shell.dart

119 lines
3.5 KiB
Dart

import 'package:flutter/material.dart';
import '../app/theme/app_colors.dart';
import '../app/i18n/app_localizations.dart';
import '../core/updater/update_service.dart';
import '../core/providers/notification_badge_manager.dart';
import '../features/coupons/presentation/pages/home_page.dart';
import '../features/coupons/presentation/pages/market_page.dart';
import '../features/message/presentation/pages/message_page.dart';
import '../features/profile/presentation/pages/profile_page.dart';
/// GenexMobile主Shell - Bottom Navigation
///
/// Tab: 首页 / 交易 / 消息 / 我的
class MainShell extends StatefulWidget {
const MainShell({super.key});
@override
State<MainShell> createState() => _MainShellState();
}
class _MainShellState extends State<MainShell> {
int _currentIndex = 0;
bool _updateChecked = false;
final _pages = const [
HomePage(),
MarketPage(),
MessagePage(),
ProfilePage(),
];
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (!_updateChecked) {
_updateChecked = true;
_checkForUpdate();
}
}
Future<void> _checkForUpdate() async {
await Future.delayed(const Duration(seconds: 3));
if (!mounted) return;
await UpdateService().checkForUpdate(context);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: _pages,
),
bottomNavigationBar: Container(
decoration: const BoxDecoration(
color: AppColors.surface,
border: Border(top: BorderSide(color: AppColors.borderLight, width: 0.5)),
),
child: NavigationBar(
selectedIndex: _currentIndex,
onDestinationSelected: (index) => setState(() => _currentIndex = index),
destinations: [
_buildDestination(Icons.home_rounded, Icons.home_outlined, context.t('nav.home')),
_buildDestination(Icons.show_chart_rounded, Icons.show_chart_outlined, context.t('nav.trading')),
_buildBadgeDestination(
Icons.notifications_rounded,
Icons.notifications_outlined,
context.t('nav.messages'),
),
_buildDestination(Icons.person_rounded, Icons.person_outlined, context.t('nav.profile')),
],
),
),
);
}
NavigationDestination _buildDestination(
IconData selected,
IconData unselected,
String label,
) {
return NavigationDestination(
icon: Icon(unselected),
selectedIcon: Icon(selected),
label: label,
);
}
NavigationDestination _buildBadgeDestination(
IconData selected,
IconData unselected,
String label,
) {
return NavigationDestination(
icon: ValueListenableBuilder<int>(
valueListenable: NotificationBadgeManager().unreadCount,
builder: (context, count, _) {
if (count <= 0) return Icon(unselected);
return Badge(
label: Text('$count', style: const TextStyle(fontSize: 10)),
child: Icon(unselected),
);
},
),
selectedIcon: ValueListenableBuilder<int>(
valueListenable: NotificationBadgeManager().unreadCount,
builder: (context, count, _) {
if (count <= 0) return Icon(selected);
return Badge(
label: Text('$count', style: const TextStyle(fontSize: 10)),
child: Icon(selected),
);
},
),
label: label,
);
}
}