feat : PopScope and there logic

This commit is contained in:
2025-07-13 11:52:19 +03:30
parent 9c8ab53188
commit 6de5c21919
2 changed files with 169 additions and 112 deletions

View File

@@ -1,89 +1,119 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rasadyar_chicken/chicken.dart'; import 'package:rasadyar_chicken/chicken.dart';
import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart'; import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart';
import 'package:rasadyar_core/core.dart'; import 'package:rasadyar_core/core.dart';
class RootPage extends GetView<RootLogic> { class RootPage extends GetView<RootLogic> {
const RootPage({super.key}); RootPage({super.key});
DateTime? _lastBackPressed;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ObxValue((data) { return ObxValue((data) {
return Scaffold( return PopScope(
backgroundColor: AppColor.bgLight, canPop: false,
body: IndexedStack( onPopInvokedWithResult: (didPop, result) async {
children: [ final nestedKey = Get.nestedKey(controller.currentPage.value);
Navigator( final currentNavigator = nestedKey?.currentState;
key: Get.nestedKey(0),
onGenerateRoute: (settings) {
final page = ChickenPages.pages.firstWhere(
(e) => e.name == settings.name,
orElse: () => ChickenPages.pages.firstWhere((e) => e.name == ChickenRoutes.buy),
);
return buildRouteFromGetPage(page); if (currentNavigator?.canPop() ?? false) {
}, currentNavigator?.pop();
), } else {
Navigator( final now = DateTime.now();
key: Get.nestedKey(1), if (_lastBackPressed == null ||
onGenerateRoute: (settings) { now.difference(_lastBackPressed!) > Duration(seconds: 2)) {
final page = ChickenPages.pages.firstWhere( _lastBackPressed = now;
(e) => e.name == settings.name, Get.snackbar(
orElse: () => ChickenPages.pages.firstWhere((e) => e.name == ChickenRoutes.sale), 'خروج از برنامه',
); 'برای خروج دوباره بازگشت را بزنید',
snackPosition: SnackPosition.TOP,
duration: Duration(seconds: 2),
backgroundColor: AppColor.warning,
);
} else {
await SystemNavigator.pop();
}
}
},
child: Scaffold(
backgroundColor: AppColor.bgLight,
body: IndexedStack(
children: [
Navigator(
key: Get.nestedKey(0),
onGenerateRoute: (settings) {
final page = ChickenPages.pages.firstWhere(
(e) => e.name == settings.name,
orElse: () => ChickenPages.pages.firstWhere((e) => e.name == ChickenRoutes.buy),
);
return buildRouteFromGetPage(page); return buildRouteFromGetPage(page);
}, },
), ),
Navigator( Navigator(
key: Get.nestedKey(2), key: Get.nestedKey(1),
onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[2]), onGenerateRoute: (settings) {
), final page = ChickenPages.pages.firstWhere(
Navigator( (e) => e.name == settings.name,
key: Get.nestedKey(3), orElse: () =>
onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[3]), ChickenPages.pages.firstWhere((e) => e.name == ChickenRoutes.sale),
), );
Navigator(
key: Get.nestedKey(4),
onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[4]),
),
],
index: data.value,
),
bottomNavigationBar: RBottomNavigation( return buildRouteFromGetPage(page);
items: [ },
RBottomNavigationItem( ),
label: 'خرید', Navigator(
icon: Assets.vec.buySvg.path, key: Get.nestedKey(2),
isSelected: controller.currentPage.value == 0, onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[2]),
onTap: () => controller.changePage(0), ),
), Navigator(
RBottomNavigationItem( key: Get.nestedKey(3),
label: 'فروش', onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[3]),
icon: Assets.vec.saleSvg.path, ),
isSelected: controller.currentPage.value == 1, Navigator(
onTap: () => controller.changePage(1), key: Get.nestedKey(4),
), onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[4]),
RBottomNavigationItem( ),
label: 'خانه', ],
icon: Assets.vec.homeSvg.path, index: data.value,
isSelected: controller.currentPage.value == 2, ),
onTap: () => controller.changePage(2),
), bottomNavigationBar: RBottomNavigation(
RBottomNavigationItem( items: [
label: 'قطعه بندی', RBottomNavigationItem(
icon: Assets.vec.convertCubeSvg.path, label: 'خرید',
isSelected: controller.currentPage.value == 3, icon: Assets.vec.buySvg.path,
onTap: () => controller.changePage(3), isSelected: controller.currentPage.value == 0,
), onTap: () => controller.changePage(0),
RBottomNavigationItem( ),
label: 'پروفایل', RBottomNavigationItem(
icon: Assets.vec.profileCircleSvg.path, label: 'فروش',
isSelected: controller.currentPage.value == 4, icon: Assets.vec.saleSvg.path,
onTap: () => controller.changePage(4), isSelected: controller.currentPage.value == 1,
), onTap: () => controller.changePage(1),
], ),
RBottomNavigationItem(
label: 'خانه',
icon: Assets.vec.homeSvg.path,
isSelected: controller.currentPage.value == 2,
onTap: () => controller.changePage(2),
),
RBottomNavigationItem(
label: 'قطعه بندی',
icon: Assets.vec.convertCubeSvg.path,
isSelected: controller.currentPage.value == 3,
onTap: () => controller.changePage(3),
),
RBottomNavigationItem(
label: 'پروفایل',
icon: Assets.vec.profileCircleSvg.path,
isSelected: controller.currentPage.value == 4,
onTap: () => controller.changePage(4),
),
],
),
), ),
); );
}, controller.currentPage); }, controller.currentPage);
@@ -164,15 +194,20 @@ class RootPage extends GetView<RootLogic> {
height: 82, height: 82,
decoration: BoxDecoration( decoration: BoxDecoration(
color: bgLabelColor, color: bgLabelColor,
borderRadius: BorderRadius.only(topRight: Radius.circular(8), bottomRight: Radius.circular(8)), borderRadius: BorderRadius.only(
topRight: Radius.circular(8),
bottomRight: Radius.circular(8),
),
), ),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
spacing: 4, spacing: 4,
children: [ children: [
SvgGenImage.vec( SvgGenImage.vec(iconPath).svg(
iconPath, width: 24,
).svg(width: 24, height: 24, colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn)), height: 24,
colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
),
Text( Text(
title, title,
textAlign: TextAlign.right, textAlign: TextAlign.right,
@@ -187,7 +222,10 @@ class RootPage extends GetView<RootLogic> {
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: bgDescriptionColor, color: bgDescriptionColor,
borderRadius: BorderRadius.only(topLeft: Radius.circular(8), bottomLeft: Radius.circular(8)), borderRadius: BorderRadius.only(
topLeft: Radius.circular(8),
bottomLeft: Radius.circular(8),
),
), ),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@@ -275,9 +313,11 @@ class RootPage extends GetView<RootLogic> {
), ),
), ),
child: Center( child: Center(
child: SvgGenImage.vec( child: SvgGenImage.vec(iconPath).svg(
iconPath, width: 24,
).svg(width: 24, height: 24, colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn)), height: 24,
colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
),
), ),
), ),
), ),
@@ -286,7 +326,11 @@ class RootPage extends GetView<RootLogic> {
); );
} }
Widget widelyUsed({required String title, required String iconPath, required VoidCallback onTap}) { Widget widelyUsed({
required String title,
required String iconPath,
required VoidCallback onTap,
}) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
@@ -525,15 +569,25 @@ class RootPage extends GetView<RootLogic> {
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
buildRow('فروش و توزیع داخل استان (کیلوگرم)', model.stewardAllocationsWeight!.toInt().toString()), buildRow(
buildRow('فروش و توزیع خارج استان (کیلوگرم)', model.freeSalesWeight!.toInt().toString()), 'فروش و توزیع داخل استان (کیلوگرم)',
model.stewardAllocationsWeight!.toInt().toString(),
),
buildRow(
'فروش و توزیع خارج استان (کیلوگرم)',
model.freeSalesWeight!.toInt().toString(),
),
], ],
) )
: const Center(child: CircularProgressIndicator()), : const Center(child: CircularProgressIndicator()),
); );
} }
Widget cardWidget({required String title, required String iconPath, required VoidCallback onTap}) { Widget cardWidget({
required String title,
required String iconPath,
required VoidCallback onTap,
}) {
return Container( return Container(
width: Get.width / 4, width: Get.width / 4,
height: 130, height: 130,

View File

@@ -23,11 +23,10 @@ class BasePage extends StatefulWidget {
this.onFilterTap, this.onFilterTap,
this.onSearchTap, this.onSearchTap,
this.filteringWidget, this.filteringWidget,
}):assert( }) : assert(
(routes != null ) || routesWidget != null, (routes != null) || routesWidget != null,
'Either routes or routesWidget must be provided.', 'Either routes or routesWidget must be provided.',
); );
final List<String>? routes; final List<String>? routes;
final Widget? routesWidget; final Widget? routesWidget;
@@ -77,29 +76,33 @@ class _BasePageState extends State<BasePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return PopScope(
backgroundColor: AppColor.bgLight, canPop: false,
appBar: chickenAppBar( onPopInvokedWithResult: (didPop, result) => widget.onBackPressed,
hasBack: widget.isBase ? false : widget.hasBack, child: Scaffold(
onBackPressed: widget.onBackPressed, backgroundColor: AppColor.bgLight,
hasFilter: widget.hasFilter, appBar: chickenAppBar(
hasSearch: widget.hasSearch, hasBack: widget.isBase ? false : widget.hasBack,
isBase: widget.isBase, onBackPressed: widget.onBackPressed,
onFilterTap: widget.hasFilter ? () => controller.toggleFilter() : null, hasFilter: widget.hasFilter,
onSearchTap: widget.hasSearch ? () => Get.find<SearchLogic>().toggleSearch() : null, hasSearch: widget.hasSearch,
isBase: widget.isBase,
onFilterTap: widget.hasFilter ? () => controller.toggleFilter() : null,
onSearchTap: widget.hasSearch ? () => Get.find<SearchLogic>().toggleSearch() : null,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.routesWidget != null ? widget.routesWidget! : buildPageRoute(widget.routes!),
if (!widget.isBase && widget.hasSearch) ...{
SearchWidget(onSearchChanged: widget.onSearchChanged),
},
...widget.widgets,
],
),
floatingActionButtonLocation: widget.floatingActionButtonLocation,
floatingActionButton: widget.floatingActionButton,
), ),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.routesWidget != null ? widget.routesWidget! : buildPageRoute(widget.routes!),
if (!widget.isBase && widget.hasSearch) ...{
SearchWidget(onSearchChanged: widget.onSearchChanged),
},
...widget.widgets,
],
),
floatingActionButtonLocation: widget.floatingActionButtonLocation,
floatingActionButton: widget.floatingActionButton,
); );
} }
} }