2024-06-03 18:02:05 +08:00
|
|
|
import 'package:fl_clash/common/common.dart';
|
2025-02-09 18:39:38 +08:00
|
|
|
import 'package:fl_clash/enum/enum.dart';
|
2024-04-30 23:38:49 +08:00
|
|
|
import 'package:fl_clash/models/models.dart';
|
2025-02-09 18:39:38 +08:00
|
|
|
import 'package:fl_clash/providers/providers.dart';
|
2024-04-30 23:38:49 +08:00
|
|
|
import 'package:fl_clash/state.dart';
|
2025-02-09 18:39:38 +08:00
|
|
|
import 'package:fl_clash/widgets/widgets.dart';
|
2024-04-30 23:38:49 +08:00
|
|
|
import 'package:flutter/material.dart';
|
2025-02-09 18:39:38 +08:00
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
2024-04-30 23:38:49 +08:00
|
|
|
import 'package:intl/intl.dart';
|
|
|
|
|
|
|
|
|
|
typedef OnSelected = void Function(int index);
|
|
|
|
|
|
|
|
|
|
class HomePage extends StatelessWidget {
|
|
|
|
|
const HomePage({super.key});
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
2024-09-08 21:21:21 +08:00
|
|
|
return BackScope(
|
2025-02-09 18:39:38 +08:00
|
|
|
child: Consumer(
|
|
|
|
|
builder: (_, ref, child) {
|
|
|
|
|
final state = ref.watch(homeStateProvider);
|
2024-09-18 10:27:53 +08:00
|
|
|
final viewMode = state.viewMode;
|
|
|
|
|
final navigationItems = state.navigationItems;
|
2025-02-09 18:39:38 +08:00
|
|
|
final pageLabel = state.pageLabel;
|
2024-09-18 10:27:53 +08:00
|
|
|
final index = navigationItems.lastIndexWhere(
|
2025-02-09 18:39:38 +08:00
|
|
|
(element) => element.label == pageLabel,
|
2024-09-18 10:27:53 +08:00
|
|
|
);
|
|
|
|
|
final currentIndex = index == -1 ? 0 : index;
|
2024-12-09 01:40:39 +08:00
|
|
|
final navigationBar = CommonNavigationBar(
|
2024-09-18 10:27:53 +08:00
|
|
|
viewMode: viewMode,
|
|
|
|
|
navigationItems: navigationItems,
|
|
|
|
|
currentIndex: currentIndex,
|
|
|
|
|
);
|
|
|
|
|
final bottomNavigationBar =
|
2025-02-09 18:39:38 +08:00
|
|
|
viewMode == ViewMode.mobile ? navigationBar : null;
|
2024-09-18 10:27:53 +08:00
|
|
|
final sideNavigationBar =
|
2025-02-09 18:39:38 +08:00
|
|
|
viewMode != ViewMode.mobile ? navigationBar : null;
|
2024-09-18 10:27:53 +08:00
|
|
|
return CommonScaffold(
|
|
|
|
|
key: globalState.homeScaffoldKey,
|
|
|
|
|
title: Intl.message(
|
2025-02-09 18:39:38 +08:00
|
|
|
pageLabel.name,
|
2024-09-18 10:27:53 +08:00
|
|
|
),
|
|
|
|
|
sideNavigationBar: sideNavigationBar,
|
|
|
|
|
body: child!,
|
|
|
|
|
bottomNavigationBar: bottomNavigationBar,
|
2024-07-24 01:27:49 +08:00
|
|
|
);
|
|
|
|
|
},
|
2025-02-09 18:39:38 +08:00
|
|
|
child: _HomePageView(),
|
2024-07-24 01:27:49 +08:00
|
|
|
),
|
2024-04-30 23:38:49 +08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-12-09 01:40:39 +08:00
|
|
|
|
2025-02-09 18:39:38 +08:00
|
|
|
class _HomePageView extends ConsumerStatefulWidget {
|
|
|
|
|
const _HomePageView();
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
ConsumerState createState() => _HomePageViewState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _HomePageViewState extends ConsumerState<_HomePageView> {
|
|
|
|
|
_updatePageController(List<NavigationItem> navigationItems) {
|
|
|
|
|
final pageLabel = globalState.appState.pageLabel;
|
|
|
|
|
final index = navigationItems.lastIndexWhere(
|
|
|
|
|
(element) => element.label == pageLabel,
|
|
|
|
|
);
|
|
|
|
|
final pageIndex = index == -1 ? 0 : index;
|
|
|
|
|
if (globalState.pageController != null) {
|
|
|
|
|
Future.delayed(Duration(milliseconds: 200), () {
|
|
|
|
|
globalState.appController.toPage(
|
|
|
|
|
pageIndex,
|
|
|
|
|
hasAnimate: true,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
globalState.pageController = PageController(
|
|
|
|
|
initialPage: pageIndex,
|
|
|
|
|
keepPage: true,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// _handlePageChanged(PageLabel next) {
|
|
|
|
|
// debouncer.call(DebounceTag.pageChange, () {
|
|
|
|
|
// if (_prevPageLabel == next) {
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
// if (_prevPageLabel != null) {
|
|
|
|
|
// final prevTabPageKey = GlobalObjectKey(_prevPageLabel!);
|
|
|
|
|
// if (prevTabPageKey.currentState is PageMixin) {
|
|
|
|
|
// (prevTabPageKey.currentState as PageMixin).onPageHidden();
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// final nextTabPageKey = GlobalObjectKey(next);
|
|
|
|
|
// if (nextTabPageKey.currentState is PageMixin) {
|
|
|
|
|
// (nextTabPageKey.currentState as PageMixin).onPageShow();
|
|
|
|
|
// }
|
|
|
|
|
// _prevPageLabel = next;
|
|
|
|
|
// }, duration: commonDuration);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
final navigationItems = ref.watch(currentNavigationsStateProvider).value;
|
|
|
|
|
_updatePageController(navigationItems);
|
|
|
|
|
return PageView.builder(
|
|
|
|
|
controller: globalState.pageController,
|
|
|
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
|
|
|
itemCount: navigationItems.length,
|
|
|
|
|
// onPageChanged: (index) {
|
|
|
|
|
// _handlePageChanged(navigationItems[index].label);
|
|
|
|
|
// },
|
|
|
|
|
itemBuilder: (_, index) {
|
|
|
|
|
final navigationItem = navigationItems[index];
|
|
|
|
|
return KeepScope(
|
|
|
|
|
keep: navigationItem.keep,
|
|
|
|
|
key: Key(navigationItem.label.name),
|
|
|
|
|
child: navigationItem.fragment,
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class CommonNavigationBar extends ConsumerWidget {
|
2024-12-09 01:40:39 +08:00
|
|
|
final ViewMode viewMode;
|
|
|
|
|
final List<NavigationItem> navigationItems;
|
|
|
|
|
final int currentIndex;
|
|
|
|
|
|
|
|
|
|
const CommonNavigationBar({
|
|
|
|
|
super.key,
|
|
|
|
|
required this.viewMode,
|
|
|
|
|
required this.navigationItems,
|
|
|
|
|
required this.currentIndex,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
_updateSafeMessageOffset(BuildContext context) {
|
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
|
|
final size = context.size;
|
|
|
|
|
if (viewMode == ViewMode.mobile) {
|
|
|
|
|
globalState.safeMessageOffsetNotifier.value = Offset(
|
|
|
|
|
0,
|
|
|
|
|
-(size?.height ?? 0),
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
globalState.safeMessageOffsetNotifier.value = Offset(
|
|
|
|
|
size?.width ?? 0,
|
|
|
|
|
0,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
2025-02-09 18:39:38 +08:00
|
|
|
Widget build(BuildContext context, ref) {
|
2024-12-09 01:40:39 +08:00
|
|
|
_updateSafeMessageOffset(context);
|
|
|
|
|
if (viewMode == ViewMode.mobile) {
|
|
|
|
|
return NavigationBar(
|
|
|
|
|
destinations: navigationItems
|
|
|
|
|
.map(
|
|
|
|
|
(e) => NavigationDestination(
|
2025-02-09 18:39:38 +08:00
|
|
|
icon: e.icon,
|
|
|
|
|
label: Intl.message(e.label.name),
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-12-09 01:40:39 +08:00
|
|
|
.toList(),
|
|
|
|
|
onDestinationSelected: globalState.appController.toPage,
|
|
|
|
|
selectedIndex: currentIndex,
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-02-09 18:39:38 +08:00
|
|
|
final showLabel = ref.watch(appSettingProvider).showLabel;
|
2024-12-09 01:40:39 +08:00
|
|
|
return Material(
|
|
|
|
|
color: context.colorScheme.surfaceContainer,
|
2025-02-03 23:32:00 +08:00
|
|
|
child: Column(
|
|
|
|
|
children: [
|
|
|
|
|
Expanded(
|
|
|
|
|
child: SingleChildScrollView(
|
|
|
|
|
child: IntrinsicHeight(
|
2025-02-09 18:39:38 +08:00
|
|
|
child: NavigationRail(
|
|
|
|
|
backgroundColor: context.colorScheme.surfaceContainer,
|
|
|
|
|
selectedIconTheme: IconThemeData(
|
|
|
|
|
color: context.colorScheme.onSurfaceVariant,
|
|
|
|
|
),
|
|
|
|
|
unselectedIconTheme: IconThemeData(
|
|
|
|
|
color: context.colorScheme.onSurfaceVariant,
|
|
|
|
|
),
|
|
|
|
|
selectedLabelTextStyle:
|
|
|
|
|
context.textTheme.labelLarge!.copyWith(
|
|
|
|
|
color: context.colorScheme.onSurface,
|
|
|
|
|
),
|
|
|
|
|
unselectedLabelTextStyle:
|
|
|
|
|
context.textTheme.labelLarge!.copyWith(
|
|
|
|
|
color: context.colorScheme.onSurface,
|
|
|
|
|
),
|
|
|
|
|
destinations: navigationItems
|
|
|
|
|
.map(
|
|
|
|
|
(e) => NavigationRailDestination(
|
|
|
|
|
icon: e.icon,
|
|
|
|
|
label: Text(
|
|
|
|
|
Intl.message(e.label.name),
|
2025-02-03 23:32:00 +08:00
|
|
|
),
|
2025-02-09 18:39:38 +08:00
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
.toList(),
|
|
|
|
|
onDestinationSelected: globalState.appController.toPage,
|
|
|
|
|
extended: false,
|
|
|
|
|
selectedIndex: currentIndex,
|
|
|
|
|
labelType: showLabel
|
|
|
|
|
? NavigationRailLabelType.all
|
|
|
|
|
: NavigationRailLabelType.none,
|
2024-12-09 01:40:39 +08:00
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
2025-02-03 23:32:00 +08:00
|
|
|
),
|
|
|
|
|
const SizedBox(
|
|
|
|
|
height: 16,
|
|
|
|
|
),
|
|
|
|
|
IconButton(
|
|
|
|
|
onPressed: () {
|
2025-02-09 18:39:38 +08:00
|
|
|
ref.read(appSettingProvider.notifier).updateState(
|
|
|
|
|
(state) => state.copyWith(
|
|
|
|
|
showLabel: !state.showLabel,
|
|
|
|
|
),
|
2025-02-03 23:32:00 +08:00
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
icon: const Icon(Icons.menu),
|
|
|
|
|
),
|
|
|
|
|
const SizedBox(
|
|
|
|
|
height: 16,
|
|
|
|
|
),
|
|
|
|
|
],
|
2024-12-09 01:40:39 +08:00
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|