Jonny Borges
Committed by GitHub

Compatibility with dev/master branch

@@ -153,8 +153,6 @@ @@ -153,8 +153,6 @@
153 ## [1.11.1] 153 ## [1.11.1]
154 -Improve swipe to back on iOS devices 154 -Improve swipe to back on iOS devices
155 155
156 -  
157 -  
158 -  
159 - 156 + ## [1.12.0-dev]
  157 + -Compatibility with Dev branch
160 158
@@ -11,13 +11,15 @@ increasing your productivity, and eliminating all the bugs present in Flutter's @@ -11,13 +11,15 @@ increasing your productivity, and eliminating all the bugs present in Flutter's
11 11
12 ##### If you use MODULAR, add on your MaterialApp this: navigatorKey: Get.addKey(Modular.navigatorKey) 12 ##### If you use MODULAR, add on your MaterialApp this: navigatorKey: Get.addKey(Modular.navigatorKey)
13 13
  14 +##### If you use master/dev branch of Flutter, use the version 1.12.0-dev.
  15 +
14 ## How to use? 16 ## How to use?
15 17
16 Add this to your package's pubspec.yaml file: 18 Add this to your package's pubspec.yaml file:
17 19
18 ``` 20 ```
19 dependencies: 21 dependencies:
20 - get: ^1.11.1 22 + get: ^1.11.1 // get: ^1.12.0-dev on dev/master
21 ``` 23 ```
22 24
23 And import it: 25 And import it:
@@ -49,7 +49,7 @@ class Get { @@ -49,7 +49,7 @@ class Get {
49 /// It replaces Navigator.push, but needs no context, and it doesn't have the Navigator.push 49 /// It replaces Navigator.push, but needs no context, and it doesn't have the Navigator.push
50 /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior 50 /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
51 /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. 51 /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter.
52 - static to(Widget page, 52 + static Future<T> to<T>(Widget page,
53 {bool rebuildRoutes, 53 {bool rebuildRoutes,
54 Transition transition, 54 Transition transition,
55 Duration duration = const Duration(milliseconds: 400)}) { 55 Duration duration = const Duration(milliseconds: 400)}) {
@@ -72,47 +72,47 @@ class Get { @@ -72,47 +72,47 @@ class Get {
72 /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed 72 /// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed
73 /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior 73 /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
74 /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. 74 /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter.
75 - static toNamed(String page, {arguments}) { 75 + static Future<T> toNamed<T>(String page, {arguments}) {
76 // if (key.currentState.mounted) // add this if appear problems on future with route navigate 76 // if (key.currentState.mounted) // add this if appear problems on future with route navigate
77 // when widget don't mounted 77 // when widget don't mounted
78 return key.currentState.pushNamed(page, arguments: arguments); 78 return key.currentState.pushNamed(page, arguments: arguments);
79 } 79 }
80 80
81 /// It replaces Navigator.pushReplacementNamed, but needs no context. 81 /// It replaces Navigator.pushReplacementNamed, but needs no context.
82 - static offNamed(String page, {arguments}) { 82 + static Future<T> offNamed<T>(String page, {arguments}) {
83 // if (key.currentState.mounted) // add this if appear problems on future with route navigate 83 // if (key.currentState.mounted) // add this if appear problems on future with route navigate
84 // when widget don't mounted 84 // when widget don't mounted
85 return key.currentState.pushReplacementNamed(page, arguments: arguments); 85 return key.currentState.pushReplacementNamed(page, arguments: arguments);
86 } 86 }
87 87
88 /// It replaces Navigator.popUntil, but needs no context. 88 /// It replaces Navigator.popUntil, but needs no context.
89 - static until(String page, predicate) { 89 + static void until(String page, predicate) {
90 // if (key.currentState.mounted) // add this if appear problems on future with route navigate 90 // if (key.currentState.mounted) // add this if appear problems on future with route navigate
91 // when widget don't mounted 91 // when widget don't mounted
92 return key.currentState.popUntil(predicate); 92 return key.currentState.popUntil(predicate);
93 } 93 }
94 94
95 /// It replaces Navigator.pushAndRemoveUntil, but needs no context. 95 /// It replaces Navigator.pushAndRemoveUntil, but needs no context.
96 - static offUntil(page, predicate) { 96 + static Future<T> offUntil<T>(page, predicate) {
97 // if (key.currentState.mounted) // add this if appear problems on future with route navigate 97 // if (key.currentState.mounted) // add this if appear problems on future with route navigate
98 // when widget don't mounted 98 // when widget don't mounted
99 return key.currentState.pushAndRemoveUntil(page, predicate); 99 return key.currentState.pushAndRemoveUntil(page, predicate);
100 } 100 }
101 101
102 /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context. 102 /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context.
103 - static offNamedUntil(page, predicate) { 103 + static Future<T> offNamedUntil<T>(page, predicate) {
104 // if (key.currentState.mounted) // add this if appear problems on future with route navigate 104 // if (key.currentState.mounted) // add this if appear problems on future with route navigate
105 // when widget don't mounted 105 // when widget don't mounted
106 return key.currentState.pushNamedAndRemoveUntil(page, predicate); 106 return key.currentState.pushNamedAndRemoveUntil(page, predicate);
107 } 107 }
108 108
109 /// It replaces Navigator.removeRoute, but needs no context. 109 /// It replaces Navigator.removeRoute, but needs no context.
110 - static removeRoute(route) { 110 + static void removeRoute(route) {
111 return key.currentState.removeRoute(route); 111 return key.currentState.removeRoute(route);
112 } 112 }
113 113
114 /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context. 114 /// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context.
115 - static offAllNamed( 115 + static Future<T> offAllNamed<T>(
116 String newRouteName, { 116 String newRouteName, {
117 RoutePredicate predicate, 117 RoutePredicate predicate,
118 arguments, 118 arguments,
@@ -124,12 +124,12 @@ class Get { @@ -124,12 +124,12 @@ class Get {
124 } 124 }
125 125
126 /// It replaces Navigator.pop, but needs no context. 126 /// It replaces Navigator.pop, but needs no context.
127 - static back({dynamic result}) { 127 + static void back({dynamic result}) {
128 return key.currentState.pop(result); 128 return key.currentState.pop(result);
129 } 129 }
130 130
131 /// It will close as many screens as you define. Times must be> 0; 131 /// It will close as many screens as you define. Times must be> 0;
132 - static close(int times) { 132 + static void close(int times) {
133 if ((times == null) || (times < 1)) { 133 if ((times == null) || (times < 1)) {
134 times = 1; 134 times = 1;
135 } 135 }
@@ -143,25 +143,33 @@ class Get { @@ -143,25 +143,33 @@ class Get {
143 /// It replaces Navigator.pushReplacement, but needs no context, and it doesn't have the Navigator.pushReplacement 143 /// It replaces Navigator.pushReplacement, but needs no context, and it doesn't have the Navigator.pushReplacement
144 /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior 144 /// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
145 /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter. 145 /// of rebuilding every app after a route, use rebuildRoutes = true as the parameter.
146 - static off(Widget page, 146 + static Future<T> off<T>(Widget page,
147 {bool rebuildRoutes = false, 147 {bool rebuildRoutes = false,
148 - Transition transition = Transition.rightToLeft, 148 + Transition transition,
149 Duration duration = const Duration(milliseconds: 400)}) { 149 Duration duration = const Duration(milliseconds: 400)}) {
150 return key.currentState.pushReplacement(GetRoute( 150 return key.currentState.pushReplacement(GetRoute(
151 opaque: rebuildRoutes, 151 opaque: rebuildRoutes,
152 page: page, 152 page: page,
153 - transition: transition, 153 + transition: transition ?? Platform.isIOS
  154 + ? Transition.cupertino
  155 + : Transition.fade,
154 duration: duration)); 156 duration: duration));
155 } 157 }
156 158
157 /// It replaces Navigator.pushAndRemoveUntil, but needs no context 159 /// It replaces Navigator.pushAndRemoveUntil, but needs no context
158 - static offAll(Widget page, 160 + static Future<T> offAll<T>(Widget page,
159 {RoutePredicate predicate, 161 {RoutePredicate predicate,
160 bool rebuildRoutes = false, 162 bool rebuildRoutes = false,
161 - Transition transition = Transition.rightToLeft}) { 163 + Transition transition}) {
162 var route = (Route<dynamic> rota) => false; 164 var route = (Route<dynamic> rota) => false;
163 return key.currentState.pushAndRemoveUntil( 165 return key.currentState.pushAndRemoveUntil(
164 - GetRoute(opaque: rebuildRoutes, page: page, transition: transition), 166 + GetRoute(
  167 + opaque: rebuildRoutes,
  168 + page: page,
  169 + transition: transition ?? Platform.isIOS
  170 + ? Transition.cupertino
  171 + : Transition.fade,
  172 + ),
165 predicate ?? route); 173 predicate ?? route);
166 } 174 }
167 175
@@ -258,7 +266,7 @@ class Get { @@ -258,7 +266,7 @@ class Get {
258 return ModalRoute.of(context).settings.arguments; 266 return ModalRoute.of(context).settings.arguments;
259 } 267 }
260 268
261 - static backdrop(Widget child, 269 + static Future backdrop(Widget child,
262 {double radius = 20.0, 270 {double radius = 20.0,
263 double blurRadius: 20.0, 271 double blurRadius: 20.0,
264 int duration = 300, 272 int duration = 300,
@@ -282,7 +290,7 @@ class Get { @@ -282,7 +290,7 @@ class Get {
282 })); 290 }));
283 } 291 }
284 292
285 - static snackbar(title, message, 293 + static void snackbar(title, message,
286 {Color colorText, 294 {Color colorText,
287 Duration duration, 295 Duration duration,
288 SnackPosition snackPosition, 296 SnackPosition snackPosition,
@@ -369,15 +377,23 @@ class Get { @@ -369,15 +377,23 @@ class Get {
369 }); 377 });
370 } 378 }
371 379
372 - static iconColor() {  
373 - return Theme.of(key.currentContext).iconTheme.color; 380 + static BuildContext context() {
  381 + return key.currentContext;
  382 + }
  383 +
  384 + static ThemeData theme() {
  385 + return Theme.of(context());
  386 + }
  387 +
  388 + static Color iconColor() {
  389 + return Theme.of(context()).iconTheme.color;
374 } 390 }
375 391
376 - static height() {  
377 - return MediaQuery.of(key.currentContext).size.height; 392 + static double height() {
  393 + return MediaQuery.of(context()).size.height;
378 } 394 }
379 395
380 - static width() {  
381 - return MediaQuery.of(key.currentContext).size.width; 396 + static double width() {
  397 + return MediaQuery.of(context()).size.width;
382 } 398 }
383 } 399 }
  1 +import 'dart:math';
  2 +import 'dart:ui' show lerpDouble;
  3 +
  4 +import 'package:flutter/cupertino.dart';
  5 +import 'package:flutter/foundation.dart';
  6 +import 'package:flutter/gestures.dart';
  7 +
  8 +const double _kBackGestureWidth = 20.0;
  9 +const double _kMinFlingVelocity = 1.0;
  10 +const int _kMaxDroppedSwipePageForwardAnimationTime = 800; // Milliseconds.
  11 +
  12 +// The maximum time for a page to get reset to it's original position if the
  13 +// user releases a page mid swipe.
  14 +const int _kMaxPageBackAnimationTime = 300;
  15 +
  16 +class GetCupertino<T> extends PageRoute<T> {
  17 + /// Creates a page route for use in an iOS designed app.
  18 + ///
  19 + /// The [builder], [maintainState], and [fullscreenDialog] arguments must not
  20 + /// be null.
  21 + GetCupertino({
  22 + @required this.builder,
  23 + this.title,
  24 + RouteSettings settings,
  25 + this.maintainState = true,
  26 + bool fullscreenDialog = false,
  27 + }) : assert(builder != null),
  28 + assert(maintainState != null),
  29 + assert(fullscreenDialog != null),
  30 + assert(opaque),
  31 + super(settings: settings, fullscreenDialog: fullscreenDialog);
  32 +
  33 + /// Builds the primary contents of the route.
  34 + final WidgetBuilder builder;
  35 +
  36 + /// A title string for this route.
  37 + ///
  38 + /// Used to auto-populate [CupertinoNavigationBar] and
  39 + /// [CupertinoSliverNavigationBar]'s `middle`/`largeTitle` widgets when
  40 + /// one is not manually supplied.
  41 + final String title;
  42 +
  43 + ValueNotifier<String> _previousTitle;
  44 +
  45 + /// The title string of the previous [GetCupertino].
  46 + ///
  47 + /// The [ValueListenable]'s value is readable after the route is installed
  48 + /// onto a [Navigator]. The [ValueListenable] will also notify its listeners
  49 + /// if the value changes (such as by replacing the previous route).
  50 + ///
  51 + /// The [ValueListenable] itself will be null before the route is installed.
  52 + /// Its content value will be null if the previous route has no title or
  53 + /// is not a [GetCupertino].
  54 + ///
  55 + /// See also:
  56 + ///
  57 + /// * [ValueListenableBuilder], which can be used to listen and rebuild
  58 + /// widgets based on a ValueListenable.
  59 + ValueListenable<String> get previousTitle {
  60 + assert(
  61 + _previousTitle != null,
  62 + 'Cannot read the previousTitle for a route that has not yet been installed',
  63 + );
  64 + return _previousTitle;
  65 + }
  66 +
  67 + @override
  68 + void didChangePrevious(Route<dynamic> previousRoute) {
  69 + final String previousTitleString =
  70 + previousRoute is GetCupertino ? previousRoute.title : null;
  71 + if (_previousTitle == null) {
  72 + _previousTitle = ValueNotifier<String>(previousTitleString);
  73 + } else {
  74 + _previousTitle.value = previousTitleString;
  75 + }
  76 + super.didChangePrevious(previousRoute);
  77 + }
  78 +
  79 + @override
  80 + final bool maintainState;
  81 +
  82 + @override
  83 + // A relatively rigorous eyeball estimation.
  84 + Duration get transitionDuration => const Duration(milliseconds: 400);
  85 +
  86 + @override
  87 + Color get barrierColor => null;
  88 +
  89 + @override
  90 + String get barrierLabel => null;
  91 +
  92 + @override
  93 + bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
  94 + // Don't perform outgoing animation if the next route is a fullscreen dialog.
  95 + return nextRoute is GetCupertino && !nextRoute.fullscreenDialog;
  96 + }
  97 +
  98 + /// True if an iOS-style back swipe pop gesture is currently underway for [route].
  99 + ///
  100 + /// This just check the route's [NavigatorState.userGestureInProgress].
  101 + ///
  102 + /// See also:
  103 + ///
  104 + /// * [popGestureEnabled], which returns true if a user-triggered pop gesture
  105 + /// would be allowed.
  106 + static bool isPopGestureInProgress(PageRoute<dynamic> route) {
  107 + return route.navigator.userGestureInProgress;
  108 + }
  109 +
  110 + /// True if an iOS-style back swipe pop gesture is currently underway for this route.
  111 + ///
  112 + /// See also:
  113 + ///
  114 + /// * [isPopGestureInProgress], which returns true if a Cupertino pop gesture
  115 + /// is currently underway for specific route.
  116 + /// * [popGestureEnabled], which returns true if a user-triggered pop gesture
  117 + /// would be allowed.
  118 + bool get popGestureInProgress => isPopGestureInProgress(this);
  119 +
  120 + /// Whether a pop gesture can be started by the user.
  121 + ///
  122 + /// Returns true if the user can edge-swipe to a previous route.
  123 + ///
  124 + /// Returns false once [isPopGestureInProgress] is true, but
  125 + /// [isPopGestureInProgress] can only become true if [popGestureEnabled] was
  126 + /// true first.
  127 + ///
  128 + /// This should only be used between frames, not during build.
  129 + bool get popGestureEnabled => _isPopGestureEnabled(this);
  130 +
  131 + static bool _isPopGestureEnabled<T>(PageRoute<T> route) {
  132 + // If there's nothing to go back to, then obviously we don't support
  133 + // the back gesture.
  134 + if (route.isFirst) return false;
  135 + // If the route wouldn't actually pop if we popped it, then the gesture
  136 + // would be really confusing (or would skip internal routes), so disallow it.
  137 + if (route.willHandlePopInternally) return false;
  138 + // If attempts to dismiss this route might be vetoed such as in a page
  139 + // with forms, then do not allow the user to dismiss the route with a swipe.
  140 + if (route.hasScopedWillPopCallback) return false;
  141 + // Fullscreen dialogs aren't dismissible by back swipe.
  142 + if (route.fullscreenDialog) return false;
  143 + // If we're in an animation already, we cannot be manually swiped.
  144 + if (route.animation.status != AnimationStatus.completed) return false;
  145 + // If we're being popped into, we also cannot be swiped until the pop above
  146 + // it completes. This translates to our secondary animation being
  147 + // dismissed.
  148 + if (route.secondaryAnimation.status != AnimationStatus.dismissed)
  149 + return false;
  150 + // If we're in a gesture already, we cannot start another.
  151 + if (isPopGestureInProgress(route)) return false;
  152 +
  153 + // Looks like a back gesture would be welcome!
  154 + return true;
  155 + }
  156 +
  157 + @override
  158 + Widget buildPage(BuildContext context, Animation<double> animation,
  159 + Animation<double> secondaryAnimation) {
  160 + final Widget child = builder(context);
  161 + final Widget result = Semantics(
  162 + scopesRoute: true,
  163 + explicitChildNodes: true,
  164 + child: child,
  165 + );
  166 + assert(() {
  167 + if (child == null) {
  168 + throw FlutterError.fromParts(<DiagnosticsNode>[
  169 + ErrorSummary(
  170 + 'The builder for route "${settings.name}" returned null.'),
  171 + ErrorDescription('Route builders must never return null.'),
  172 + ]);
  173 + }
  174 + return true;
  175 + }());
  176 + return result;
  177 + }
  178 +
  179 + // Called by _CupertinoBackGestureDetector when a pop ("back") drag start
  180 + // gesture is detected. The returned controller handles all of the subsequent
  181 + // drag events.
  182 + static _CupertinoBackGestureController<T> _startPopGesture<T>(
  183 + PageRoute<T> route) {
  184 + assert(_isPopGestureEnabled(route));
  185 +
  186 + return _CupertinoBackGestureController<T>(
  187 + navigator: route.navigator,
  188 + controller: route.controller, // protected access
  189 + );
  190 + }
  191 +
  192 + /// Returns a [CupertinoFullscreenDialogTransition] if [route] is a full
  193 + /// screen dialog, otherwise a [CupertinoPageTransition] is returned.
  194 + ///
  195 + /// Used by [GetCupertino.buildTransitions].
  196 + ///
  197 + /// This method can be applied to any [PageRoute], not just
  198 + /// [GetCupertino]. It's typically used to provide a Cupertino style
  199 + /// horizontal transition for material widgets when the target platform
  200 + /// is [TargetPlatform.iOS].
  201 + ///
  202 + /// See also:
  203 + ///
  204 + /// * [CupertinoPageTransitionsBuilder], which uses this method to define a
  205 + /// [PageTransitionsBuilder] for the [PageTransitionsTheme].
  206 + static Widget buildPageTransitions<T>(
  207 + PageRoute<T> route,
  208 + BuildContext context,
  209 + Animation<double> animation,
  210 + Animation<double> secondaryAnimation,
  211 + Widget child,
  212 + ) {
  213 + if (route.fullscreenDialog) {
  214 + return CupertinoFullscreenDialogTransition(
  215 + animation: animation,
  216 + child: child,
  217 + );
  218 + } else {
  219 + return CupertinoPageTransition(
  220 + primaryRouteAnimation: animation,
  221 + secondaryRouteAnimation: secondaryAnimation,
  222 + // Check if the route has an animation that's currently participating
  223 + // in a back swipe gesture.
  224 + //
  225 + // In the middle of a back gesture drag, let the transition be linear to
  226 + // match finger motions.
  227 + linearTransition: isPopGestureInProgress(route),
  228 + child: _CupertinoBackGestureDetector<T>(
  229 + enabledCallback: () => _isPopGestureEnabled<T>(route),
  230 + onStartPopGesture: () => _startPopGesture<T>(route),
  231 + child: child,
  232 + ),
  233 + );
  234 + }
  235 + }
  236 +
  237 + @override
  238 + Widget buildTransitions(BuildContext context, Animation<double> animation,
  239 + Animation<double> secondaryAnimation, Widget child) {
  240 + return buildPageTransitions<T>(
  241 + this, context, animation, secondaryAnimation, child);
  242 + }
  243 +
  244 + @override
  245 + String get debugLabel => '${super.debugLabel}(${settings.name})';
  246 +}
  247 +
  248 +class _CupertinoBackGestureDetector<T> extends StatefulWidget {
  249 + const _CupertinoBackGestureDetector({
  250 + Key key,
  251 + @required this.enabledCallback,
  252 + @required this.onStartPopGesture,
  253 + @required this.child,
  254 + }) : assert(enabledCallback != null),
  255 + assert(onStartPopGesture != null),
  256 + assert(child != null),
  257 + super(key: key);
  258 +
  259 + final Widget child;
  260 +
  261 + final ValueGetter<bool> enabledCallback;
  262 +
  263 + final ValueGetter<_CupertinoBackGestureController<T>> onStartPopGesture;
  264 +
  265 + @override
  266 + _CupertinoBackGestureDetectorState<T> createState() =>
  267 + _CupertinoBackGestureDetectorState<T>();
  268 +}
  269 +
  270 +class _CupertinoBackGestureDetectorState<T>
  271 + extends State<_CupertinoBackGestureDetector<T>> {
  272 + _CupertinoBackGestureController<T> _backGestureController;
  273 +
  274 + HorizontalDragGestureRecognizer _recognizer;
  275 +
  276 + @override
  277 + void initState() {
  278 + super.initState();
  279 + _recognizer = HorizontalDragGestureRecognizer(debugOwner: this)
  280 + ..onStart = _handleDragStart
  281 + ..onUpdate = _handleDragUpdate
  282 + ..onEnd = _handleDragEnd
  283 + ..onCancel = _handleDragCancel;
  284 + }
  285 +
  286 + @override
  287 + void dispose() {
  288 + _recognizer.dispose();
  289 + super.dispose();
  290 + }
  291 +
  292 + void _handleDragStart(DragStartDetails details) {
  293 + assert(mounted);
  294 + assert(_backGestureController == null);
  295 + _backGestureController = widget.onStartPopGesture();
  296 + }
  297 +
  298 + void _handleDragUpdate(DragUpdateDetails details) {
  299 + assert(mounted);
  300 + assert(_backGestureController != null);
  301 + _backGestureController.dragUpdate(
  302 + _convertToLogical(details.primaryDelta / context.size.width));
  303 + }
  304 +
  305 + void _handleDragEnd(DragEndDetails details) {
  306 + assert(mounted);
  307 + assert(_backGestureController != null);
  308 + _backGestureController.dragEnd(_convertToLogical(
  309 + details.velocity.pixelsPerSecond.dx / context.size.width));
  310 + _backGestureController = null;
  311 + }
  312 +
  313 + void _handleDragCancel() {
  314 + assert(mounted);
  315 + // This can be called even if start is not called, paired with the "down" event
  316 + // that we don't consider here.
  317 + _backGestureController?.dragEnd(0.0);
  318 + _backGestureController = null;
  319 + }
  320 +
  321 + void _handlePointerDown(PointerDownEvent event) {
  322 + if (widget.enabledCallback()) _recognizer.addPointer(event);
  323 + }
  324 +
  325 + double _convertToLogical(double value) {
  326 + switch (Directionality.of(context)) {
  327 + case TextDirection.rtl:
  328 + return -value;
  329 + case TextDirection.ltr:
  330 + return value;
  331 + }
  332 + return null;
  333 + }
  334 +
  335 + @override
  336 + Widget build(BuildContext context) {
  337 + assert(debugCheckHasDirectionality(context));
  338 + // For devices with notches, the drag area needs to be larger on the side
  339 + // that has the notch.
  340 + double dragAreaWidth = Directionality.of(context) == TextDirection.ltr
  341 + ? MediaQuery.of(context).padding.left
  342 + : MediaQuery.of(context).padding.right;
  343 + dragAreaWidth = max(dragAreaWidth, _kBackGestureWidth);
  344 + return Stack(
  345 + fit: StackFit.passthrough,
  346 + children: <Widget>[
  347 + widget.child,
  348 + PositionedDirectional(
  349 + start: 0.0,
  350 + width: dragAreaWidth,
  351 + top: 0.0,
  352 + bottom: 0.0,
  353 + child: Listener(
  354 + onPointerDown: _handlePointerDown,
  355 + behavior: HitTestBehavior.translucent,
  356 + ),
  357 + ),
  358 + ],
  359 + );
  360 + }
  361 +}
  362 +
  363 +class _CupertinoBackGestureController<T> {
  364 + /// Creates a controller for an iOS-style back gesture.
  365 + ///
  366 + /// The [navigator] and [controller] arguments must not be null.
  367 + _CupertinoBackGestureController({
  368 + @required this.navigator,
  369 + @required this.controller,
  370 + }) : assert(navigator != null),
  371 + assert(controller != null) {
  372 + navigator.didStartUserGesture();
  373 + }
  374 +
  375 + final AnimationController controller;
  376 + final NavigatorState navigator;
  377 +
  378 + /// The drag gesture has changed by [fractionalDelta]. The total range of the
  379 + /// drag should be 0.0 to 1.0.
  380 + void dragUpdate(double delta) {
  381 + controller.value -= delta;
  382 + }
  383 +
  384 + /// The drag gesture has ended with a horizontal motion of
  385 + /// [fractionalVelocity] as a fraction of screen width per second.
  386 + void dragEnd(double velocity) {
  387 + // Fling in the appropriate direction.
  388 + // AnimationController.fling is guaranteed to
  389 + // take at least one frame.
  390 + //
  391 + // This curve has been determined through rigorously eyeballing native iOS
  392 + // animations.
  393 + const Curve animationCurve = Curves.fastLinearToSlowEaseIn;
  394 + bool animateForward;
  395 +
  396 + // If the user releases the page before mid screen with sufficient velocity,
  397 + // or after mid screen, we should animate the page out. Otherwise, the page
  398 + // should be animated back in.
  399 + if (velocity.abs() >= _kMinFlingVelocity)
  400 + animateForward = velocity <= 0;
  401 + else
  402 + animateForward = controller.value > 0.5;
  403 +
  404 + if (animateForward) {
  405 + // The closer the panel is to dismissing, the shorter the animation is.
  406 + // We want to cap the animation time, but we want to use a linear curve
  407 + // to determine it.
  408 + final int droppedPageForwardAnimationTime = min(
  409 + lerpDouble(
  410 + _kMaxDroppedSwipePageForwardAnimationTime, 0, controller.value)
  411 + .floor(),
  412 + _kMaxPageBackAnimationTime,
  413 + );
  414 + controller.animateTo(1.0,
  415 + duration: Duration(milliseconds: droppedPageForwardAnimationTime),
  416 + curve: animationCurve);
  417 + } else {
  418 + // This route is destined to pop at this point. Reuse navigator's pop.
  419 + navigator.pop();
  420 +
  421 + // The popping may have finished inline if already at the target destination.
  422 + if (controller.isAnimating) {
  423 + // Otherwise, use a custom popping animation duration and curve.
  424 + final int droppedPageBackAnimationTime = lerpDouble(
  425 + 0, _kMaxDroppedSwipePageForwardAnimationTime, controller.value)
  426 + .floor();
  427 + controller.animateBack(0.0,
  428 + duration: Duration(milliseconds: droppedPageBackAnimationTime),
  429 + curve: animationCurve);
  430 + }
  431 + }
  432 +
  433 + if (controller.isAnimating) {
  434 + // Keep the userGestureInProgress in true state so we don't change the
  435 + // curve of the page transition mid-flight since CupertinoPageTransition
  436 + // depends on userGestureInProgress.
  437 + AnimationStatusListener animationStatusCallback;
  438 + animationStatusCallback = (AnimationStatus status) {
  439 + navigator.didStopUserGesture();
  440 + controller.removeStatusListener(animationStatusCallback);
  441 + };
  442 + controller.addStatusListener(animationStatusCallback);
  443 + } else {
  444 + navigator.didStopUserGesture();
  445 + }
  446 + }
  447 +}
@@ -276,7 +276,7 @@ class SnackRoute<T> extends OverlayRoute<T> { @@ -276,7 +276,7 @@ class SnackRoute<T> extends OverlayRoute<T> {
276 } 276 }
277 277
278 @override 278 @override
279 - void install(OverlayEntry insertionPoint) { 279 + void install() {
280 assert(!_transitionCompleter.isCompleted, 280 assert(!_transitionCompleter.isCompleted,
281 'Cannot install a $runtimeType after disposing it.'); 281 'Cannot install a $runtimeType after disposing it.');
282 _controller = createAnimationController(); 282 _controller = createAnimationController();
@@ -286,7 +286,7 @@ class SnackRoute<T> extends OverlayRoute<T> { @@ -286,7 +286,7 @@ class SnackRoute<T> extends OverlayRoute<T> {
286 _filterColorAnimation = createColorFilterAnimation(); 286 _filterColorAnimation = createColorFilterAnimation();
287 _animation = createAnimation(); 287 _animation = createAnimation();
288 assert(_animation != null, '$runtimeType.createAnimation() returned null.'); 288 assert(_animation != null, '$runtimeType.createAnimation() returned null.');
289 - super.install(insertionPoint); 289 + super.install();
290 } 290 }
291 291
292 @override 292 @override
@@ -95,13 +95,6 @@ packages: @@ -95,13 +95,6 @@ packages:
95 url: "https://pub.dartlang.org" 95 url: "https://pub.dartlang.org"
96 source: hosted 96 source: hosted
97 version: "1.6.4" 97 version: "1.6.4"
98 - pedantic:  
99 - dependency: transitive  
100 - description:  
101 - name: pedantic  
102 - url: "https://pub.dartlang.org"  
103 - source: hosted  
104 - version: "1.8.0+1"  
105 petitparser: 98 petitparser:
106 dependency: transitive 99 dependency: transitive
107 description: 100 description:
@@ -162,7 +155,7 @@ packages: @@ -162,7 +155,7 @@ packages:
162 name: test_api 155 name: test_api
163 url: "https://pub.dartlang.org" 156 url: "https://pub.dartlang.org"
164 source: hosted 157 source: hosted
165 - version: "0.2.11" 158 + version: "0.2.15"
166 typed_data: 159 typed_data:
167 dependency: transitive 160 dependency: transitive
168 description: 161 description:
1 name: get 1 name: get
2 description: A consistent navigation library that lets you navigate between screens, open dialogs, and display snackbars easily with no context. 2 description: A consistent navigation library that lets you navigate between screens, open dialogs, and display snackbars easily with no context.
3 -version: 1.11.1 3 +version: 1.12.0-dev
4 homepage: https://github.com/jonataslaw/get 4 homepage: https://github.com/jonataslaw/get
5 5
6 environment: 6 environment: