fix(driver): ضمّ حزم get و get_storage داخل المستودع

apps/driver كان يشير إلى `../../Intaleq/packages/get` خارج المستودع — وهو
مسار يُحل من apps/driver إلى Tripz/Intaleq/ غير الموجود، فلا يمرّ
`flutter pub get` إطلاقاً. (فجوة docs/30 §2.6.)

ضُمّت نسخة **انطلق** تحديداً (App/Intaleq/packages) لا فرع apps/rider:
الفرعان يختلفان فعلاً — snackbar_controller.dart و get_queue.dart وغيرهما
مختلفة بين النسختين، فاستعارة فرع rider كانت ستغيّر سلوك السائق صامتة.

  apps/driver/packages/get         (3.5 م.ب، 202 ملف dart مع get_storage)
  apps/driver/packages/get_storage
  pubspec: ../../Intaleq/packages/* → ./packages/*  (3 مواضع، منها
  dependency_overrides سطر 142)

المستودع صار مكتفياً ذاتياً: لا تبعية مسار خارج شجرته. لم يُمسّ App/Intaleq.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-27 05:16:10 +03:00
co-authored by Claude Opus 5
parent 4d8414c96b
commit ecbe245b77
482 changed files with 64909 additions and 3 deletions
@@ -0,0 +1,46 @@
import 'dart:math' show sqrt, max;
import 'dart:ui' show lerpDouble;
import 'package:flutter/material.dart';
class CircularRevealClipper extends CustomClipper<Path> {
final double fraction;
final Alignment? centerAlignment;
final Offset? centerOffset;
final double? minRadius;
final double? maxRadius;
CircularRevealClipper({
required this.fraction,
this.centerAlignment,
this.centerOffset,
this.minRadius,
this.maxRadius,
});
@override
Path getClip(Size size) {
final center = centerAlignment?.alongSize(size) ??
centerOffset ??
Offset(size.width / 2, size.height / 2);
final minRadius = this.minRadius ?? 0;
final maxRadius = this.maxRadius ?? calcMaxRadius(size, center);
return Path()
..addOval(
Rect.fromCircle(
center: center,
radius: lerpDouble(minRadius, maxRadius, fraction)!,
),
);
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
static double calcMaxRadius(Size size, Offset center) {
final w = max(center.dx, size.width - center.dx);
final h = max(center.dy, size.height - center.dy);
return sqrt(w * w + h * h);
}
}
@@ -0,0 +1,13 @@
import 'package:flutter/widgets.dart';
// ignore: one_member_abstracts
abstract class CustomTransition {
Widget buildTransition(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
);
}
@@ -0,0 +1,127 @@
import 'package:flutter/material.dart';
import '../../../get.dart';
import '../router_report.dart';
import 'get_transition_mixin.dart';
mixin PageRouteReportMixin<T> on Route<T> {
@override
void install() {
super.install();
RouterReportManager.reportCurrentRoute(this);
}
@override
void dispose() {
super.dispose();
RouterReportManager.reportRouteDispose(this);
}
}
class GetPageRoute<T> extends PageRoute<T>
with GetPageRouteTransitionMixin<T>, PageRouteReportMixin {
/// Creates a page route for use in an iOS designed app.
///
/// The [builder], [maintainState], and [fullscreenDialog] arguments must not
/// be null.
GetPageRoute({
RouteSettings? settings,
this.transitionDuration = const Duration(milliseconds: 300),
this.opaque = true,
this.parameter,
this.gestureWidth,
this.curve,
this.alignment,
this.transition,
this.popGesture,
this.customTransition,
this.barrierDismissible = false,
this.barrierColor,
this.binding,
this.bindings,
this.routeName,
this.page,
this.title,
this.showCupertinoParallax = true,
this.barrierLabel,
this.maintainState = true,
bool fullscreenDialog = false,
this.middlewares,
}) : super(settings: settings, fullscreenDialog: fullscreenDialog);
@override
final Duration transitionDuration;
final GetPageBuilder? page;
final String? routeName;
//final String reference;
final CustomTransition? customTransition;
final Bindings? binding;
final Map<String, String>? parameter;
final List<Bindings>? bindings;
@override
final bool showCupertinoParallax;
@override
final bool opaque;
final bool? popGesture;
@override
final bool barrierDismissible;
final Transition? transition;
final Curve? curve;
final Alignment? alignment;
final List<GetMiddleware>? middlewares;
@override
final Color? barrierColor;
@override
final String? barrierLabel;
@override
final bool maintainState;
@override
void dispose() {
super.dispose();
final middlewareRunner = MiddlewareRunner(middlewares);
middlewareRunner.runOnPageDispose();
}
Widget? _child;
Widget _getChild() {
if (_child != null) return _child!;
final middlewareRunner = MiddlewareRunner(middlewares);
final localbindings = [
if (bindings != null) ...bindings!,
if (binding != null) ...[binding!]
];
final bindingsToBind = middlewareRunner.runOnBindingsStart(localbindings);
if (bindingsToBind != null) {
for (final binding in bindingsToBind) {
binding.dependencies();
}
}
final pageToBuild = middlewareRunner.runOnPageBuildStart(page)!;
_child = middlewareRunner.runOnPageBuilt(pageToBuild());
return _child!;
}
@override
Widget buildContent(BuildContext context) {
return _getChild();
}
@override
final String? title;
@override
String get debugLabel => '${super.debugLabel}(${settings.name})';
@override
final double Function(BuildContext context)? gestureWidth;
}
@@ -0,0 +1,209 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'circular_reveal_clipper.dart';
class LeftToRightFadeTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(-1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: FadeTransition(
opacity: animation,
child: SlideTransition(
position: Tween<Offset>(
begin: Offset.zero,
end: const Offset(1.0, 0.0),
).animate(secondaryAnimation),
child: child),
),
);
}
}
class RightToLeftFadeTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: FadeTransition(
opacity: animation,
child: SlideTransition(
position: Tween<Offset>(
begin: Offset.zero,
end: const Offset(-1.0, 0.0),
).animate(secondaryAnimation),
child: child),
),
);
}
}
class NoTransition {
Widget buildTransitions(
BuildContext context,
Curve curve,
Alignment alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return child;
}
}
class FadeInTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return FadeTransition(opacity: animation, child: child);
}
}
class SlideDownTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(0.0, 1.0),
end: Offset.zero,
).animate(animation),
child: child,
);
}
}
class SlideLeftTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(-1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child,
);
}
}
class SlideRightTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child,
);
}
}
class SlideTopTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(0.0, -1.0),
end: Offset.zero,
).animate(animation),
child: child,
);
}
}
class ZoomInTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return ScaleTransition(
scale: animation,
child: child,
);
}
}
class SizeTransitions {
Widget buildTransitions(
BuildContext context,
Curve curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return Align(
alignment: Alignment.center,
child: SizeTransition(
sizeFactor: CurvedAnimation(
parent: animation,
curve: curve,
),
child: child,
),
);
}
}
class CircularRevealTransition {
Widget buildTransitions(
BuildContext context,
Curve? curve,
Alignment? alignment,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return ClipPath(
clipper: CircularRevealClipper(
fraction: animation.value,
centerAlignment: Alignment.center,
centerOffset: Offset.zero,
minRadius: 0,
maxRadius: 800,
),
child: child,
);
}
}
@@ -0,0 +1,184 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../../get_core/src/get_main.dart';
import '../../../get_instance/get_instance.dart';
import '../../get_navigation.dart';
class GetPage<T> extends Page<T> {
final GetPageBuilder page;
final bool? popGesture;
final Map<String, String>? parameters;
final String? title;
final Transition? transition;
final Curve curve;
final bool? participatesInRootNavigator;
final Alignment? alignment;
final bool maintainState;
final bool opaque;
final double Function(BuildContext context)? gestureWidth;
final Bindings? binding;
final List<Bindings> bindings;
final CustomTransition? customTransition;
final Duration? transitionDuration;
final bool fullscreenDialog;
final bool preventDuplicates;
// @override
// final LocalKey? key;
// @override
// RouteSettings get settings => this;
@override
final Object? arguments;
@override
final String name;
final List<GetPage> children;
final List<GetMiddleware>? middlewares;
final PathDecoded path;
final GetPage? unknownRoute;
final bool showCupertinoParallax;
GetPage({
required this.name,
required this.page,
this.title,
this.participatesInRootNavigator,
this.gestureWidth,
// RouteSettings settings,
this.maintainState = true,
this.curve = Curves.linear,
this.alignment,
this.parameters,
this.opaque = true,
this.transitionDuration,
this.popGesture,
this.binding,
this.bindings = const [],
this.transition,
this.customTransition,
this.fullscreenDialog = false,
this.children = const <GetPage>[],
this.middlewares,
this.unknownRoute,
this.arguments,
this.showCupertinoParallax = true,
this.preventDuplicates = true,
}) : path = _nameToRegex(name),
assert(name.startsWith('/'),
'It is necessary to start route name [$name] with a slash: /$name'),
super(
key: ValueKey(name),
name: name,
arguments: Get.arguments,
);
// settings = RouteSettings(name: name, arguments: Get.arguments);
GetPage<T> copy({
String? name,
GetPageBuilder? page,
bool? popGesture,
Map<String, String>? parameters,
String? title,
Transition? transition,
Curve? curve,
Alignment? alignment,
bool? maintainState,
bool? opaque,
Bindings? binding,
List<Bindings>? bindings,
CustomTransition? customTransition,
Duration? transitionDuration,
bool? fullscreenDialog,
RouteSettings? settings,
List<GetPage>? children,
GetPage? unknownRoute,
List<GetMiddleware>? middlewares,
bool? preventDuplicates,
final double Function(BuildContext context)? gestureWidth,
bool? participatesInRootNavigator,
Object? arguments,
bool? showCupertinoParallax,
}) {
return GetPage(
participatesInRootNavigator:
participatesInRootNavigator ?? this.participatesInRootNavigator,
preventDuplicates: preventDuplicates ?? this.preventDuplicates,
name: name ?? this.name,
page: page ?? this.page,
popGesture: popGesture ?? this.popGesture,
parameters: parameters ?? this.parameters,
title: title ?? this.title,
transition: transition ?? this.transition,
curve: curve ?? this.curve,
alignment: alignment ?? this.alignment,
maintainState: maintainState ?? this.maintainState,
opaque: opaque ?? this.opaque,
binding: binding ?? this.binding,
bindings: bindings ?? this.bindings,
customTransition: customTransition ?? this.customTransition,
transitionDuration: transitionDuration ?? this.transitionDuration,
fullscreenDialog: fullscreenDialog ?? this.fullscreenDialog,
children: children ?? this.children,
unknownRoute: unknownRoute ?? this.unknownRoute,
middlewares: middlewares ?? this.middlewares,
gestureWidth: gestureWidth ?? this.gestureWidth,
arguments: arguments ?? this.arguments,
showCupertinoParallax:
showCupertinoParallax ?? this.showCupertinoParallax,
);
}
@override
Route<T> createRoute(BuildContext context) {
// return GetPageRoute<T>(settings: this, page: page);
final _page = PageRedirect(
route: this,
settings: this,
unknownRoute: unknownRoute,
).getPageToRoute<T>(this, unknownRoute);
return _page;
}
static PathDecoded _nameToRegex(String path) {
var keys = <String?>[];
String _replace(Match pattern) {
var buffer = StringBuffer('(?:');
if (pattern[1] != null) buffer.write('\.');
buffer.write('([\\w%+-._~!\$&\'()*,;=:@]+))');
if (pattern[3] != null) buffer.write('?');
keys.add(pattern[2]);
return "$buffer";
}
var stringPath = '$path/?'
.replaceAllMapped(RegExp(r'(\.)?:(\w+)(\?)?'), _replace)
.replaceAll('//', '/');
return PathDecoded(RegExp('^$stringPath\$'), keys);
}
}
@immutable
class PathDecoded {
final RegExp regex;
final List<String?> keys;
const PathDecoded(this.regex, this.keys);
@override
int get hashCode => regex.hashCode;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is PathDecoded &&
other.regex == regex; // && listEquals(other.keys, keys);
}
}
@@ -0,0 +1,714 @@
import 'dart:math';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import '../../../get.dart';
import 'default_transitions.dart';
const double _kBackGestureWidth = 20.0;
const int _kMaxDroppedSwipePageForwardAnimationTime =
800; // Screen widths per second.
// An eyeballed value for the maximum time it takes
//for a page to animate forward
// if the user releases a page mid swipe.
const int _kMaxPageBackAnimationTime = 300; // Milliseconds.
// The maximum time for a page to get reset to it's original position if the
// user releases a page mid swipe.
const double _kMinFlingVelocity = 1.0; // Milliseconds.
class CupertinoBackGestureController<T> {
final AnimationController controller;
final NavigatorState navigator;
/// Creates a controller for an iOS-style back gesture.
///
/// The [navigator] and [controller] arguments must not be null.
CupertinoBackGestureController({
required this.navigator,
required this.controller,
}) {
navigator.didStartUserGesture();
}
/// The drag gesture has ended with a horizontal motion of
/// [fractionalVelocity] as a fraction of screen width per second.
void dragEnd(double velocity) {
// Fling in the appropriate direction.
// AnimationController.fling is guaranteed to
// take at least one frame.
//
// This curve has been determined through rigorously eyeballing native iOS
// animations.
const Curve animationCurve = Curves.fastLinearToSlowEaseIn;
final bool animateForward;
// If the user releases the page before mid screen with sufficient velocity,
// or after mid screen, we should animate the page out. Otherwise, the page
// should be animated back in.
if (velocity.abs() >= _kMinFlingVelocity) {
animateForward = velocity <= 0;
} else {
animateForward = controller.value > 0.5;
}
if (animateForward) {
// The closer the panel is to dismissing, the shorter the animation is.
// We want to cap the animation time, but we want to use a linear curve
// to determine it.
final droppedPageForwardAnimationTime = min(
lerpDouble(
_kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value)!
.floor(),
_kMaxPageBackAnimationTime,
);
controller.animateTo(1.0,
duration: Duration(milliseconds: droppedPageForwardAnimationTime),
curve: animationCurve);
} else {
// This route is destined to pop at this point. Reuse navigator's pop.
navigator.pop();
// The popping may have finished inline if already at the
// target destination.
if (controller.isAnimating) {
// Otherwise, use a custom popping animation duration and curve.
final droppedPageBackAnimationTime = lerpDouble(
0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value)!
.floor();
controller.animateBack(0.0,
duration: Duration(milliseconds: droppedPageBackAnimationTime),
curve: animationCurve);
}
}
if (controller.isAnimating) {
// Keep the userGestureInProgress in true state so we don't change the
// curve of the page transition mid-flight since CupertinoPageTransition
// depends on userGestureInProgress.
late AnimationStatusListener animationStatusCallback;
animationStatusCallback = (status) {
navigator.didStopUserGesture();
controller.removeStatusListener(animationStatusCallback);
};
controller.addStatusListener(animationStatusCallback);
} else {
navigator.didStopUserGesture();
}
}
/// The drag gesture has changed by [fractionalDelta]. The total range of the
/// drag should be 0.0 to 1.0.
void dragUpdate(double delta) {
controller.value -= delta;
}
}
class CupertinoBackGestureDetector<T> extends StatefulWidget {
final Widget child;
final double gestureWidth;
final ValueGetter<bool> enabledCallback;
final ValueGetter<CupertinoBackGestureController<T>> onStartPopGesture;
const CupertinoBackGestureDetector({
Key? key,
required this.enabledCallback,
required this.onStartPopGesture,
required this.child,
required this.gestureWidth,
}) : super(key: key);
@override
CupertinoBackGestureDetectorState<T> createState() =>
CupertinoBackGestureDetectorState<T>();
}
class CupertinoBackGestureDetectorState<T>
extends State<CupertinoBackGestureDetector<T>> {
CupertinoBackGestureController<T>? _backGestureController;
late HorizontalDragGestureRecognizer _recognizer;
@override
Widget build(BuildContext context) {
assert(debugCheckHasDirectionality(context));
// For devices with notches, the drag area needs to be larger on the side
// that has the notch.
var dragAreaWidth = Directionality.of(context) == TextDirection.ltr
? MediaQuery.of(context).padding.left
: MediaQuery.of(context).padding.right;
dragAreaWidth = max(dragAreaWidth, widget.gestureWidth);
return Stack(
fit: StackFit.passthrough,
children: <Widget>[
widget.child,
PositionedDirectional(
start: 0.0,
width: dragAreaWidth,
top: 0.0,
bottom: 0.0,
child: Listener(
onPointerDown: _handlePointerDown,
behavior: HitTestBehavior.translucent,
),
),
],
);
}
@override
void dispose() {
_recognizer.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_recognizer = HorizontalDragGestureRecognizer(debugOwner: this)
..onStart = _handleDragStart
..onUpdate = _handleDragUpdate
..onEnd = _handleDragEnd
..onCancel = _handleDragCancel;
}
double _convertToLogical(double value) {
switch (Directionality.of(context)) {
case TextDirection.rtl:
return -value;
case TextDirection.ltr:
return value;
}
}
void _handleDragCancel() {
assert(mounted);
// This can be called even if start is not called, paired with
// the "down" event
// that we don't consider here.
_backGestureController?.dragEnd(0.0);
_backGestureController = null;
}
void _handleDragEnd(DragEndDetails details) {
assert(mounted);
assert(_backGestureController != null);
_backGestureController!.dragEnd(_convertToLogical(
details.velocity.pixelsPerSecond.dx / context.size!.width));
_backGestureController = null;
}
void _handleDragStart(DragStartDetails details) {
assert(mounted);
assert(_backGestureController == null);
_backGestureController = widget.onStartPopGesture();
}
void _handleDragUpdate(DragUpdateDetails details) {
assert(mounted);
assert(_backGestureController != null);
_backGestureController!.dragUpdate(
_convertToLogical(details.primaryDelta! / context.size!.width));
}
void _handlePointerDown(PointerDownEvent event) {
if (widget.enabledCallback()) _recognizer.addPointer(event);
}
}
mixin GetPageRouteTransitionMixin<T> on PageRoute<T> {
ValueNotifier<String?>? _previousTitle;
@override
Color? get barrierColor => null;
@override
String? get barrierLabel => null;
double Function(BuildContext context)? get gestureWidth;
/// Whether a pop gesture can be started by the user.
///
/// Returns true if the user can edge-swipe to a previous route.
///
/// Returns false once [isPopGestureInProgress] is true, but
/// [isPopGestureInProgress] can only become true if [popGestureEnabled] was
/// true first.
///
/// This should only be used between frames, not during build.
bool get popGestureEnabled => _isPopGestureEnabled(this);
/// True if an iOS-style back swipe pop gesture is currently
/// underway for this route.
///
/// See also:
///
/// * [isPopGestureInProgress], which returns true if a Cupertino pop gesture
/// is currently underway for specific route.
/// * [popGestureEnabled], which returns true if a user-triggered pop gesture
/// would be allowed.
bool get popGestureInProgress => isPopGestureInProgress(this);
/// The title string of the previous [CupertinoPageRoute].
///
/// The [ValueListenable]'s value is readable after the route is installed
/// onto a [Navigator]. The [ValueListenable] will also notify its listeners
/// if the value changes (such as by replacing the previous route).
///
/// The [ValueListenable] itself will be null before the route is installed.
/// Its content value will be null if the previous route has no title or
/// is not a [CupertinoPageRoute].
///
/// See also:
///
/// * [ValueListenableBuilder], which can be used to listen and rebuild
/// widgets based on a ValueListenable.
ValueListenable<String?> get previousTitle {
assert(
_previousTitle != null,
'''
Cannot read the previousTitle for a route that has not yet been installed''',
);
return _previousTitle!;
}
bool get showCupertinoParallax;
/// {@template flutter.cupertino.CupertinoRouteTransitionMixin.title}
/// A title string for this route.
///
/// Used to auto-populate [CupertinoNavigationBar] and
/// [CupertinoSliverNavigationBar]'s `middle`/`largeTitle` widgets when
/// one is not manually supplied.
/// {@endtemplate}
String? get title;
@override
// A relatively rigorous eyeball estimation.
Duration get transitionDuration => const Duration(milliseconds: 400);
/// Builds the primary contents of the route.
@protected
Widget buildContent(BuildContext context);
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
final child = buildContent(context);
final Widget result = Semantics(
scopesRoute: true,
explicitChildNodes: true,
child: child,
);
return result;
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return buildPageTransitions<T>(
this, context, animation, secondaryAnimation, child);
}
@override
bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
// Don't perform outgoing animation if the next route is a
// fullscreen dialog.
return (nextRoute is GetPageRouteTransitionMixin &&
!nextRoute.fullscreenDialog &&
nextRoute.showCupertinoParallax) ||
(nextRoute is CupertinoRouteTransitionMixin &&
!nextRoute.fullscreenDialog);
}
@override
void didChangePrevious(Route<dynamic>? previousRoute) {
final previousTitleString = previousRoute is CupertinoRouteTransitionMixin
? previousRoute.title
: null;
if (_previousTitle == null) {
_previousTitle = ValueNotifier<String?>(previousTitleString);
} else {
_previousTitle!.value = previousTitleString;
}
super.didChangePrevious(previousRoute);
}
/// Returns a [CupertinoFullscreenDialogTransition] if [route] is a full
/// screen dialog, otherwise a [CupertinoPageTransition] is returned.
///
/// Used by [CupertinoPageRoute.buildTransitions].
///
/// This method can be applied to any [PageRoute], not just
/// [CupertinoPageRoute]. It's typically used to provide a Cupertino style
/// horizontal transition for material widgets when the target platform
/// is [TargetPlatform.iOS].
///
/// See also:
///
/// * [CupertinoPageTransitionsBuilder], which uses this method to define a
/// [PageTransitionsBuilder] for the [PageTransitionsTheme].
static Widget buildPageTransitions<T>(
PageRoute<T> rawRoute,
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
// Check if the route has an animation that's currently participating
// in a back swipe gesture.
//
// In the middle of a back gesture drag, let the transition be linear to
// match finger motions.
final route = rawRoute as GetPageRoute<T>;
final linearTransition = isPopGestureInProgress(route);
final finalCurve = route.curve ?? Get.defaultTransitionCurve;
final hasCurve = route.curve != null;
if (route.fullscreenDialog && route.transition == null) {
return CupertinoFullscreenDialogTransition(
primaryRouteAnimation: hasCurve
? CurvedAnimation(parent: animation, curve: finalCurve)
: animation,
secondaryRouteAnimation: secondaryAnimation,
child: child,
linearTransition: linearTransition,
);
} else {
if (route.customTransition != null) {
return route.customTransition!.buildTransition(
context,
finalCurve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth:
route.gestureWidth?.call(context) ?? _kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child,
);
}
/// Apply the curve by default...
final iosAnimation = animation;
animation = CurvedAnimation(parent: animation, curve: finalCurve);
switch (route.transition ?? Get.defaultTransition) {
case Transition.leftToRight:
return SlideLeftTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.downToUp:
return SlideDownTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.upToDown:
return SlideTopTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.noTransition:
return route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth:
route.gestureWidth?.call(context) ?? _kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child;
case Transition.rightToLeft:
return SlideRightTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.zoom:
return ZoomInTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.fadeIn:
return FadeInTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.rightToLeftWithFade:
return RightToLeftFadeTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.leftToRightWithFade:
return LeftToRightFadeTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.cupertino:
return CupertinoPageTransition(
primaryRouteAnimation: animation,
secondaryRouteAnimation: secondaryAnimation,
linearTransition: linearTransition,
child: CupertinoBackGestureDetector<T>(
gestureWidth:
route.gestureWidth?.call(context) ?? _kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child,
),
);
case Transition.size:
return SizeTransitions().buildTransitions(
context,
route.curve!,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.fade:
return FadeUpwardsPageTransitionsBuilder().buildTransitions(
route,
context,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.topLevel:
return ZoomPageTransitionsBuilder().buildTransitions(
route,
context,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.native:
return PageTransitionsTheme().buildTransitions(
route,
context,
iosAnimation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
case Transition.circularReveal:
return CircularRevealTransition().buildTransitions(
context,
route.curve,
route.alignment,
animation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
default:
if (Get.customTransition != null) {
return Get.customTransition!.buildTransition(context, route.curve,
route.alignment, animation, secondaryAnimation, child);
}
return PageTransitionsTheme().buildTransitions(
route,
context,
iosAnimation,
secondaryAnimation,
route.popGesture ?? Get.defaultPopGesture
? CupertinoBackGestureDetector<T>(
gestureWidth: route.gestureWidth?.call(context) ??
_kBackGestureWidth,
enabledCallback: () => _isPopGestureEnabled<T>(route),
onStartPopGesture: () => _startPopGesture<T>(route),
child: child)
: child);
}
}
}
// Called by CupertinoBackGestureDetector when a pop ("back") drag start
// gesture is detected. The returned controller handles all of the subsequent
// drag events.
/// True if an iOS-style back swipe pop gesture is currently
/// underway for [route].
///
/// This just check the route's [NavigatorState.userGestureInProgress].
///
/// See also:
///
/// * [popGestureEnabled], which returns true if a user-triggered pop gesture
/// would be allowed.
static bool isPopGestureInProgress(PageRoute<dynamic> route) {
return route.navigator!.userGestureInProgress;
}
static bool _isPopGestureEnabled<T>(PageRoute<T> route) {
// If there's nothing to go back to, then obviously we don't support
// the back gesture.
if (route.isFirst) return false;
// If the route wouldn't actually pop if we popped it, then the gesture
// would be really confusing (or would skip internal routes),
//so disallow it.
if (route.willHandlePopInternally) return false;
// If attempts to dismiss this route might be vetoed such as in a page
// with forms, then do not allow the user to dismiss the route with a swipe.
if (route.hasScopedWillPopCallback) return false;
// Fullscreen dialogs aren't dismissible by back swipe.
if (route.fullscreenDialog) return false;
// If we're in an animation already, we cannot be manually swiped.
if (route.animation!.status != AnimationStatus.completed) return false;
// If we're being popped into, we also cannot be swiped until the pop above
// it completes. This translates to our secondary animation being
// dismissed.
if (route.secondaryAnimation!.status != AnimationStatus.dismissed) {
return false;
}
// If we're in a gesture already, we cannot start another.
if (isPopGestureInProgress(route)) return false;
// Looks like a back gesture would be welcome!
return true;
}
static CupertinoBackGestureController<T> _startPopGesture<T>(
PageRoute<T> route) {
assert(_isPopGestureEnabled(route));
return CupertinoBackGestureController<T>(
navigator: route.navigator!,
controller: route.controller!, // protected access
);
}
}
@@ -0,0 +1,241 @@
import 'package:flutter/widgets.dart';
import '../../../../get_core/get_core.dart';
import '../../../../instance_manager.dart';
import '../../../get_navigation.dart';
import '../../dialog/dialog_route.dart';
import '../../router_report.dart';
/// Extracts the name of a route based on it's instance type
/// or null if not possible.
String? _extractRouteName(Route? route) {
if (route?.settings.name != null) {
return route!.settings.name;
}
if (route is GetPageRoute) {
return route.routeName;
}
if (route is GetDialogRoute) {
return 'DIALOG ${route.hashCode}';
}
if (route is GetModalBottomSheetRoute) {
return 'BOTTOMSHEET ${route.hashCode}';
}
return null;
}
class GetObserver extends NavigatorObserver {
final Function(Routing?)? routing;
final Routing? _routeSend;
GetObserver([this.routing, this._routeSend]);
@override
void didPop(Route route, Route? previousRoute) {
super.didPop(route, previousRoute);
final currentRoute = _RouteData.ofRoute(route);
final newRoute = _RouteData.ofRoute(previousRoute);
// if (currentRoute.isSnackbar) {
// // Get.log("CLOSE SNACKBAR ${currentRoute.name}");
// Get.log("CLOSE SNACKBAR");
// } else
if (currentRoute.isBottomSheet || currentRoute.isDialog) {
Get.log("CLOSE ${currentRoute.name}");
} else if (currentRoute.isGetPageRoute) {
Get.log("CLOSE TO ROUTE ${currentRoute.name}");
}
if (previousRoute != null) {
RouterReportManager.reportCurrentRoute(previousRoute);
}
// Here we use a 'inverse didPush set', meaning that we use
// previous route instead of 'route' because this is
// a 'inverse push'
_routeSend?.update((value) {
// Only PageRoute is allowed to change current value
if (previousRoute is PageRoute) {
value.current = _extractRouteName(previousRoute) ?? '';
value.previous = newRoute.name ?? '';
} else if (value.previous.isNotEmpty) {
value.current = value.previous;
}
value.args = previousRoute?.settings.arguments;
value.route = previousRoute;
value.isBack = true;
value.removed = '';
// value.isSnackbar = newRoute.isSnackbar;
value.isBottomSheet = newRoute.isBottomSheet;
value.isDialog = newRoute.isDialog;
});
// print('currentRoute.isDialog ${currentRoute.isDialog}');
routing?.call(_routeSend);
}
@override
void didPush(Route route, Route? previousRoute) {
super.didPush(route, previousRoute);
final newRoute = _RouteData.ofRoute(route);
// if (newRoute.isSnackbar) {
// // Get.log("OPEN SNACKBAR ${newRoute.name}");
// Get.log("OPEN SNACKBAR");
// } else
if (newRoute.isBottomSheet || newRoute.isDialog) {
Get.log("OPEN ${newRoute.name}");
} else if (newRoute.isGetPageRoute) {
Get.log("GOING TO ROUTE ${newRoute.name}");
}
RouterReportManager.reportCurrentRoute(route);
_routeSend?.update((value) {
// Only PageRoute is allowed to change current value
if (route is PageRoute) {
value.current = newRoute.name ?? '';
}
final previousRouteName = _extractRouteName(previousRoute);
if (previousRouteName != null) {
value.previous = previousRouteName;
}
value.args = route.settings.arguments;
value.route = route;
value.isBack = false;
value.removed = '';
value.isBottomSheet =
newRoute.isBottomSheet ? true : value.isBottomSheet ?? false;
value.isDialog = newRoute.isDialog ? true : value.isDialog ?? false;
});
if (routing != null) {
routing!(_routeSend);
}
}
@override
void didRemove(Route route, Route? previousRoute) {
super.didRemove(route, previousRoute);
final routeName = _extractRouteName(route);
final currentRoute = _RouteData.ofRoute(route);
Get.log("REMOVING ROUTE $routeName");
_routeSend?.update((value) {
value.route = previousRoute;
value.isBack = false;
value.removed = routeName ?? '';
value.previous = routeName ?? '';
// value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar;
value.isBottomSheet =
currentRoute.isBottomSheet ? false : value.isBottomSheet;
value.isDialog = currentRoute.isDialog ? false : value.isDialog;
});
if (route is GetPageRoute) {
RouterReportManager.reportRouteWillDispose(route);
}
routing?.call(_routeSend);
}
@override
void didReplace({Route? newRoute, Route? oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
final newName = _extractRouteName(newRoute);
final oldName = _extractRouteName(oldRoute);
final currentRoute = _RouteData.ofRoute(oldRoute);
Get.log("REPLACE ROUTE $oldName");
Get.log("NEW ROUTE $newName");
if (newRoute != null) {
RouterReportManager.reportCurrentRoute(newRoute);
}
_routeSend?.update((value) {
// Only PageRoute is allowed to change current value
if (newRoute is PageRoute) {
value.current = newName ?? '';
}
value.args = newRoute?.settings.arguments;
value.route = newRoute;
value.isBack = false;
value.removed = '';
value.previous = '$oldName';
// value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar;
value.isBottomSheet =
currentRoute.isBottomSheet ? false : value.isBottomSheet;
value.isDialog = currentRoute.isDialog ? false : value.isDialog;
});
if (oldRoute is GetPageRoute) {
RouterReportManager.reportRouteWillDispose(oldRoute);
}
routing?.call(_routeSend);
}
}
class Routing {
String current;
String previous;
dynamic args;
String removed;
Route<dynamic>? route;
bool? isBack;
// bool? isSnackbar;
bool? isBottomSheet;
bool? isDialog;
Routing({
this.current = '',
this.previous = '',
this.args,
this.removed = '',
this.route,
this.isBack,
// this.isSnackbar,
this.isBottomSheet,
this.isDialog,
});
void update(void fn(Routing value)) {
fn(this);
}
}
/// This is basically a util for rules about 'what a route is'
class _RouteData {
final bool isGetPageRoute;
//final bool isSnackbar;
final bool isBottomSheet;
final bool isDialog;
final String? name;
_RouteData({
required this.name,
required this.isGetPageRoute,
// required this.isSnackbar,
required this.isBottomSheet,
required this.isDialog,
});
factory _RouteData.ofRoute(Route? route) {
return _RouteData(
name: _extractRouteName(route),
isGetPageRoute: route is GetPageRoute,
// isSnackbar: route is SnackRoute,
isDialog: route is GetDialogRoute,
isBottomSheet: route is GetModalBottomSheetRoute,
);
}
}
@@ -0,0 +1,291 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import '../../../get.dart';
abstract class _RouteMiddleware {
/// The Order of the Middlewares to run.
///
/// {@tool snippet}
/// This Middewares will be called in this order.
/// ```dart
/// final middlewares = [
/// GetMiddleware(priority: 2),
/// GetMiddleware(priority: 5),
/// GetMiddleware(priority: 4),
/// GetMiddleware(priority: -8),
/// ];
/// ```
/// -8 => 2 => 4 => 5
/// {@end-tool}
int? priority;
/// This function will be called when the page of
/// the called route is being searched for.
/// It take RouteSettings as a result an redirect to the new settings or
/// give it null and there will be no redirecting.
/// {@tool snippet}
/// ```dart
/// GetPage redirect(String route) {
/// final authService = Get.find<AuthService>();
/// return authService.authed.value ? null : RouteSettings(name: '/login');
/// }
/// ```
/// {@end-tool}
RouteSettings? redirect(String route);
/// Similar to [redirect],
/// This function will be called when the router delegate changes the
/// current route.
///
/// The default implmentation is to navigate to
/// the input route, with no redirection.
///
/// if this returns null, the navigation is stopped,
/// and no new routes are pushed.
/// {@tool snippet}
/// ```dart
/// GetNavConfig? redirect(GetNavConfig route) {
/// final authService = Get.find<AuthService>();
/// return authService.authed.value ? null : RouteSettings(name: '/login');
/// }
/// ```
/// {@end-tool}
Future<GetNavConfig?> redirectDelegate(GetNavConfig route);
/// This function will be called when this Page is called
/// you can use it to change something about the page or give it new page
/// {@tool snippet}
/// ```dart
/// GetPage onPageCalled(GetPage page) {
/// final authService = Get.find<AuthService>();
/// return page.copyWith(title: 'Welcome ${authService.UserName}');
/// }
/// ```
/// {@end-tool}
GetPage? onPageCalled(GetPage page);
/// This function will be called right before the [Bindings] are initialize.
/// Here you can change [Bindings] for this page
/// {@tool snippet}
/// ```dart
/// List<Bindings> onBindingsStart(List<Bindings> bindings) {
/// final authService = Get.find<AuthService>();
/// if (authService.isAdmin) {
/// bindings.add(AdminBinding());
/// }
/// return bindings;
/// }
/// ```
/// {@end-tool}
List<Bindings>? onBindingsStart(List<Bindings> bindings);
/// This function will be called right after the [Bindings] are initialize.
GetPageBuilder? onPageBuildStart(GetPageBuilder page);
/// This function will be called right after the
/// GetPage.page function is called and will give you the result
/// of the function. and take the widget that will be showed.
Widget onPageBuilt(Widget page);
void onPageDispose();
}
/// The Page Middlewares.
/// The Functions will be called in this order
/// (( [redirect] -> [onPageCalled] -> [onBindingsStart] ->
/// [onPageBuildStart] -> [onPageBuilt] -> [onPageDispose] ))
class GetMiddleware implements _RouteMiddleware {
@override
int? priority = 0;
GetMiddleware({this.priority});
@override
RouteSettings? redirect(String? route) => null;
@override
GetPage? onPageCalled(GetPage? page) => page;
@override
List<Bindings>? onBindingsStart(List<Bindings>? bindings) => bindings;
@override
GetPageBuilder? onPageBuildStart(GetPageBuilder? page) => page;
@override
Widget onPageBuilt(Widget page) => page;
@override
void onPageDispose() {}
@override
Future<GetNavConfig?> redirectDelegate(GetNavConfig route) =>
SynchronousFuture(route);
}
class MiddlewareRunner {
MiddlewareRunner(this._middlewares);
final List<GetMiddleware>? _middlewares;
List<GetMiddleware> _getMiddlewares() {
final _m = _middlewares ?? <GetMiddleware>[];
return _m
..sort(
(a, b) => (a.priority ?? 0).compareTo(b.priority ?? 0),
);
}
GetPage? runOnPageCalled(GetPage? page) {
_getMiddlewares().forEach((element) {
page = element.onPageCalled(page);
});
return page;
}
RouteSettings? runRedirect(String? route) {
RouteSettings? to;
for (final element in _getMiddlewares()) {
to = element.redirect(route);
if (to != null) {
break;
}
}
Get.log('Redirect to $to');
return to;
}
List<Bindings>? runOnBindingsStart(List<Bindings>? bindings) {
_getMiddlewares().forEach((element) {
bindings = element.onBindingsStart(bindings);
});
return bindings;
}
GetPageBuilder? runOnPageBuildStart(GetPageBuilder? page) {
_getMiddlewares().forEach((element) {
page = element.onPageBuildStart(page);
});
return page;
}
Widget runOnPageBuilt(Widget page) {
_getMiddlewares().forEach((element) {
page = element.onPageBuilt(page);
});
return page;
}
void runOnPageDispose() =>
_getMiddlewares().forEach((element) => element.onPageDispose());
}
class PageRedirect {
GetPage? route;
GetPage? unknownRoute;
RouteSettings? settings;
bool isUnknown;
PageRedirect({
this.route,
this.unknownRoute,
this.isUnknown = false,
this.settings,
});
// redirect all pages that needes redirecting
GetPageRoute<T> page<T>() {
while (needRecheck()) {}
final _r = (isUnknown ? unknownRoute : route)!;
return GetPageRoute<T>(
page: _r.page,
parameter: _r.parameters,
settings: isUnknown
? RouteSettings(
name: _r.name,
arguments: settings!.arguments,
)
: settings,
curve: _r.curve,
opaque: _r.opaque,
showCupertinoParallax: _r.showCupertinoParallax,
gestureWidth: _r.gestureWidth,
customTransition: _r.customTransition,
binding: _r.binding,
bindings: _r.bindings,
transitionDuration:
_r.transitionDuration ?? Get.defaultTransitionDuration,
transition: _r.transition,
popGesture: _r.popGesture,
fullscreenDialog: _r.fullscreenDialog,
middlewares: _r.middlewares,
);
}
// redirect all pages that needes redirecting
GetPageRoute<T> getPageToRoute<T>(GetPage rou, GetPage? unk) {
while (needRecheck()) {}
final _r = (isUnknown ? unk : rou)!;
return GetPageRoute<T>(
page: _r.page,
parameter: _r.parameters,
alignment: _r.alignment,
title: _r.title,
maintainState: _r.maintainState,
routeName: _r.name,
settings: _r,
curve: _r.curve,
showCupertinoParallax: _r.showCupertinoParallax,
gestureWidth: _r.gestureWidth,
opaque: _r.opaque,
customTransition: _r.customTransition,
binding: _r.binding,
bindings: _r.bindings,
transitionDuration:
_r.transitionDuration ?? Get.defaultTransitionDuration,
transition: _r.transition,
popGesture: _r.popGesture,
fullscreenDialog: _r.fullscreenDialog,
middlewares: _r.middlewares,
);
}
/// check if redirect is needed
bool needRecheck() {
if (settings == null && route != null) {
settings = route;
}
final match = Get.routeTree.matchRoute(settings!.name!);
Get.parameters = match.parameters;
// No Match found
if (match.route == null) {
isUnknown = true;
return false;
}
final runner = MiddlewareRunner(match.route!.middlewares);
route = runner.runOnPageCalled(match.route);
addPageParameter(route!);
// No middlewares found return match.
if (match.route!.middlewares == null || match.route!.middlewares!.isEmpty) {
return false;
}
final newSettings = runner.runRedirect(settings!.name);
if (newSettings == null) {
return false;
}
settings = newSettings;
return true;
}
void addPageParameter(GetPage route) {
if (route.parameters == null) return;
final parameters = Get.parameters;
parameters.addEntries(route.parameters!.entries);
Get.parameters = parameters;
}
}
@@ -0,0 +1,22 @@
import 'package:flutter/widgets.dart';
enum Transition {
fade,
fadeIn,
rightToLeft,
leftToRight,
upToDown,
downToUp,
rightToLeftWithFade,
leftToRightWithFade,
zoom,
topLevel,
noTransition,
cupertino,
cupertinoDialog,
size,
circularReveal,
native,
}
typedef GetPageBuilder = Widget Function();