import 'dart:async'; import 'package:f_r_e_hub/pages/fast_pass_page/fast_pass_page_widget.dart'; import 'package:f_r_e_hub/pages/message_history_page/message_history_page_widget.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '/backend/schema/structs/index.dart'; import '/flutter_flow/flutter_flow_util.dart'; import '/index.dart'; import '../../pages/visit_history_page/visit_history_page_widget.dart'; export 'package:go_router/go_router.dart'; export 'serialization_util.dart'; const kTransitionInfoKey = '__transition_info__'; class AppStateNotifier extends ChangeNotifier { AppStateNotifier._(); static AppStateNotifier? _instance; static AppStateNotifier get instance => _instance ??= AppStateNotifier._(); bool showSplashImage = true; void stopShowingSplashImage() { showSplashImage = false; notifyListeners(); } } GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter( initialLocation: '/', debugLogDiagnostics: true, refreshListenable: appStateNotifier, // errorBuilder: (context, state) => appStateNotifier.showSplashImage // ? Builder( // builder: (context) => Container( // color: FlutterFlowTheme.of(context).primary, // child: Image.asset( // 'assets/images/logo.svg', // fit: BoxFit.cover, // ), // ), // ) // : const PeopleOnThePropertyPageWidget(), routes: [ // FFRoute( // name: '_initialize', // path: '/', // builder: (context, _) => appStateNotifier.showSplashImage // ? Builder( // builder: (context) => Container( // color: FlutterFlowTheme.of(context).primary, // child: Image.asset( // 'assets/images/favicon.png', // fit: BoxFit.cover, // ), // ), // ) // : const OnBoardingPageWidget(), // ), FFRoute( name: '_initialize', path: '/', builder: (context, _) => FFAppState().isLogged ? const HomePageWidget() : const WelcomePageWidget(), ), FFRoute( name: 'homePage', path: '/homePage', builder: (context, params) => const HomePageWidget(), ), FFRoute( name: 'visitHistoryPage', path: '/visitHistoryPage', builder: (context, params) => const VisitHistoryPageWidget(), ), FFRoute(name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => const MessageHistoryPageWidget()), FFRoute( name: 'registerVisitorPage', path: '/registerVisitorPage', builder: (context, params) => const RegisterVisitorPageWidget(), ), FFRoute( name: 'scheduleCompleteVisitPage', path: '/scheduleCompleteVisitPage', builder: (context, params) => ScheduleCompleteVisitPageWidget( visitorStrList: params.getParam( 'visitorStrList', ParamType.String, ), visitStartDateStr: params.getParam( 'visitStartDateStr', ParamType.String, ), visitEndDateStr: params.getParam( 'visitEndDateStr', ParamType.String, ), visitReasonStr: params.getParam( 'visitReasonStr', ParamType.String, ), visitLevelStr: params.getParam( 'visitLevelStr', ParamType.String, ), visitTempBol: params.getParam( 'visitTempBol', ParamType.bool, ), visitObsStr: params.getParam( 'visitObsStr', ParamType.String, ), visitorJsonList: params.getParam( 'visitorJsonList', ParamType.JSON, isList: true, ), ), ), FFRoute( name: 'scheduleProvisionalVisitPage', path: '/scheduleProvisionalVisitPage', builder: (context, params) => const ScheduleProvisionalVisitPageWidget(), ), FFRoute( name: 'fastPassPage', path: '/fastPassPage', builder: (context, params) => /*const*/ FastPassPageWidget(), ), FFRoute( name: 'peopleOnThePropertyPage', path: '/peopleOnThePropertyPage', builder: (context, params) => const PeopleOnThePropertyPageWidget(), ), FFRoute( name: 'acessHistoryPage', path: '/acessHistoryPage', builder: (context, params) => AcessHistoryPageWidget(opt: { 'personType': '.*', 'accessType': '.*', 'search': '.*', })), FFRoute( name: 'liberationHistory', path: '/liberationHistory', builder: (context, params) => const LiberationHistoryWidget(), ), FFRoute( name: 'signInPage', path: '/signInPage', builder: (context, params) => const SignInPageWidget(), ), FFRoute( name: 'signUpPage', path: '/signUpPage', builder: (context, params) => const SignUpPageWidget(), ), FFRoute( name: 'welcomePage', path: '/welcomePage', builder: (context, params) => const WelcomePageWidget(), ) ].map((r) => r.toRoute(appStateNotifier)).toList(), ); extension NavParamExtensions on Map { Map get withoutNulls => Map.fromEntries( entries .where((e) => e.value != null) .map((e) => MapEntry(e.key, e.value!)), ); } extension NavigationExtensions on BuildContext { void safePop() { // If there is only one route on the stack, navigate to the initial // page instead of popping. if (canPop()) { pop(); } else { go('/'); } } } extension _GoRouterStateExtensions on GoRouterState { Map get extraMap => extra != null ? extra as Map : {}; Map get allParams => {} ..addAll(pathParameters) ..addAll(uri.queryParameters) ..addAll(extraMap); TransitionInfo get transitionInfo => extraMap.containsKey(kTransitionInfoKey) ? extraMap[kTransitionInfoKey] as TransitionInfo : TransitionInfo.appDefault(); } class FFParameters { FFParameters(this.state, [this.asyncParams = const {}]); final GoRouterState state; final Map Function(String)> asyncParams; Map futureParamValues = {}; // Parameters are empty if the params map is empty or if the only parameter // present is the special extra parameter reserved for the transition info. bool get isEmpty => state.allParams.isEmpty || (state.allParams.length == 1 && state.extraMap.containsKey(kTransitionInfoKey)); bool isAsyncParam(MapEntry param) => asyncParams.containsKey(param.key) && param.value is String; bool get hasFutures => state.allParams.entries.any(isAsyncParam); Future completeFutures() => Future.wait( state.allParams.entries.where(isAsyncParam).map( (param) async { final doc = await asyncParams[param.key]!(param.value) .onError((_, __) => null); if (doc != null) { futureParamValues[param.key] = doc; return true; } return false; }, ), ).onError((_, __) => [false]).then((v) => v.every((e) => e)); dynamic getParam( String paramName, ParamType type, { bool isList = false, StructBuilder? structBuilder, }) { if (futureParamValues.containsKey(paramName)) { return futureParamValues[paramName]; } if (!state.allParams.containsKey(paramName)) { return null; } final param = state.allParams[paramName]; // Got parameter from `extras`, so just directly return it. if (param is! String) { return param; } // Return serialized value. return deserializeParam( param, type, isList, structBuilder: structBuilder, ); } } class FFRoute { const FFRoute({ required this.name, required this.path, required this.builder, this.requireAuth = false, this.asyncParams = const {}, this.routes = const [], }); final String name; final String path; final bool requireAuth; final Map Function(String)> asyncParams; final Widget Function(BuildContext, FFParameters) builder; final List routes; GoRoute toRoute(AppStateNotifier appStateNotifier) => GoRoute( name: name, path: path, pageBuilder: (context, state) { fixStatusBarOniOS16AndBelow(context); final ffParams = FFParameters(state, asyncParams); final page = ffParams.hasFutures ? FutureBuilder( future: ffParams.completeFutures(), builder: (context, _) => builder(context, ffParams), ) : builder(context, ffParams); final child = page; final transitionInfo = state.transitionInfo; return transitionInfo.hasTransition ? CustomTransitionPage( key: state.pageKey, child: child, transitionDuration: transitionInfo.duration, transitionsBuilder: (context, animation, secondaryAnimation, child) => PageTransition( type: transitionInfo.transitionType, duration: transitionInfo.duration, reverseDuration: transitionInfo.duration, alignment: transitionInfo.alignment, child: child, ).buildTransitions( context, animation, secondaryAnimation, child, ), ) : MaterialPage(key: state.pageKey, child: child); }, routes: routes, ); } class TransitionInfo { const TransitionInfo({ required this.hasTransition, this.transitionType = PageTransitionType.fade, this.duration = const Duration(milliseconds: 300), this.alignment, }); final bool hasTransition; final PageTransitionType transitionType; final Duration duration; final Alignment? alignment; static TransitionInfo appDefault() => const TransitionInfo(hasTransition: false); } class RootPageContext { const RootPageContext(this.isRootPage, [this.errorRoute]); final bool isRootPage; final String? errorRoute; static bool isInactiveRootPage(BuildContext context) { final rootPageContext = context.read(); final isRootPage = rootPageContext?.isRootPage ?? false; final location = GoRouterState.of(context).uri.toString(); return isRootPage && location != '/' && location != rootPageContext?.errorRoute; } static Widget wrap(Widget child, {String? errorRoute}) => Provider.value( value: RootPageContext(true, errorRoute), child: child, ); } extension GoRouterLocationExtension on GoRouter { String getCurrentLocation() { final RouteMatch lastMatch = routerDelegate.currentConfiguration.last; final RouteMatchList matchList = lastMatch is ImperativeRouteMatch ? lastMatch.matches : routerDelegate.currentConfiguration; return matchList.uri.toString(); } }