cb_prestige_qr/lib/core/utils/MainShell.dart

174 lines
5.8 KiB
Dart
Raw Permalink Normal View History

2026-04-09 06:47:03 +00:00
import 'dart:async';
import 'dart:ui';
import 'package:cb_prestige_qr/core/utils/ScanShell.dart';
import 'package:cb_prestige_qr/core/presentation/widgets/global_loading_overlay.dart';
import 'package:cb_prestige_qr/core/widgets/CenterNavButton.dart';
import 'package:cb_prestige_qr/core/widgets/NavItem.dart';
import 'package:cb_prestige_qr/features/analysis/presentation/pages/analysis_page.dart';
import 'package:cb_prestige_qr/features/history/presentation/pages/history_page.dart';
import 'package:cb_prestige_qr/features/home/presentation/pages/home.dart';
import 'package:cb_prestige_qr/features/settings/presentation/pages/settings_page.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
final navIndexNotifierProvider = NotifierProvider<NavIndexNotifier, int>(
NavIndexNotifier.new,
);
class NavIndexNotifier extends Notifier<int> {
@override
int build() => 0;
void setIndex(int index) {
if (state == index) return;
state = index;
}
}
class MainShell extends ConsumerStatefulWidget {
const MainShell({super.key});
@override
ConsumerState<MainShell> createState() => _MainShellState();
}
class _MainShellState extends ConsumerState<MainShell> {
Timer? _timer;
var _isLoading = false;
void _startLoading([Duration duration = const Duration(seconds: 1)]) {
_timer?.cancel();
if (!_isLoading) setState(() => _isLoading = true);
_timer = Timer(duration, () {
if (!mounted) return;
setState(() => _isLoading = false);
});
}
@override
void initState() {
super.initState();
final initialIndex = ref.read(navIndexNotifierProvider);
if (initialIndex != 0) _startLoading();
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final selectedIndex = ref.watch(navIndexNotifierProvider);
final theme = Theme.of(context);
ref.listen<int>(navIndexNotifierProvider, (previous, next) {
if (previous == null || previous == next) return;
if (next == 0) return;
_startLoading();
});
final pages = [
const HomeView(),
const AnalysisPage(),
const SizedBox(),
const HistoryPage(),
const SettingsPage(),
];
return Stack(
children: [
Scaffold(
extendBody: true,
body: IndexedStack(index: selectedIndex, children: pages),
bottomNavigationBar: Padding(
padding: const EdgeInsets.symmetric(horizontal: 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: Container(
height: 70 + MediaQuery.of(context).padding.bottom,
decoration: BoxDecoration(
color: theme.scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.white.withAlpha(31)),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(31),
blurRadius: 25,
offset: const Offset(0, 10),
),
],
),
child: Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom,
),
child: Row(
children: [
Expanded(
child: NavItem(
icon: Icons.home_rounded,
isActive: selectedIndex == 0,
onTap: () => ref
.read(navIndexNotifierProvider.notifier)
.setIndex(0),
),
),
Expanded(
child: NavItem(
icon: Icons.analytics,
isActive: selectedIndex == 1,
onTap: () => ref
.read(navIndexNotifierProvider.notifier)
.setIndex(1),
),
),
Expanded(
child: CenterNavButton(
isActive: false,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const ScanFlow(),
),
);
},
),
),
Expanded(
child: NavItem(
icon: Icons.history_rounded,
isActive: selectedIndex == 3,
onTap: () => ref
.read(navIndexNotifierProvider.notifier)
.setIndex(3),
),
),
Expanded(
child: NavItem(
icon: Icons.person_rounded,
isActive: selectedIndex == 4,
onTap: () => ref
.read(navIndexNotifierProvider.notifier)
.setIndex(4),
),
),
],
),
),
),
),
),
),
),
GlobalLoadingOverlay(isLoading: _isLoading),
],
);
}
}