flutter-freaccess-hub/lib/flutter_flow/nav/nav.dart

425 lines
14 KiB
Dart

import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/pages/delivery_schedule_page/delivery_schedule_widget.dart';
import 'package:hub/pages/fast_pass_page/fast_pass_page_widget.dart';
import 'package:hub/pages/forgot_password_page/forgot_password_screen.dart';
import 'package:hub/pages/message_history_page/message_history_page_widget.dart';
import 'package:hub/pages/package_order_page/package_order_page.dart';
import 'package:hub/pages/pets_page/pets_page_widget.dart';
import 'package:hub/pages/provisional_schedule_page/provisional_schedule_widget.dart';
import 'package:hub/pages/reception_page/reception_page_widget.dart';
import 'package:hub/pages/reservation_page/reservation_page_widget.dart';
import 'package:hub/shared/helpers/base_storage.dart';
import 'package:hub/shared/helpers/storage_helper.dart';
import 'package:provider/provider.dart';
import '../../shared/utils/dialog_util.dart';
import '/backend/schema/structs/index.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/index.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) {
return 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, _) {
return FutureBuilder<Widget>(
future: () async {
final bool isLogged =
await StorageHelper().get(SecureStorageKey.isLogged.value, Storage.SecureStorage) == 'true';
final bool haveLocal =
await StorageHelper().get(SecureStorageKey.haveLocal.value, Storage.SecureStorage) == 'true';
final bool haveUserUUID =
(await StorageHelper().get(SQLiteStorageKey.userUUID.value, Storage.SQLiteStorage))?.isNotEmpty ??
false;
final bool haveDevUUID =
(await StorageHelper().get(SQLiteStorageKey.devUUID.value, Storage.SQLiteStorage))?.isNotEmpty ??
false;
if (isLogged && haveDevUUID && haveUserUUID) {
return haveLocal ? const HomePageWidget() : const ReceptionPageWidget();
} else {
return const WelcomePageWidget();
}
}(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
DialogUtil.error(context, snapshot.error.toString());
return const WelcomePageWidget();
} else {
return snapshot.data!;
}
},
);
},
),
FFRoute(
name: 'forgotPassword',
path: '/forgotPassword',
builder: (context, params) {
late final String email = params.getParam('email', ParamType.String);
late final String token = params.getParam('token', ParamType.String);
return ForgotPasswordScreen(
key: UniqueKey(),
email: email,
token: token,
);
}),
FFRoute(
name: 'homePage',
path: '/homePage',
builder: (context, params) => HomePageWidget(key: UniqueKey()),
),
FFRoute(name: 'receptionPage', path: '/receptionPage', builder: (context, params) => const ReceptionPageWidget()),
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) {
return const ScheduleCompleteVisitPageWidget();
}),
FFRoute(
name: 'deliverySchedule',
path: '/deliverySchedule',
builder: (context, params) => const DeliverySchedule(),
),
FFRoute(
name: 'provisionalSchedule',
path: '/provisionalSchedule',
builder: (context, params) => const ProvisionalSchedule(),
),
FFRoute(
name: 'fastPassPage',
path: '/fastPassPage',
builder: (context, params) => /*const*/ FastPassPageWidget(),
),
FFRoute(
name: 'preferencesSettings',
path: '/preferencesSettings',
builder: (context, params) => PreferencesPageWidget()),
FFRoute(
name: 'peopleOnThePropertyPage',
path: '/peopleOnThePropertyPage',
builder: (context, params) => const PeopleOnThePropertyPageWidget(),
),
FFRoute(
name: 'acessHistoryPage',
path: '/acessHistoryPage',
builder: (context, params) => AccessHistoryScreen(opt: const {
'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(),
),
FFRoute(
name: 'qrCodePage',
path: '/qrCodePage',
builder: (context, params) => const QrCodePageWidget(),
),
FFRoute(
name: 'preferencesPage',
path: '/preferencesPage',
builder: (context, params) => PreferencesPageWidget(),
),
FFRoute(
name: 'packageOrder',
path: '/packageOrder',
builder: (context, params) => const PackageOrderPage(),
),
FFRoute(
name: 'reservation',
path: '/reservation',
builder: (context, params) => ReservationPageWidget(),
),
FFRoute(
name: 'petsPage',
path: '/petsPage',
builder: (context, params) {
final pet = params.getParam(
'pet',
ParamType.JSON,
);
return PetsPageWidget(
pet: pet,
);
},
),
// FFRoute(
// name: 'settingsPage',
// path: '/settingsPage',
// builder: (context, params) => params.isEmpty
// ? const NavBarPage(initialPage: 'settingsPage')
// : const SettingsPageWidget(),
// )
].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();
}
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();
}
}
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,
);
}