356 lines
11 KiB
Dart
356 lines
11 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:f_r_e_hub/pages/acess_history_page/acess_history_page_widget.dart';
|
|
import 'package:f_r_e_hub/pages/fast_pass_page/fast_pass_page_widget.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import '/backend/schema/structs/index.dart';
|
|
|
|
import '/index.dart';
|
|
import '/flutter_flow/flutter_flow_util.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: '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<dynamic>(
|
|
'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) => const AcessHistoryPageWidget()),
|
|
// 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<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 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<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,
|
|
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<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();
|
|
}
|
|
}
|