Skip to content

Instantly share code, notes, and snippets.

@mondoktamas
Created March 18, 2022 17:01
Show Gist options
  • Save mondoktamas/f44155f2bbcdbff8288bc0d19893aab4 to your computer and use it in GitHub Desktop.
Save mondoktamas/f44155f2bbcdbff8288bc0d19893aab4 to your computer and use it in GitHub Desktop.
import 'dart:ui';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mrz_parser/mrz_parser.dart';
import 'package:sas/application/presentation/features/add_and_edit_traveler/page/add_and_edit_traveler_bottom_sheet.dart';
import 'package:sas/application/presentation/features/add_and_edit_traveler/widgets/picker_selection_widget.dart';
import 'package:sas/application/presentation/features/forgot_password/page/forgot_password_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/page/book_page.dart';
import 'package:sas/application/presentation/features/main/features/book/page/bundle_page/bundle_selection_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/page/calendar_picker/page/calendar_picker_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/page/cart_detail_bottom_sheet/cart_details_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/page/flights_page/page/flight_details/page/flight_details_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/page/flights_page/page/flights_page.dart';
import 'package:sas/application/presentation/features/main/features/book/page/review_page/page/confirmation_page/page/confirmation_page.dart';
import 'package:sas/application/presentation/features/main/features/book/page/review_page/page/credit_card_web_view_bottom_sheet/credit_card_web_view_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/page/review_page/page/edit_travelers_bottom_sheet/edit_travelers_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/page/review_page/page/flight_more_details_bottom_sheet/flight_more_details_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/page/review_page/page/price_detail_page/price_details_page.dart';
import 'package:sas/application/presentation/features/main/features/book/page/review_page/page/review_page.dart';
import 'package:sas/application/presentation/features/main/features/book/page/review_page/widgets/personal_information_fields_widget.dart';
import 'package:sas/application/presentation/features/main/features/book/page/seats/seat_map/seat_map_page.dart';
import 'package:sas/application/presentation/features/main/features/book/page/traveler_bottom_sheet/mrz_scanner_page.dart';
import 'package:sas/application/presentation/features/main/features/book/page/traveler_bottom_sheet/select_travelers_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/widgets/search_departure_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/book/widgets/search_destination_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/home/page/home_page.dart';
import 'package:sas/application/presentation/features/main/features/more/feedback/page/feedback_page.dart';
import 'package:sas/application/presentation/features/main/features/more/flight_status/feature/flight_results/feature/flight_status_details/flight_status_details_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/more/flight_status/feature/flight_results/page/flight_results_page.dart';
import 'package:sas/application/presentation/features/main/features/more/flight_status/page/flight_status_page.dart';
import 'package:sas/application/presentation/features/main/features/more/more/page/more_page.dart';
import 'package:sas/application/presentation/features/main/features/profile/page/eurobonus/account_activity/account_activity_page.dart';
import 'package:sas/application/presentation/features/main/features/profile/page/eurobonus/eurobonus_page.dart';
import 'package:sas/application/presentation/features/main/features/profile/page/menu/profile_menu_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/profile/page/profile_page.dart';
import 'package:sas/application/presentation/features/main/features/profile/page/saved_travelers/saved_travelers_page.dart';
import 'package:sas/application/presentation/features/main/features/trips/add_booking/page/add_booking_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/trips/booking_details/page/booking_details_page.dart';
import 'package:sas/application/presentation/features/main/features/trips/check_in_final/page/check_in_final_page.dart';
import 'package:sas/application/presentation/features/main/features/trips/check_in_select/page/check_in_select_page.dart';
import 'package:sas/application/presentation/features/main/features/trips/covid_disclaimer/page/covid_disclaimer_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/trips/emergency_contact_info/page/emergency_contact_info_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/trips/passengers_required_info/page/passengers_required_info_page.dart';
import 'package:sas/application/presentation/features/main/features/trips/passport_and_accommodation_info/page/passport_and_accommodation_info_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/trips/personal_and_contact_info/page/personal_and_contact_info_bottom_sheet.dart';
import 'package:sas/application/presentation/features/main/features/trips/trips/page/trips_page.dart';
import 'package:sas/application/presentation/features/main/page/main_page.dart';
import 'package:sas/application/presentation/features/main/page/main_tabs_page.dart';
import 'package:sas/application/presentation/features/sign_in/page/sign_in_bottom_sheet.dart';
import 'package:sas/application/presentation/features/splash/page/splash_page.dart';
import 'package:sas/application/presentation/features/welcome/page/welcome_page.dart';
import 'package:sas/application/presentation/initial_page.dart';
import 'package:sas/application/presentation/resources/colors.dart';
@AdaptiveAutoRouter(
replaceInRouteName: 'Page|Screen|BottomSheet,Route',
routes: [
AutoRoute(
path: '/',
page: InitialPage,
children: [
AutoRoute(
initial: true,
page: SplashPage,
),
AutoRoute(
path: 'welcome',
page: WelcomePage,
),
CustomRoute(
path: 'sign_in',
page: SignInBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRoute,
),
CustomRoute(
path: 'forgot_password',
page: ForgotPasswordBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
AutoRoute(
path: 'main_page',
page: MainPage,
children: [
//region bottom sheet routes
CustomRoute(
path: 'select_travelers',
page: SelectTravelersBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRoute,
),
CustomRoute(
path: 'search_destination_airport',
page: SearchDestinationAirportBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'search_departure_airport',
page: SearchDepartureAirportBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'add_booking',
page: AddBookingBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'selection_picker',
page: SelectionPickerBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'date_picker',
page: DatePickerBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoScroll,
),
CustomRoute(
path: 'add_and_edit_traveler',
page: AddAndEditTravelerBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRoute,
),
CustomRoute(
path: 'calendar_picker',
page: CalendarPickerBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'flight_details',
page: FlightDetailsBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'bundle_selection',
page: BundleSelectionBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRoute,
),
CustomRoute(
path: 'flight_more_details',
page: FlightMoreDetailsBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRoute,
),
CustomRoute(
path: 'edit_traveler',
page: EditTravelersBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRoute,
),
CustomRoute(
path: 'profile_menu',
page: ProfileMenuBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRoute,
),
CustomRoute(
path: 'credit_card_web_view',
page: CreditCardWebViewBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'flight_status_details',
page: FlightStatusDetailsBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'personal_and_contact_info',
page: PersonalAndContactInfoBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteTransparent,
),
CustomRoute(
path: 'emergency_contact_info',
page: EmergencyContactInfoBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteTransparent,
),
CustomRoute(
path: 'passport_and_accommodation_contact_info',
page: PassportAndAccommodationInfoBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteTransparent,
),
CustomRoute(
path: 'cart_details',
page: CartDetailsBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteNoDrag,
),
CustomRoute(
path: 'covid_disclaimer',
page: CovidDisclaimerBottomSheet,
customRouteBuilder: CustomRouteBuilders.modalBottomSheetRouteTransparent,
),
//endregion
//region inner screen routes
AutoRoute(
initial: true,
page: MainTabsPage,
children: [
AutoRoute(path: 'book', page: BookPage),
AutoRoute(path: 'home', page: HomePage),
AutoRoute(path: 'trips', page: TripsPage),
AutoRoute(path: 'profile', page: ProfilePage),
AutoRoute(path: 'more', page: MorePage),
RedirectRoute(path: '', redirectTo: 'book'),
],
),
MaterialRoute<MRZResult>(path: 'mrz_scanner', page: MrzScannerPage),
AutoRoute(path: 'booking_details', page: BookingDetailsPage),
AutoRoute(path: 'flights_page', page: FlightsPage),
AutoRoute(path: 'review', page: ReviewPage),
AutoRoute(path: 'price_details', page: PriceDetailsPage),
AutoRoute(path: 'confirmation', page: ConfirmationPage),
AutoRoute(path: 'check_in_select', page: CheckInSelectPage),
AutoRoute(path: 'check_in_final', page: CheckInFinalPage),
AutoRoute(path: 'passengers_required_ingo', page: PassengersRequiredInfoPage),
AutoRoute(path: 'eurobonus', page: EurobonusPage),
AutoRoute(path: 'account_activity', page: AccountActivityPage),
AutoRoute(path: 'flight_status', page: FlightStatusPage),
AutoRoute(path: 'flight_results', page: FlightsResultsPage),
AutoRoute(path: 'saved_travelers', page: SavedTravelersPage),
AutoRoute(path: 'seat_map', page: SeatMapPage),
AutoRoute(path: 'feedback', page: FeedbackPage),
//endregion
],
),
],
),
RedirectRoute(
path: '*',
redirectTo: '/',
),
],
)
class $AppRouter {}
class CustomRouteBuilders {
const CustomRouteBuilders._();
static const CustomRouteBuilder modalBottomSheetRoute = _modalBottomSheetRoute;
static const CustomRouteBuilder modalBottomSheetRouteNoDrag = _modalBottomSheetRouteNoDrag;
static const CustomRouteBuilder modalBottomSheetRouteNoScroll = _modalBottomSheetRouteNoScroll;
static const CustomRouteBuilder cupertinoActionSheetRoute = _cupertinoActionSheetRoute;
static const CustomRouteBuilder modalBottomSheetRouteTransparent = _modalBottomSheetRouteTransparent;
static Route<T> _modalBottomSheetRoute<T>(
final BuildContext context,
final Widget child,
final CustomPage<T> customPage,
) =>
_ModalBottomSheetRoute(
builder: (context) => customPage.buildPage(context),
capturedThemes: InheritedTheme.capture(from: context, to: context),
isScrollControlled: true,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
modalBarrierColor: customPage.barrierColor,
settings: customPage,
);
static Route<T> _modalBottomSheetRouteNoDrag<T>(
final BuildContext context,
final Widget child,
final CustomPage<T> customPage,
) =>
_ModalBottomSheetRoute(
builder: (context) => customPage.buildPage(context),
capturedThemes: InheritedTheme.capture(from: context, to: context),
isScrollControlled: true,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
enableDrag: false,
modalBarrierColor: customPage.barrierColor,
settings: customPage,
);
static Route<T> _modalBottomSheetRouteNoScroll<T>(
final BuildContext context,
final Widget child,
final CustomPage<T> customPage,
) =>
_ModalBottomSheetRoute(
builder: (context) => customPage.buildPage(context),
capturedThemes: InheritedTheme.capture(from: context, to: context),
isScrollControlled: false,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
enableDrag: false,
modalBarrierColor: customPage.barrierColor,
settings: customPage,
);
static Route<T> _cupertinoActionSheetRoute<T>(
final BuildContext context,
final Widget child,
final CustomPage<T> customPage,
) =>
CupertinoModalPopupRoute(
builder: (context) => customPage.buildPage(context),
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
settings: customPage,
);
static Route<T> _modalBottomSheetRouteTransparent<T>(
final BuildContext context,
final Widget child,
final CustomPage<T> customPage,
) =>
_ModalBottomSheetRoute(
builder: (context) => customPage.buildPage(context),
backgroundColor: transparent,
shape: const BeveledRectangleBorder(),
capturedThemes: InheritedTheme.capture(from: context, to: context),
isScrollControlled: true,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
modalBarrierColor: customPage.barrierColor,
settings: customPage,
);
}
const Duration _bottomSheetEnterDuration = Duration(milliseconds: 250);
const Duration _bottomSheetExitDuration = Duration(milliseconds: 200);
const Curve _modalBottomSheetCurve = decelerateEasing;
class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
_ModalBottomSheetRoute({
this.builder,
required this.capturedThemes,
this.barrierLabel,
this.backgroundColor,
this.elevation,
this.shape,
this.clipBehavior,
this.constraints,
this.modalBarrierColor,
this.isDismissible = true,
this.enableDrag = true,
required this.isScrollControlled,
RouteSettings? settings,
this.transitionAnimationController,
}) : super(settings: settings);
final WidgetBuilder? builder;
final CapturedThemes capturedThemes;
final bool isScrollControlled;
final Color? backgroundColor;
final double? elevation;
final ShapeBorder? shape;
final Clip? clipBehavior;
final BoxConstraints? constraints;
final Color? modalBarrierColor;
final bool isDismissible;
final bool enableDrag;
final AnimationController? transitionAnimationController;
@override
Duration get transitionDuration => _bottomSheetEnterDuration;
@override
Duration get reverseTransitionDuration => _bottomSheetExitDuration;
@override
bool get barrierDismissible => isDismissible;
@override
final String? barrierLabel;
@override
Color get barrierColor => modalBarrierColor ?? Colors.black54;
AnimationController? _animationController;
@override
AnimationController createAnimationController() {
assert(_animationController == null);
if (transitionAnimationController != null) {
_animationController = transitionAnimationController;
willDisposeAnimationController = false;
} else {
_animationController = BottomSheet.createAnimationController(navigator!.overlay!);
}
return _animationController!;
}
@override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
final Widget bottomSheet = MediaQuery.removePadding(
context: context,
removeTop: true,
child: Builder(
builder: (BuildContext context) {
final sheetTheme = Theme.of(context).bottomSheetTheme;
return _ModalBottomSheet<T>(
route: this,
backgroundColor: backgroundColor ?? sheetTheme.modalBackgroundColor ?? sheetTheme.backgroundColor,
elevation: elevation ?? sheetTheme.modalElevation ?? sheetTheme.elevation,
shape: shape,
clipBehavior: clipBehavior,
constraints: constraints,
isScrollControlled: isScrollControlled,
enableDrag: enableDrag,
);
},
),
);
return capturedThemes.wrap(bottomSheet);
}
}
class _ModalBottomSheetLayout extends SingleChildLayoutDelegate {
_ModalBottomSheetLayout(this.progress, this.isScrollControlled);
final double progress;
final bool isScrollControlled;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) => BoxConstraints(
minWidth: constraints.maxWidth,
maxWidth: constraints.maxWidth,
maxHeight: isScrollControlled ? constraints.maxHeight : constraints.maxHeight * 9.0 / 16.0,
);
@override
Offset getPositionForChild(Size size, Size childSize) => Offset(0.0, size.height - childSize.height * progress);
@override
bool shouldRelayout(_ModalBottomSheetLayout oldDelegate) => progress != oldDelegate.progress;
}
class _ModalBottomSheet<T> extends StatefulWidget {
const _ModalBottomSheet({
Key? key,
this.route,
this.backgroundColor,
this.elevation,
this.shape,
this.clipBehavior,
this.constraints,
this.isScrollControlled = false,
this.enableDrag = true,
}) : super(key: key);
final _ModalBottomSheetRoute<T>? route;
final bool isScrollControlled;
final Color? backgroundColor;
final double? elevation;
final ShapeBorder? shape;
final Clip? clipBehavior;
final BoxConstraints? constraints;
final bool enableDrag;
@override
_ModalBottomSheetState<T> createState() => _ModalBottomSheetState<T>();
}
class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
ParametricCurve<double> animationCurve = _modalBottomSheetCurve;
String _getRouteLabel(MaterialLocalizations localizations) {
switch (Theme.of(context).platform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
return '';
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
return localizations.dialogLabel;
}
}
void handleDragStart(DragStartDetails details) {
animationCurve = Curves.linear;
}
void handleDragEnd(DragEndDetails details, {bool? isClosing}) {
animationCurve = _BottomSheetSuspendedCurve(
widget.route!.animation!.value,
curve: _modalBottomSheetCurve,
);
}
@override
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
final mediaQuery = MediaQuery.of(context);
final localizations = MaterialLocalizations.of(context);
final routeLabel = _getRouteLabel(localizations);
return AnimatedBuilder(
animation: widget.route!.animation!,
child: BottomSheet(
animationController: widget.route!._animationController,
onClosing: () {
if (widget.route!.isCurrent) {
Navigator.pop(context);
}
},
builder: widget.route!.builder!,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
clipBehavior: widget.clipBehavior,
constraints: widget.constraints,
enableDrag: widget.enableDrag,
onDragStart: handleDragStart,
onDragEnd: handleDragEnd,
),
builder: (BuildContext context, Widget? child) {
final animationValue = animationCurve.transform(
mediaQuery.accessibleNavigation ? 1.0 : widget.route!.animation!.value,
);
return Semantics(
scopesRoute: true,
namesRoute: true,
label: routeLabel,
explicitChildNodes: true,
child: ClipRect(
child: CustomSingleChildLayout(
delegate: _ModalBottomSheetLayout(animationValue, widget.isScrollControlled),
child: child,
),
),
);
},
);
}
}
class _BottomSheetSuspendedCurve extends ParametricCurve<double> {
const _BottomSheetSuspendedCurve(
this.startingPoint, {
this.curve = Curves.easeOutCubic,
});
final double startingPoint;
final Curve curve;
@override
double transform(double t) {
assert(t >= 0.0 && t <= 1.0);
assert(startingPoint >= 0.0 && startingPoint <= 1.0);
if (t < startingPoint) {
return t;
}
if (t == 1.0) {
return t;
}
final curveProgress = (t - startingPoint) / (1 - startingPoint);
final transformed = curve.transform(curveProgress);
return lerpDouble(startingPoint, 1, transformed)!;
}
@override
String toString() => '${describeIdentity(this)}($startingPoint, $curve)';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment