| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- import 'dart:async';
- import 'package:flutter/material.dart';
- import 'package:flutter_spinkit/flutter_spinkit.dart';
- import 'package:go_router/go_router.dart';
- import 'package:page_transition/page_transition.dart';
- import 'package:provider/provider.dart';
- import '/backend/schema/structs/index.dart';
- import '/auth/custom_auth/custom_auth_user_provider.dart';
- import '/main.dart';
- import '/flutter_flow/flutter_flow_theme.dart';
- import '/flutter_flow/lat_lng.dart';
- import '/flutter_flow/place.dart';
- import '/flutter_flow/flutter_flow_util.dart';
- import 'serialization_util.dart';
- import '/index.dart';
- export 'package:go_router/go_router.dart';
- export 'serialization_util.dart';
- const kTransitionInfoKey = '__transition_info__';
- GlobalKey<NavigatorState> appNavigatorKey = GlobalKey<NavigatorState>();
- const debugRouteLinkMap = {
- '/login':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=login',
- '/horecagelegenheidCurrent':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=horecagelegenheidCurrent',
- '/home':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=home',
- '/selectprovinciegemeente':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=selectprovinciegemeente',
- '/pUitgaanPage':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=PUitgaanPage',
- '/event':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=Event',
- '/eventCurrent':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=EventCurrent',
- '/horecagelegenhedenOverzicht':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=HorecagelegenhedenOverzicht',
- '/horecagelegenhedenOverzichtPageDataType':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=HorecagelegenhedenOverzichtPageDataType',
- '/horecagelegenhedenOverzichtSortPage':
- 'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=HorecagelegenhedenOverzichtSortPage'
- };
- class AppStateNotifier extends ChangeNotifier {
- AppStateNotifier._();
- static AppStateNotifier? _instance;
- static AppStateNotifier get instance => _instance ??= AppStateNotifier._();
- UitgaanskrantAuthUser? initialUser;
- UitgaanskrantAuthUser? user;
- bool showSplashImage = true;
- String? _redirectLocation;
- /// Determines whether the app will refresh and build again when a sign
- /// in or sign out happens. This is useful when the app is launched or
- /// on an unexpected logout. However, this must be turned off when we
- /// intend to sign in/out and then navigate or perform any actions after.
- /// Otherwise, this will trigger a refresh and interrupt the action(s).
- bool notifyOnAuthChange = true;
- bool get loading => user == null || showSplashImage;
- bool get loggedIn => user?.loggedIn ?? false;
- bool get initiallyLoggedIn => initialUser?.loggedIn ?? false;
- bool get shouldRedirect => loggedIn && _redirectLocation != null;
- String getRedirectLocation() => _redirectLocation!;
- bool hasRedirect() => _redirectLocation != null;
- void setRedirectLocationIfUnset(String loc) => _redirectLocation ??= loc;
- void clearRedirectLocation() => _redirectLocation = null;
- /// Mark as not needing to notify on a sign in / out when we intend
- /// to perform subsequent actions (such as navigation) afterwards.
- void updateNotifyOnAuthChange(bool notify) => notifyOnAuthChange = notify;
- void update(UitgaanskrantAuthUser newUser) {
- final shouldUpdate =
- user?.uid == null || newUser.uid == null || user?.uid != newUser.uid;
- initialUser ??= newUser;
- user = newUser;
- // Refresh the app on auth change unless explicitly marked otherwise.
- // No need to update unless the user has changed.
- if (notifyOnAuthChange && shouldUpdate) {
- notifyListeners();
- }
- // Once again mark the notifier as needing to update on auth change
- // (in order to catch sign in / out events).
- updateNotifyOnAuthChange(true);
- }
- void stopShowingSplashImage() {
- showSplashImage = false;
- notifyListeners();
- }
- }
- GoRouter createRouter(AppStateNotifier appStateNotifier) => GoRouter(
- initialLocation: '/',
- debugLogDiagnostics: true,
- refreshListenable: appStateNotifier,
- navigatorKey: appNavigatorKey,
- errorBuilder: (context, state) => appStateNotifier.loggedIn
- ? SelectprovinciegemeenteWidget()
- : HomeWidget(),
- routes: [
- FFRoute(
- name: '_initialize',
- path: '/',
- builder: (context, _) => appStateNotifier.loggedIn
- ? SelectprovinciegemeenteWidget()
- : HomeWidget(),
- ),
- FFRoute(
- name: LoginWidget.routeName,
- path: LoginWidget.routePath,
- builder: (context, params) => LoginWidget(),
- ),
- FFRoute(
- name: HorecagelegenheidCurrentWidget.routeName,
- path: HorecagelegenheidCurrentWidget.routePath,
- builder: (context, params) => HorecagelegenheidCurrentWidget(
- nid: params.getParam(
- 'nid',
- ParamType.String,
- ),
- ),
- ),
- FFRoute(
- name: HomeWidget.routeName,
- path: HomeWidget.routePath,
- builder: (context, params) => HomeWidget(),
- ),
- FFRoute(
- name: SelectprovinciegemeenteWidget.routeName,
- path: SelectprovinciegemeenteWidget.routePath,
- builder: (context, params) => SelectprovinciegemeenteWidget(),
- ),
- FFRoute(
- name: PUitgaanPageWidget.routeName,
- path: PUitgaanPageWidget.routePath,
- builder: (context, params) => PUitgaanPageWidget(
- plaats: params.getParam(
- 'plaats',
- ParamType.String,
- ),
- services: params.getParam(
- 'services',
- ParamType.String,
- ),
- ),
- ),
- FFRoute(
- name: EventWidget.routeName,
- path: EventWidget.routePath,
- builder: (context, params) => EventWidget(
- nid: params.getParam(
- 'nid',
- ParamType.String,
- ),
- ),
- ),
- FFRoute(
- name: EventCurrentWidget.routeName,
- path: EventCurrentWidget.routePath,
- builder: (context, params) => EventCurrentWidget(
- nid: params.getParam(
- 'nid',
- ParamType.String,
- ),
- horecaid: params.getParam(
- 'horecaid',
- ParamType.String,
- ),
- ),
- ),
- FFRoute(
- name: HorecagelegenhedenOverzichtWidget.routeName,
- path: HorecagelegenhedenOverzichtWidget.routePath,
- builder: (context, params) => HorecagelegenhedenOverzichtWidget(
- plaats: params.getParam(
- 'plaats',
- ParamType.String,
- ),
- ),
- ),
- FFRoute(
- name: HorecagelegenhedenOverzichtPageDataTypeWidget.routeName,
- path: HorecagelegenhedenOverzichtPageDataTypeWidget.routePath,
- builder: (context, params) =>
- HorecagelegenhedenOverzichtPageDataTypeWidget(
- plaats: params.getParam(
- 'plaats',
- ParamType.String,
- ),
- ),
- ),
- FFRoute(
- name: HorecagelegenhedenOverzichtSortPageWidget.routeName,
- path: HorecagelegenhedenOverzichtSortPageWidget.routePath,
- builder: (context, params) =>
- HorecagelegenhedenOverzichtSortPageWidget(
- plaats: params.getParam(
- 'plaats',
- ParamType.String,
- ),
- ),
- )
- ].map((r) => r.toRoute(appStateNotifier)).toList(),
- observers: [routeObserver],
- );
- extension NavParamExtensions on Map<String, String?> {
- Map<String, String> get withoutNulls => Map.fromEntries(
- entries
- .where((e) => e.value != null)
- .map((e) => MapEntry(e.key, e.value!)),
- );
- }
- extension NavigationExtensions on BuildContext {
- void goNamedAuth(
- String name,
- bool mounted, {
- Map<String, String> pathParameters = const <String, String>{},
- Map<String, String> queryParameters = const <String, String>{},
- Object? extra,
- bool ignoreRedirect = false,
- }) =>
- !mounted || GoRouter.of(this).shouldRedirect(ignoreRedirect)
- ? null
- : goNamed(
- name,
- pathParameters: pathParameters,
- queryParameters: queryParameters,
- extra: extra,
- );
- void pushNamedAuth(
- String name,
- bool mounted, {
- Map<String, String> pathParameters = const <String, String>{},
- Map<String, String> queryParameters = const <String, String>{},
- Object? extra,
- bool ignoreRedirect = false,
- }) =>
- !mounted || GoRouter.of(this).shouldRedirect(ignoreRedirect)
- ? null
- : pushNamed(
- name,
- pathParameters: pathParameters,
- queryParameters: queryParameters,
- extra: extra,
- );
- 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 GoRouterExtensions on GoRouter {
- AppStateNotifier get appState => AppStateNotifier.instance;
- void prepareAuthEvent([bool ignoreRedirect = false]) =>
- appState.hasRedirect() && !ignoreRedirect
- ? null
- : appState.updateNotifyOnAuthChange(false);
- bool shouldRedirect(bool ignoreRedirect) =>
- !ignoreRedirect && appState.hasRedirect();
- void clearRedirectLocation() => appState.clearRedirectLocation();
- void setRedirectLocationIfUnset(String location) =>
- appState.updateNotifyOnAuthChange(false);
- }
- extension _GoRouterStateExtensions on GoRouterState {
- Map<String, dynamic> get extraMap =>
- extra != null ? extra as Map<String, dynamic> : {};
- Map<String, dynamic> get allParams => <String, dynamic>{}
- ..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<String, Future<dynamic> Function(String)> asyncParams;
- Map<String, dynamic> 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<String, dynamic> param) =>
- asyncParams.containsKey(param.key) && param.value is String;
- bool get hasFutures => state.allParams.entries.any(isAsyncParam);
- Future<bool> 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<T>(
- String paramName,
- ParamType type, {
- bool isList = false,
- StructBuilder<T>? 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<T>(
- 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<String, Future<dynamic> Function(String)> asyncParams;
- final Widget Function(BuildContext, FFParameters) builder;
- final List<GoRoute> routes;
- GoRoute toRoute(AppStateNotifier appStateNotifier) => GoRoute(
- name: name,
- path: path,
- redirect: (context, state) {
- if (appStateNotifier.shouldRedirect) {
- final redirectLocation = appStateNotifier.getRedirectLocation();
- appStateNotifier.clearRedirectLocation();
- return redirectLocation;
- }
- if (requireAuth && !appStateNotifier.loggedIn) {
- appStateNotifier.setRedirectLocationIfUnset(state.uri.toString());
- return '/home';
- }
- return null;
- },
- 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 = appStateNotifier.loading
- ? Center(
- child: SizedBox(
- width: 80.0,
- height: 80.0,
- child: SpinKitFadingCircle(
- color: Color(0xFFB1061E),
- size: 80.0,
- ),
- ),
- )
- : page;
- final transitionInfo = state.transitionInfo;
- return transitionInfo.hasTransition
- ? CustomTransitionPage(
- key: state.pageKey,
- name: state.name,
- 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, name: state.name, 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() => 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<RootPageContext?>();
- 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();
- }
- }
|