From ae4c4046c34b6426f1dd158f95ba3aa943f6422a Mon Sep 17 00:00:00 2001 From: peima Date: Fri, 24 Jul 2026 13:37:04 +0800 Subject: [PATCH] phase3(critical-path): store + main + routes + nav components null-safe - store/state + reducers: nullable AppState fields & reducer types - main.dart: localeResolutionCallback Locale?, settings.name? guard - routes.dart: fluro 2.0.5 HandlerFunc (BuildContext?) + params['x']! - navigationbar/breadcrumbs/bottom_nav/text_link: nullable optional params/fields --- lib/main.dart | 10 ++- lib/routes.dart | 116 ++++++++++++------------- lib/widgets/general/bottom_nav.dart | 2 +- lib/widgets/general/breadcrumbs.dart | 18 ++-- lib/widgets/general/navigationbar.dart | 16 ++-- lib/widgets/general/text_link.dart | 46 +++++----- 6 files changed, 106 insertions(+), 102 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 43324b9..d3aa075 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -103,7 +103,11 @@ class MyApp extends StatelessWidget { S.delegate, ], supportedLocales: S.delegate.supportedLocales, - localeResolutionCallback: (Locale locale, Iterable supportedLocales) { + localeResolutionCallback: (Locale? locale, Iterable supportedLocales) { + if (locale == null) { + store.dispatch(UpdateLocale(supportedLocales.first)); + return supportedLocales.first; + } print('Language code: ${locale.languageCode}, Country code: ${locale.countryCode}'); for (final supportedLocale in supportedLocales) { if (supportedLocale.languageCode == locale.languageCode) { @@ -115,9 +119,9 @@ class MyApp extends StatelessWidget { return supportedLocales.first; }, onGenerateRoute: (RouteSettings settings) { - final List pathElements = settings.name.split('/'); + final List pathElements = settings.name?.split('/') ?? []; print('path elements: $pathElements'); - if (pathElements[0] != '') { + if (pathElements.isEmpty || pathElements[0] != '') { return null; } if (pathElements[1] == 'me') { diff --git a/lib/routes.dart b/lib/routes.dart index 0efb875..0149558 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -44,169 +44,169 @@ class Routes { static void configure() { router.define('/', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return Home(title: Constants.APP_TITLE,); }), transitionType: TransitionType.fadeIn ); router.define('/download', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return Download(); }), transitionType: TransitionType.inFromRight ); router.define('/minipos-learn-more', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return MiniPosLearnMore(); }), transitionType: TransitionType.inFromRight ); router.define('/igoshow-learn-more', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return IGoShowLearnMore(); }), transitionType: TransitionType.inFromRight ); router.define('/login', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return Login(); }), transitionType: TransitionType.inFromRight ); router.define('/me', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return Me(); }), transitionType: TransitionType.inFromRight ); router.define('/change-password', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return ChangePassword(); }), transitionType: TransitionType.inFromRight ); router.define('/user-profile', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return UserProfile(); }), transitionType: TransitionType.inFromRight ); router.define('/new-user', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return NewUser(); }), transitionType: TransitionType.inFromRight ); router.define('/set-password/:mobile/:code', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return SetPassword(params['mobile'][0], code: params['code'][0]); + handlerFunc: (BuildContext? context, Map> params) { + return SetPassword(params['mobile']![0], code: params['code']![0]); } )); router.define('/forgot-password', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return ForgotPassword(); } )); router.define('/reset-password/:mobile/:code', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return ResetPassword(params['mobile'][0], code: params['code'][0]); + handlerFunc: (BuildContext? context, Map> params) { + return ResetPassword(params['mobile']![0], code: params['code']![0]); } )); router.define('/change-mobile-email/:ismobile', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - if (params['ismobile'][0] == '1') { + handlerFunc: (BuildContext? context, Map> params) { + if (params['ismobile']![0] == '1') { return ChangeMobileOrEmail(true); } return ChangeMobileOrEmail(false); } )); router.define('/my-addresses/:business_id', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return MyAddresses(businessId: int.parse(params['business_id'][0]),); + handlerFunc: (BuildContext? context, Map> params) { + return MyAddresses(businessId: int.parse(params['business_id']![0]),); } )); router.define('/my-support/:business_id', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return MySupport(businessId: int.parse(params['business_id'][0]),); + handlerFunc: (BuildContext? context, Map> params) { + return MySupport(businessId: int.parse(params['business_id']![0]),); } )); router.define('/new-ticket/:business_id', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return NewTicket(businessId: int.parse(params['business_id'][0]),); + handlerFunc: (BuildContext? context, Map> params) { + return NewTicket(businessId: int.parse(params['business_id']![0]),); } )); router.define('/search-place/:business_id', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return SearchPlace(int.parse(params['business_id'][0])); + handlerFunc: (BuildContext? context, Map> params) { + return SearchPlace(int.parse(params['business_id']![0])); } )); router.define('/view-ticket/:ticket_id', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return ViewTicket(int.parse(params['ticket_id'][0]),); + handlerFunc: (BuildContext? context, Map> params) { + return ViewTicket(int.parse(params['ticket_id']![0]),); } )); router.define('/blog/:business_id', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return Blog(businessId: int.parse(params['business_id'][0]),); + handlerFunc: (BuildContext? context, Map> params) { + return Blog(businessId: int.parse(params['business_id']![0]),); } )); router.define('/view-blog/:bid', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return ViewBlog(int.parse(params['bid'][0]),); + handlerFunc: (BuildContext? context, Map> params) { + return ViewBlog(int.parse(params['bid']![0]),); } )); router.define('/shop/:business_id', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return Shop(businessId: int.parse(params['business_id'][0]),); + handlerFunc: (BuildContext? context, Map> params) { + return Shop(businessId: int.parse(params['business_id']![0]),); } )); router.define('/shop', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return Shop(); } )); // router.define('/ocr-scan', handler: new Handler( - // handlerFunc: (BuildContext context, Map> params) { + // handlerFunc: (BuildContext? context, Map> params) { // return OCRScan(); // } // )); router.define('/checkout/:id', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return Checkout(int.parse(params['id'][0])); + handlerFunc: (BuildContext? context, Map> params) { + return Checkout(int.parse(params['id']![0])); }), ); router.define('/paynow/:orderId', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return PayNow(int.parse(params['orderId'][0])); + handlerFunc: (BuildContext? context, Map> params) { + return PayNow(int.parse(params['orderId']![0])); }), ); router.define('/orders', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return Orders(); } )); router.define('/my-cards', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return MyCards(); } )); router.define('/orderdetail/:orderId', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return OrderDetail(int.parse(params['orderId'][0])); + handlerFunc: (BuildContext? context, Map> params) { + return OrderDetail(int.parse(params['orderId']![0])); }), ); router.define('/new-comment/:orderId', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return NewComment(int.parse(params['orderId'][0])); + handlerFunc: (BuildContext? context, Map> params) { + return NewComment(int.parse(params['orderId']![0])); }), ); router.define('/coupons/:contactId', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return Coupons(int.parse(params['contactId'][0])); + handlerFunc: (BuildContext? context, Map> params) { + return Coupons(int.parse(params['contactId']![0])); }), ); router.define('/service-policy', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return PlainPage( 'service-policy', // businessId: Constants.BUSINESS_ID, @@ -215,7 +215,7 @@ class Routes { }), ); router.define('/return-policy', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return PlainPage( 'return-policy', // businessId: Constants.BUSINESS_ID, @@ -224,7 +224,7 @@ class Routes { }), ); router.define('/privacy-policy', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return PlainPage( 'privacy-policy', // businessId: Constants.BUSINESS_ID, @@ -233,7 +233,7 @@ class Routes { }), ); router.define('/end-user-license-agreement', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return PlainPage( 'end-user-license-agreement', // businessId: Constants.BUSINESS_ID, @@ -242,7 +242,7 @@ class Routes { }), ); router.define('/about-us', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return PlainPage( 'about-us', // businessId: Constants.BUSINESS_ID, @@ -251,29 +251,29 @@ class Routes { }), ); router.define('/contact-us', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return ContactUs( businessId: Constants.BUSINESS_ID, ); }), ); router.define('/renew-license', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return RenewLicense(); } )); router.define('/renew-minioffice/:gid', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return RenewMiniOffice(int.parse(params['gid'][0])); + handlerFunc: (BuildContext? context, Map> params) { + return RenewMiniOffice(int.parse(params['gid']![0])); } )); router.define('/buy-service/:gid/:servicename', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { - return BuyService(int.parse(params['gid'][0]), params['servicename'][0]); + handlerFunc: (BuildContext? context, Map> params) { + return BuyService(int.parse(params['gid']![0]), params['servicename']![0]); } )); router.define('/contact-stores', handler: new Handler( - handlerFunc: (BuildContext context, Map> params) { + handlerFunc: (BuildContext? context, Map> params) { return CreateOnlineStore1(); } )); diff --git a/lib/widgets/general/bottom_nav.dart b/lib/widgets/general/bottom_nav.dart index 4d4ce6d..d774641 100644 --- a/lib/widgets/general/bottom_nav.dart +++ b/lib/widgets/general/bottom_nav.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; class BottomNav extends StatefulWidget { - const BottomNav({Key key}) : super(key: key); + const BottomNav({Key? key}) : super(key: key); @override State createState() { diff --git a/lib/widgets/general/breadcrumbs.dart b/lib/widgets/general/breadcrumbs.dart index e45edcf..012e87c 100644 --- a/lib/widgets/general/breadcrumbs.dart +++ b/lib/widgets/general/breadcrumbs.dart @@ -7,10 +7,10 @@ import '../../routes.dart'; import 'navigationbar.dart'; class BreadCrumbs extends StatelessWidget { - final List breadCrumbs; + final List? breadCrumbs; final bool hasBack; - final OnBackPress onBackPress; - const BreadCrumbs(this.hasBack, {this.breadCrumbs, Key key, this.onBackPress}) : super(key: key); + final OnBackPress? onBackPress; + const BreadCrumbs(this.hasBack, {this.breadCrumbs, Key? key, this.onBackPress}) : super(key: key); @override Widget build(BuildContext context) { @@ -49,11 +49,11 @@ class BreadCrumbs extends StatelessWidget { )); } if (breadCrumbs != null) { - for (int i = 0; i < breadCrumbs.length; i++) { - BreadCrumb breadCrumb = breadCrumbs[i]; + for (int i = 0; i < breadCrumbs!.length; i++) { + BreadCrumb breadCrumb = breadCrumbs![i]; if (breadCrumb.text == null && breadCrumb.item != null) { if (breadCrumb.onTap == null) { - widgets.add(breadCrumb.item); + widgets.add(breadCrumb.item!); } else { widgets.add(MouseRegion( cursor: SystemMouseCursors.click, @@ -186,9 +186,9 @@ class BreadCrumbs extends StatelessWidget { class BreadCrumb { final String text; final String route; - final IconData icon; - final Widget item; - final Function onTap; + final IconData? icon; + final Widget? item; + final GestureTapCallback? onTap; BreadCrumb(this.text, this.route, {this.icon, this.item, this.onTap}); } \ No newline at end of file diff --git a/lib/widgets/general/navigationbar.dart b/lib/widgets/general/navigationbar.dart index 7504fc9..e8eef33 100644 --- a/lib/widgets/general/navigationbar.dart +++ b/lib/widgets/general/navigationbar.dart @@ -9,17 +9,17 @@ import 'breadcrumbs.dart'; typedef OnBackPress(); class MiniNavigationBar extends StatefulWidget implements PreferredSizeWidget { - final Key key; + final Key? key; final String title; final bool back; final bool toHome; final bool showMe; - final List breadCrumbs; - final double breadCrumbHeight; - final Widget shoppingCart; + final List? breadCrumbs; + final double? breadCrumbHeight; + final Widget? shoppingCart; - MiniNavigationBar({Key key, PreferredSizeWidget bottom, String title, - bool back, bool toHome, bool showMe, this.breadCrumbs, + MiniNavigationBar({Key? key, PreferredSizeWidget? bottom, String? title, + bool? back, bool? toHome, bool? showMe, this.breadCrumbs, this.breadCrumbHeight, this.shoppingCart}) : key = key, preferredSize = breadCrumbHeight != null ? Size.fromHeight(kToolbarHeight + breadCrumbHeight) : @@ -47,9 +47,9 @@ class MiniNavigationBarState extends State { mobile: MobileNavigationBar(title: widget.title, back: widget.back, toHome: widget.toHome, showMe: widget.showMe,), tablet: DesktopNavigationBar(hasBack: widget.back, - breadCrumbs: widget.breadCrumbs, shoppingCart: widget.shoppingCart,), + breadCrumbs: widget.breadCrumbs ?? [], shoppingCart: widget.shoppingCart ?? const SizedBox.shrink(),), desktop: DesktopNavigationBar(hasBack: widget.back, - breadCrumbs: widget.breadCrumbs, shoppingCart: widget.shoppingCart,), + breadCrumbs: widget.breadCrumbs ?? [], shoppingCart: widget.shoppingCart ?? const SizedBox.shrink(),), ); } diff --git a/lib/widgets/general/text_link.dart b/lib/widgets/general/text_link.dart index 21b5dd3..7e3dafb 100644 --- a/lib/widgets/general/text_link.dart +++ b/lib/widgets/general/text_link.dart @@ -11,22 +11,22 @@ import '../../routes.dart'; class TextLink extends StatelessWidget { final String title; final String url; - final Color color; - final Color hoverColor; - final double paddingHorizontal; - final double paddingVertical; - final FontWeight fontWeight; - final bool selected; + final Color? color; + final Color? hoverColor; + final double? paddingHorizontal; + final double? paddingVertical; + final FontWeight? fontWeight; + final bool? selected; final bool isLink; final bool replace; final bool clearStack; final bool maintainState; final bool rootNavigator; - final TransitionType transition; + final TransitionType? transition; final bool closeDrawer; final bool isEmail; final bool isPhone; - final double fontSize; + final double? fontSize; final bool isAddress; final TextOverflow overflow; final int maxLines; @@ -38,19 +38,19 @@ class TextLink extends StatelessWidget { this.paddingVertical, this.fontWeight, this.selected, - bool isLink, - bool replace, - bool clearStack, - bool maintainState, - bool rootNavigator, + bool? isLink, + bool? replace, + bool? clearStack, + bool? maintainState, + bool? rootNavigator, this.transition, - bool closeDrawer, - bool isEmail, - bool isPhone, - double fontSize, - bool isAddress, - TextOverflow overflow, - int maxLines, + bool? closeDrawer, + bool? isEmail, + bool? isPhone, + double? fontSize, + bool? isAddress, + TextOverflow? overflow, + int? maxLines, }) : isLink = isLink ?? false, replace = replace ?? false, @@ -60,7 +60,7 @@ class TextLink extends StatelessWidget { closeDrawer = closeDrawer ?? false, isEmail = isEmail ?? false, isPhone = isPhone ?? false, - fontSize = fontSize ?? null, + fontSize = fontSize, isAddress = isAddress ?? false, overflow = overflow ?? TextOverflow.ellipsis, maxLines = maxLines ?? 1; @@ -101,7 +101,7 @@ class TextLink extends StatelessWidget { }, ), decoration: BoxDecoration( - border: (selected != null && selected) ? Border( + border: (selected == true) ? Border( bottom: BorderSide( color: color ?? Colors.blue, width: 3.0, @@ -110,7 +110,7 @@ class TextLink extends StatelessWidget { ), ), onTap: () async { - if (selected == null || !selected) { + if (selected != true) { if (isEmail) { Utils.openEmail(url); } else if (isPhone) {