Jonny Borges

prepare snackbar api to getx 5

@@ -17,4 +17,3 @@ export 'src/routes/observers/route_observer.dart'; @@ -17,4 +17,3 @@ export 'src/routes/observers/route_observer.dart';
17 export 'src/routes/route_middleware.dart'; 17 export 'src/routes/route_middleware.dart';
18 export 'src/routes/transitions_type.dart'; 18 export 'src/routes/transitions_type.dart';
19 export 'src/snackbar/snack.dart'; 19 export 'src/snackbar/snack.dart';
20 -export 'src/snackbar/snack_route.dart';  
@@ -11,243 +11,56 @@ import 'dialog/dialog_route.dart'; @@ -11,243 +11,56 @@ import 'dialog/dialog_route.dart';
11 import 'root/parse_route.dart'; 11 import 'root/parse_route.dart';
12 import 'root/root_controller.dart'; 12 import 'root/root_controller.dart';
13 import 'routes/transitions_type.dart'; 13 import 'routes/transitions_type.dart';
  14 +import 'snackbar/snackbar_controller.dart';
14 15
15 -extension ExtensionSnackbar on GetInterface {  
16 - void rawSnackbar({  
17 - String? title,  
18 - String? message,  
19 - Widget? titleText,  
20 - Widget? messageText,  
21 - Widget? icon,  
22 - bool instantInit = true,  
23 - bool shouldIconPulse = true,  
24 - double? maxWidth,  
25 - EdgeInsets margin = const EdgeInsets.all(0.0),  
26 - EdgeInsets padding = const EdgeInsets.all(16),  
27 - double borderRadius = 0.0,  
28 - Color? borderColor,  
29 - double borderWidth = 1.0,  
30 - Color backgroundColor = const Color(0xFF303030),  
31 - Color? leftBarIndicatorColor,  
32 - List<BoxShadow>? boxShadows,  
33 - Gradient? backgroundGradient,  
34 - Widget? mainButton,  
35 - OnTap? onTap,  
36 - Duration duration = const Duration(seconds: 3),  
37 - bool isDismissible = true,  
38 - SnackDismissDirection dismissDirection = SnackDismissDirection.VERTICAL,  
39 - bool showProgressIndicator = false,  
40 - AnimationController? progressIndicatorController,  
41 - Color? progressIndicatorBackgroundColor,  
42 - Animation<Color>? progressIndicatorValueColor,  
43 - SnackPosition snackPosition = SnackPosition.BOTTOM,  
44 - SnackStyle snackStyle = SnackStyle.FLOATING,  
45 - Curve forwardAnimationCurve = Curves.easeOutCirc,  
46 - Curve reverseAnimationCurve = Curves.easeOutCirc,  
47 - Duration animationDuration = const Duration(seconds: 1),  
48 - SnackbarStatusCallback? snackbarStatus,  
49 - double? barBlur = 0.0,  
50 - double overlayBlur = 0.0,  
51 - Color? overlayColor,  
52 - Form? userInputForm,  
53 - }) async {  
54 - final getBar = GetBar(  
55 - snackbarStatus: snackbarStatus,  
56 - title: title,  
57 - message: message,  
58 - titleText: titleText,  
59 - messageText: messageText,  
60 - snackPosition: snackPosition,  
61 - borderRadius: borderRadius,  
62 - margin: margin,  
63 - duration: duration,  
64 - barBlur: barBlur,  
65 - backgroundColor: backgroundColor,  
66 - icon: icon,  
67 - shouldIconPulse: shouldIconPulse,  
68 - maxWidth: maxWidth,  
69 - padding: padding,  
70 - borderColor: borderColor,  
71 - borderWidth: borderWidth,  
72 - leftBarIndicatorColor: leftBarIndicatorColor,  
73 - boxShadows: boxShadows,  
74 - backgroundGradient: backgroundGradient,  
75 - mainButton: mainButton,  
76 - onTap: onTap,  
77 - isDismissible: isDismissible,  
78 - dismissDirection: dismissDirection,  
79 - showProgressIndicator: showProgressIndicator,  
80 - progressIndicatorController: progressIndicatorController,  
81 - progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,  
82 - progressIndicatorValueColor: progressIndicatorValueColor,  
83 - snackStyle: snackStyle,  
84 - forwardAnimationCurve: forwardAnimationCurve,  
85 - reverseAnimationCurve: reverseAnimationCurve,  
86 - animationDuration: animationDuration,  
87 - overlayBlur: overlayBlur,  
88 - overlayColor: overlayColor,  
89 - userInputForm: userInputForm,  
90 - );  
91 -  
92 - if (instantInit) {  
93 - getBar.show();  
94 - } else {  
95 - SchedulerBinding.instance!.addPostFrameCallback((_) {  
96 - getBar.show();  
97 - });  
98 - }  
99 - }  
100 -  
101 - Future<T?>? showSnackbar<T>(GetBar snackbar) {  
102 - return key.currentState?.push(SnackRoute<T>(snack: snackbar));  
103 - }  
104 -  
105 - void snackbar<T>(  
106 - String title,  
107 - String message, {  
108 - Color? colorText,  
109 - Duration? duration, 16 +/// It replaces the Flutter Navigator, but needs no context.
  17 +/// You can to use navigator.push(YourRoute()) rather
  18 +/// Navigator.push(context, YourRoute());
  19 +NavigatorState? get navigator => GetNavigation(Get).key.currentState;
110 20
111 - /// with instantInit = false you can put snackbar on initState  
112 - bool instantInit = true,  
113 - SnackPosition? snackPosition,  
114 - Widget? titleText,  
115 - Widget? messageText,  
116 - Widget? icon,  
117 - bool? shouldIconPulse,  
118 - double? maxWidth,  
119 - EdgeInsets? margin,  
120 - EdgeInsets? padding,  
121 - double? borderRadius,  
122 - Color? borderColor,  
123 - double? borderWidth, 21 +extension ExtensionBottomSheet on GetInterface {
  22 + Future<T?> bottomSheet<T>(
  23 + Widget bottomsheet, {
124 Color? backgroundColor, 24 Color? backgroundColor,
125 - Color? leftBarIndicatorColor,  
126 - List<BoxShadow>? boxShadows,  
127 - Gradient? backgroundGradient,  
128 - TextButton? mainButton,  
129 - OnTap? onTap,  
130 - bool? isDismissible,  
131 - bool? showProgressIndicator,  
132 - SnackDismissDirection? dismissDirection,  
133 - AnimationController? progressIndicatorController,  
134 - Color? progressIndicatorBackgroundColor,  
135 - Animation<Color>? progressIndicatorValueColor,  
136 - SnackStyle? snackStyle,  
137 - Curve? forwardAnimationCurve,  
138 - Curve? reverseAnimationCurve,  
139 - Duration? animationDuration,  
140 - double? barBlur,  
141 - double? overlayBlur,  
142 - SnackbarStatusCallback? snackbarStatus,  
143 - Color? overlayColor,  
144 - Form? userInputForm,  
145 - }) async {  
146 - final getBar = GetBar(  
147 - snackbarStatus: snackbarStatus,  
148 - titleText: titleText ??  
149 - Text(  
150 - title,  
151 - style: TextStyle(  
152 - color: colorText ?? iconColor ?? Colors.black,  
153 - fontWeight: FontWeight.w800,  
154 - fontSize: 16,  
155 - ),  
156 - ),  
157 - messageText: messageText ??  
158 - Text(  
159 - message,  
160 - style: TextStyle(  
161 - color: colorText ?? iconColor ?? Colors.black,  
162 - fontWeight: FontWeight.w300,  
163 - fontSize: 14,  
164 - ),  
165 - ),  
166 - snackPosition: snackPosition ?? SnackPosition.TOP,  
167 - borderRadius: borderRadius ?? 15,  
168 - margin: margin ?? EdgeInsets.symmetric(horizontal: 10),  
169 - duration: duration ?? Duration(seconds: 3),  
170 - barBlur: barBlur ?? 7.0,  
171 - backgroundColor: backgroundColor ?? Colors.grey.withOpacity(0.2),  
172 - icon: icon,  
173 - shouldIconPulse: shouldIconPulse ?? true,  
174 - maxWidth: maxWidth,  
175 - padding: padding ?? EdgeInsets.all(16),  
176 - borderColor: borderColor,  
177 - borderWidth: borderWidth,  
178 - leftBarIndicatorColor: leftBarIndicatorColor,  
179 - boxShadows: boxShadows,  
180 - backgroundGradient: backgroundGradient,  
181 - mainButton: mainButton,  
182 - onTap: onTap,  
183 - isDismissible: isDismissible ?? true,  
184 - dismissDirection: dismissDirection ?? SnackDismissDirection.VERTICAL,  
185 - showProgressIndicator: showProgressIndicator ?? false,  
186 - progressIndicatorController: progressIndicatorController,  
187 - progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,  
188 - progressIndicatorValueColor: progressIndicatorValueColor,  
189 - snackStyle: snackStyle ?? SnackStyle.FLOATING,  
190 - forwardAnimationCurve: forwardAnimationCurve ?? Curves.easeOutCirc,  
191 - reverseAnimationCurve: reverseAnimationCurve ?? Curves.easeOutCirc,  
192 - animationDuration: animationDuration ?? Duration(seconds: 1),  
193 - overlayBlur: overlayBlur ?? 0.0,  
194 - overlayColor: overlayColor ?? Colors.transparent,  
195 - userInputForm: userInputForm);  
196 -  
197 - if (instantInit) {  
198 - showSnackbar<T>(getBar);  
199 - } else {  
200 - routing.isSnackbar = true;  
201 - SchedulerBinding.instance!.addPostFrameCallback((_) {  
202 - showSnackbar<T>(getBar);  
203 - });  
204 - }  
205 - }  
206 -} 25 + double? elevation,
  26 + bool persistent = true,
  27 + ShapeBorder? shape,
  28 + Clip? clipBehavior,
  29 + Color? barrierColor,
  30 + bool? ignoreSafeArea,
  31 + bool isScrollControlled = false,
  32 + bool useRootNavigator = false,
  33 + bool isDismissible = true,
  34 + bool enableDrag = true,
  35 + RouteSettings? settings,
  36 + Duration? enterBottomSheetDuration,
  37 + Duration? exitBottomSheetDuration,
  38 + }) {
  39 + return Navigator.of(overlayContext!, rootNavigator: useRootNavigator)
  40 + .push(GetModalBottomSheetRoute<T>(
  41 + builder: (_) => bottomsheet,
  42 + isPersistent: persistent,
  43 + // theme: Theme.of(key.currentContext, shadowThemeOnly: true),
  44 + theme: Theme.of(key.currentContext!),
  45 + isScrollControlled: isScrollControlled,
207 46
208 -extension OverlayExt on GetInterface {  
209 - Future<T> showOverlay<T>({  
210 - required Future<T> Function() asyncFunction,  
211 - Color opacityColor = Colors.black,  
212 - Widget? loadingWidget,  
213 - double opacity = .5,  
214 - }) async {  
215 - final navigatorState =  
216 - Navigator.of(Get.overlayContext!, rootNavigator: false);  
217 - final overlayState = navigatorState.overlay!; 47 + barrierLabel: MaterialLocalizations.of(key.currentContext!)
  48 + .modalBarrierDismissLabel,
218 49
219 - final overlayEntryOpacity = OverlayEntry(builder: (context) {  
220 - return Opacity(  
221 - opacity: opacity,  
222 - child: Container(  
223 - color: opacityColor,  
224 - ));  
225 - });  
226 - final overlayEntryLoader = OverlayEntry(builder: (context) {  
227 - return loadingWidget ??  
228 - Center(  
229 - child: Container(  
230 - height: 90,  
231 - width: 90,  
232 - child: Text('Loading...'), 50 + backgroundColor: backgroundColor ?? Colors.transparent,
  51 + elevation: elevation,
  52 + shape: shape,
  53 + removeTop: ignoreSafeArea ?? true,
  54 + clipBehavior: clipBehavior,
  55 + isDismissible: isDismissible,
  56 + modalBarrierColor: barrierColor,
  57 + settings: settings,
  58 + enableDrag: enableDrag,
  59 + enterBottomSheetDuration:
  60 + enterBottomSheetDuration ?? const Duration(milliseconds: 250),
  61 + exitBottomSheetDuration:
  62 + exitBottomSheetDuration ?? const Duration(milliseconds: 200),
233 )); 63 ));
234 - });  
235 - overlayState.insert(overlayEntryOpacity);  
236 - overlayState.insert(overlayEntryLoader);  
237 -  
238 - T data;  
239 -  
240 - try {  
241 - data = await asyncFunction();  
242 - } on Exception catch (_) {  
243 - overlayEntryLoader.remove();  
244 - overlayEntryOpacity.remove();  
245 - rethrow;  
246 - }  
247 -  
248 - overlayEntryLoader.remove();  
249 - overlayEntryOpacity.remove();  
250 - return data;  
251 } 64 }
252 } 65 }
253 66
@@ -378,7 +191,7 @@ extension ExtensionDialog on GetInterface { @@ -378,7 +191,7 @@ extension ExtensionDialog on GetInterface {
378 padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8), 191 padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8),
379 shape: RoundedRectangleBorder( 192 shape: RoundedRectangleBorder(
380 side: BorderSide( 193 side: BorderSide(
381 - color: buttonColor ?? theme.accentColor, 194 + color: buttonColor ?? theme.colorScheme.secondary,
382 width: 2, 195 width: 2,
383 style: BorderStyle.solid), 196 style: BorderStyle.solid),
384 borderRadius: BorderRadius.circular(100)), 197 borderRadius: BorderRadius.circular(100)),
@@ -389,7 +202,8 @@ extension ExtensionDialog on GetInterface { @@ -389,7 +202,8 @@ extension ExtensionDialog on GetInterface {
389 }, 202 },
390 child: Text( 203 child: Text(
391 textCancel ?? "Cancel", 204 textCancel ?? "Cancel",
392 - style: TextStyle(color: cancelTextColor ?? theme.accentColor), 205 + style: TextStyle(
  206 + color: cancelTextColor ?? theme.colorScheme.secondary),
393 ), 207 ),
394 )); 208 ));
395 } 209 }
@@ -397,113 +211,260 @@ extension ExtensionDialog on GetInterface { @@ -397,113 +211,260 @@ extension ExtensionDialog on GetInterface {
397 if (confirm != null) { 211 if (confirm != null) {
398 actions.add(confirm); 212 actions.add(confirm);
399 } else { 213 } else {
400 - if (leanConfirm) {  
401 - actions.add(TextButton(  
402 - style: TextButton.styleFrom(  
403 - tapTargetSize: MaterialTapTargetSize.shrinkWrap,  
404 - backgroundColor: buttonColor ?? theme.accentColor,  
405 - shape: RoundedRectangleBorder(  
406 - borderRadius: BorderRadius.circular(100)),  
407 - ),  
408 - child: Text(  
409 - textConfirm ?? "Ok",  
410 - style:  
411 - TextStyle(color: confirmTextColor ?? theme.backgroundColor),  
412 - ),  
413 - onPressed: () {  
414 - onConfirm?.call();  
415 - })); 214 + if (leanConfirm) {
  215 + actions.add(TextButton(
  216 + style: TextButton.styleFrom(
  217 + tapTargetSize: MaterialTapTargetSize.shrinkWrap,
  218 + backgroundColor: buttonColor ?? theme.colorScheme.secondary,
  219 + shape: RoundedRectangleBorder(
  220 + borderRadius: BorderRadius.circular(100)),
  221 + ),
  222 + child: Text(
  223 + textConfirm ?? "Ok",
  224 + style:
  225 + TextStyle(color: confirmTextColor ?? theme.backgroundColor),
  226 + ),
  227 + onPressed: () {
  228 + onConfirm?.call();
  229 + }));
  230 + }
  231 + }
  232 +
  233 + Widget baseAlertDialog = AlertDialog(
  234 + titlePadding: titlePadding ?? EdgeInsets.all(8),
  235 + contentPadding: contentPadding ?? EdgeInsets.all(8),
  236 +
  237 + backgroundColor: backgroundColor ?? theme.dialogBackgroundColor,
  238 + shape: RoundedRectangleBorder(
  239 + borderRadius: BorderRadius.all(Radius.circular(radius))),
  240 + title: Text(title, textAlign: TextAlign.center, style: titleStyle),
  241 + content: Column(
  242 + crossAxisAlignment: CrossAxisAlignment.center,
  243 + mainAxisSize: MainAxisSize.min,
  244 + children: [
  245 + content ??
  246 + Text(middleText,
  247 + textAlign: TextAlign.center, style: middleTextStyle),
  248 + SizedBox(height: 16),
  249 + ButtonTheme(
  250 + minWidth: 78.0,
  251 + height: 34.0,
  252 + child: Wrap(
  253 + alignment: WrapAlignment.center,
  254 + spacing: 8,
  255 + runSpacing: 8,
  256 + children: actions,
  257 + ),
  258 + )
  259 + ],
  260 + ),
  261 + // actions: actions, // ?? <Widget>[cancelButton, confirmButton],
  262 + buttonPadding: EdgeInsets.zero,
  263 + );
  264 +
  265 + return dialog<T>(
  266 + onWillPop != null
  267 + ? WillPopScope(
  268 + onWillPop: onWillPop,
  269 + child: baseAlertDialog,
  270 + )
  271 + : baseAlertDialog,
  272 + barrierDismissible: barrierDismissible,
  273 + navigatorKey: navigatorKey,
  274 + );
  275 + }
  276 +}
  277 +
  278 +extension ExtensionSnackbar on GetInterface {
  279 + void rawSnackbar({
  280 + String? title,
  281 + String? message,
  282 + Widget? titleText,
  283 + Widget? messageText,
  284 + Widget? icon,
  285 + bool instantInit = true,
  286 + bool shouldIconPulse = true,
  287 + double? maxWidth,
  288 + EdgeInsets margin = const EdgeInsets.all(0.0),
  289 + EdgeInsets padding = const EdgeInsets.all(16),
  290 + double borderRadius = 0.0,
  291 + Color? borderColor,
  292 + double borderWidth = 1.0,
  293 + Color backgroundColor = const Color(0xFF303030),
  294 + Color? leftBarIndicatorColor,
  295 + List<BoxShadow>? boxShadows,
  296 + Gradient? backgroundGradient,
  297 + Widget? mainButton,
  298 + OnTap? onTap,
  299 + Duration duration = const Duration(seconds: 3),
  300 + bool isDismissible = true,
  301 + SnackDismissDirection dismissDirection = SnackDismissDirection.VERTICAL,
  302 + bool showProgressIndicator = false,
  303 + AnimationController? progressIndicatorController,
  304 + Color? progressIndicatorBackgroundColor,
  305 + Animation<Color>? progressIndicatorValueColor,
  306 + SnackPosition snackPosition = SnackPosition.BOTTOM,
  307 + SnackStyle snackStyle = SnackStyle.FLOATING,
  308 + Curve forwardAnimationCurve = Curves.easeOutCirc,
  309 + Curve reverseAnimationCurve = Curves.easeOutCirc,
  310 + Duration animationDuration = const Duration(seconds: 1),
  311 + SnackbarStatusCallback? snackbarStatus,
  312 + double? barBlur = 0.0,
  313 + double overlayBlur = 0.0,
  314 + Color? overlayColor,
  315 + Form? userInputForm,
  316 + }) async {
  317 + final getBar = GetBar(
  318 + snackbarStatus: snackbarStatus,
  319 + title: title,
  320 + message: message,
  321 + titleText: titleText,
  322 + messageText: messageText,
  323 + snackPosition: snackPosition,
  324 + borderRadius: borderRadius,
  325 + margin: margin,
  326 + duration: duration,
  327 + barBlur: barBlur,
  328 + backgroundColor: backgroundColor,
  329 + icon: icon,
  330 + shouldIconPulse: shouldIconPulse,
  331 + maxWidth: maxWidth,
  332 + padding: padding,
  333 + borderColor: borderColor,
  334 + borderWidth: borderWidth,
  335 + leftBarIndicatorColor: leftBarIndicatorColor,
  336 + boxShadows: boxShadows,
  337 + backgroundGradient: backgroundGradient,
  338 + mainButton: mainButton,
  339 + onTap: onTap,
  340 + isDismissible: isDismissible,
  341 + dismissDirection: dismissDirection,
  342 + showProgressIndicator: showProgressIndicator,
  343 + progressIndicatorController: progressIndicatorController,
  344 + progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
  345 + progressIndicatorValueColor: progressIndicatorValueColor,
  346 + snackStyle: snackStyle,
  347 + forwardAnimationCurve: forwardAnimationCurve,
  348 + reverseAnimationCurve: reverseAnimationCurve,
  349 + animationDuration: animationDuration,
  350 + overlayBlur: overlayBlur,
  351 + overlayColor: overlayColor,
  352 + userInputForm: userInputForm,
  353 + );
  354 +
  355 + if (instantInit) {
  356 + getBar.show();
  357 + } else {
  358 + SchedulerBinding.instance!.addPostFrameCallback((_) {
  359 + getBar.show();
  360 + });
416 } 361 }
417 } 362 }
418 363
419 - Widget baseAlertDialog = AlertDialog(  
420 - titlePadding: titlePadding ?? EdgeInsets.all(8),  
421 - contentPadding: contentPadding ?? EdgeInsets.all(8), 364 + Future<void> showSnackbar<T>(GetBar snackbar) {
  365 + return SnackbarController(snackbar).show();
  366 + }
422 367
423 - backgroundColor: backgroundColor ?? theme.dialogBackgroundColor,  
424 - shape: RoundedRectangleBorder(  
425 - borderRadius: BorderRadius.all(Radius.circular(radius))),  
426 - title: Text(title, textAlign: TextAlign.center, style: titleStyle),  
427 - content: Column(  
428 - crossAxisAlignment: CrossAxisAlignment.center,  
429 - mainAxisSize: MainAxisSize.min,  
430 - children: [  
431 - content ??  
432 - Text(middleText,  
433 - textAlign: TextAlign.center, style: middleTextStyle),  
434 - SizedBox(height: 16),  
435 - ButtonTheme(  
436 - minWidth: 78.0,  
437 - height: 34.0,  
438 - child: Wrap(  
439 - alignment: WrapAlignment.center,  
440 - spacing: 8,  
441 - runSpacing: 8,  
442 - children: actions, 368 + void snackbar<T>(
  369 + String title,
  370 + String message, {
  371 + Color? colorText,
  372 + Duration? duration,
  373 +
  374 + /// with instantInit = false you can put snackbar on initState
  375 + bool instantInit = true,
  376 + SnackPosition? snackPosition,
  377 + Widget? titleText,
  378 + Widget? messageText,
  379 + Widget? icon,
  380 + bool? shouldIconPulse,
  381 + double? maxWidth,
  382 + EdgeInsets? margin,
  383 + EdgeInsets? padding,
  384 + double? borderRadius,
  385 + Color? borderColor,
  386 + double? borderWidth,
  387 + Color? backgroundColor,
  388 + Color? leftBarIndicatorColor,
  389 + List<BoxShadow>? boxShadows,
  390 + Gradient? backgroundGradient,
  391 + TextButton? mainButton,
  392 + OnTap? onTap,
  393 + bool? isDismissible,
  394 + bool? showProgressIndicator,
  395 + SnackDismissDirection? dismissDirection,
  396 + AnimationController? progressIndicatorController,
  397 + Color? progressIndicatorBackgroundColor,
  398 + Animation<Color>? progressIndicatorValueColor,
  399 + SnackStyle? snackStyle,
  400 + Curve? forwardAnimationCurve,
  401 + Curve? reverseAnimationCurve,
  402 + Duration? animationDuration,
  403 + double? barBlur,
  404 + double? overlayBlur,
  405 + SnackbarStatusCallback? snackbarStatus,
  406 + Color? overlayColor,
  407 + Form? userInputForm,
  408 + }) async {
  409 + final getBar = GetBar(
  410 + snackbarStatus: snackbarStatus,
  411 + titleText: titleText ??
  412 + Text(
  413 + title,
  414 + style: TextStyle(
  415 + color: colorText ?? iconColor ?? Colors.black,
  416 + fontWeight: FontWeight.w800,
  417 + fontSize: 16,
443 ), 418 ),
444 - )  
445 - ],  
446 ), 419 ),
447 - // actions: actions, // ?? <Widget>[cancelButton, confirmButton],  
448 - buttonPadding: EdgeInsets.zero,  
449 - ); 420 + messageText: messageText ??
  421 + Text(
  422 + message,
  423 + style: TextStyle(
  424 + color: colorText ?? iconColor ?? Colors.black,
  425 + fontWeight: FontWeight.w300,
  426 + fontSize: 14,
  427 + ),
  428 + ),
  429 + snackPosition: snackPosition ?? SnackPosition.TOP,
  430 + borderRadius: borderRadius ?? 15,
  431 + margin: margin ?? EdgeInsets.symmetric(horizontal: 10),
  432 + duration: duration ?? Duration(seconds: 3),
  433 + barBlur: barBlur ?? 7.0,
  434 + backgroundColor: backgroundColor ?? Colors.grey.withOpacity(0.2),
  435 + icon: icon,
  436 + shouldIconPulse: shouldIconPulse ?? true,
  437 + maxWidth: maxWidth,
  438 + padding: padding ?? EdgeInsets.all(16),
  439 + borderColor: borderColor,
  440 + borderWidth: borderWidth,
  441 + leftBarIndicatorColor: leftBarIndicatorColor,
  442 + boxShadows: boxShadows,
  443 + backgroundGradient: backgroundGradient,
  444 + mainButton: mainButton,
  445 + onTap: onTap,
  446 + isDismissible: isDismissible ?? true,
  447 + dismissDirection: dismissDirection ?? SnackDismissDirection.VERTICAL,
  448 + showProgressIndicator: showProgressIndicator ?? false,
  449 + progressIndicatorController: progressIndicatorController,
  450 + progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
  451 + progressIndicatorValueColor: progressIndicatorValueColor,
  452 + snackStyle: snackStyle ?? SnackStyle.FLOATING,
  453 + forwardAnimationCurve: forwardAnimationCurve ?? Curves.easeOutCirc,
  454 + reverseAnimationCurve: reverseAnimationCurve ?? Curves.easeOutCirc,
  455 + animationDuration: animationDuration ?? Duration(seconds: 1),
  456 + overlayBlur: overlayBlur ?? 0.0,
  457 + overlayColor: overlayColor ?? Colors.transparent,
  458 + userInputForm: userInputForm);
450 459
451 - return dialog<T>(  
452 - onWillPop != null  
453 - ? WillPopScope(  
454 - onWillPop: onWillPop,  
455 - child: baseAlertDialog,  
456 - )  
457 - : baseAlertDialog,  
458 - barrierDismissible: barrierDismissible,  
459 - navigatorKey: navigatorKey,  
460 - ); 460 + if (instantInit) {
  461 + showSnackbar<T>(getBar);
  462 + } else {
  463 + //routing.isSnackbar = true;
  464 + SchedulerBinding.instance!.addPostFrameCallback((_) {
  465 + showSnackbar<T>(getBar);
  466 + });
461 } 467 }
462 -}  
463 -  
464 -extension ExtensionBottomSheet on GetInterface {  
465 - Future<T?> bottomSheet<T>(  
466 - Widget bottomsheet, {  
467 - Color? backgroundColor,  
468 - double? elevation,  
469 - bool persistent = true,  
470 - ShapeBorder? shape,  
471 - Clip? clipBehavior,  
472 - Color? barrierColor,  
473 - bool? ignoreSafeArea,  
474 - bool isScrollControlled = false,  
475 - bool useRootNavigator = false,  
476 - bool isDismissible = true,  
477 - bool enableDrag = true,  
478 - RouteSettings? settings,  
479 - Duration? enterBottomSheetDuration,  
480 - Duration? exitBottomSheetDuration,  
481 - }) {  
482 - return Navigator.of(overlayContext!, rootNavigator: useRootNavigator)  
483 - .push(GetModalBottomSheetRoute<T>(  
484 - builder: (_) => bottomsheet,  
485 - isPersistent: persistent,  
486 - // theme: Theme.of(key.currentContext, shadowThemeOnly: true),  
487 - theme: Theme.of(key.currentContext!),  
488 - isScrollControlled: isScrollControlled,  
489 -  
490 - barrierLabel: MaterialLocalizations.of(key.currentContext!)  
491 - .modalBarrierDismissLabel,  
492 -  
493 - backgroundColor: backgroundColor ?? Colors.transparent,  
494 - elevation: elevation,  
495 - shape: shape,  
496 - removeTop: ignoreSafeArea ?? true,  
497 - clipBehavior: clipBehavior,  
498 - isDismissible: isDismissible,  
499 - modalBarrierColor: barrierColor,  
500 - settings: settings,  
501 - enableDrag: enableDrag,  
502 - enterBottomSheetDuration:  
503 - enterBottomSheetDuration ?? const Duration(milliseconds: 250),  
504 - exitBottomSheetDuration:  
505 - exitBottomSheetDuration ?? const Duration(milliseconds: 200),  
506 - ));  
507 } 468 }
508 } 469 }
509 470
@@ -1134,8 +1095,9 @@ you can only use widgets and widget functions here'''; @@ -1134,8 +1095,9 @@ you can only use widgets and widget functions here''';
1134 /// give name from previous route 1095 /// give name from previous route
1135 String get previousRoute => routing.previous; 1096 String get previousRoute => routing.previous;
1136 1097
  1098 + ///TODO: made snackbar 2.0 trackeables
1137 /// check if snackbar is open 1099 /// check if snackbar is open
1138 - bool? get isSnackbarOpen => routing.isSnackbar; 1100 + bool? get isSnackbarOpen => true; //routing.isSnackbar;
1139 1101
1140 /// check if dialog is open 1102 /// check if dialog is open
1141 bool? get isDialogOpen => routing.isDialog; 1103 bool? get isDialogOpen => routing.isDialog;
@@ -1341,7 +1303,48 @@ extension NavTwoExt on GetInterface { @@ -1341,7 +1303,48 @@ extension NavTwoExt on GetInterface {
1341 } 1303 }
1342 } 1304 }
1343 1305
1344 -/// It replaces the Flutter Navigator, but needs no context.  
1345 -/// You can to use navigator.push(YourRoute()) rather  
1346 -/// Navigator.push(context, YourRoute());  
1347 -NavigatorState? get navigator => GetNavigation(Get).key.currentState; 1306 +extension OverlayExt on GetInterface {
  1307 + Future<T> showOverlay<T>({
  1308 + required Future<T> Function() asyncFunction,
  1309 + Color opacityColor = Colors.black,
  1310 + Widget? loadingWidget,
  1311 + double opacity = .5,
  1312 + }) async {
  1313 + final navigatorState =
  1314 + Navigator.of(Get.overlayContext!, rootNavigator: false);
  1315 + final overlayState = navigatorState.overlay!;
  1316 +
  1317 + final overlayEntryOpacity = OverlayEntry(builder: (context) {
  1318 + return Opacity(
  1319 + opacity: opacity,
  1320 + child: Container(
  1321 + color: opacityColor,
  1322 + ));
  1323 + });
  1324 + final overlayEntryLoader = OverlayEntry(builder: (context) {
  1325 + return loadingWidget ??
  1326 + Center(
  1327 + child: Container(
  1328 + height: 90,
  1329 + width: 90,
  1330 + child: Text('Loading...'),
  1331 + ));
  1332 + });
  1333 + overlayState.insert(overlayEntryOpacity);
  1334 + overlayState.insert(overlayEntryLoader);
  1335 +
  1336 + T data;
  1337 +
  1338 + try {
  1339 + data = await asyncFunction();
  1340 + } on Exception catch (_) {
  1341 + overlayEntryLoader.remove();
  1342 + overlayEntryOpacity.remove();
  1343 + rethrow;
  1344 + }
  1345 +
  1346 + overlayEntryLoader.remove();
  1347 + overlayEntryOpacity.remove();
  1348 + return data;
  1349 + }
  1350 +}
@@ -10,6 +10,63 @@ import '../../get_navigation.dart'; @@ -10,6 +10,63 @@ import '../../get_navigation.dart';
10 import 'root_controller.dart'; 10 import 'root_controller.dart';
11 11
12 class GetMaterialApp extends StatelessWidget { 12 class GetMaterialApp extends StatelessWidget {
  13 + final GlobalKey<NavigatorState>? navigatorKey;
  14 +
  15 + final GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey;
  16 + final Widget? home;
  17 + final Map<String, WidgetBuilder>? routes;
  18 + final String? initialRoute;
  19 + final RouteFactory? onGenerateRoute;
  20 + final InitialRouteListFactory? onGenerateInitialRoutes;
  21 + final RouteFactory? onUnknownRoute;
  22 + final List<NavigatorObserver>? navigatorObservers;
  23 + final TransitionBuilder? builder;
  24 + final String title;
  25 + final GenerateAppTitle? onGenerateTitle;
  26 + final ThemeData? theme;
  27 + final ThemeData? darkTheme;
  28 + final ThemeMode themeMode;
  29 + final CustomTransition? customTransition;
  30 + final Color? color;
  31 + final Map<String, Map<String, String>>? translationsKeys;
  32 + final Translations? translations;
  33 + final TextDirection? textDirection;
  34 + final Locale? locale;
  35 + final Locale? fallbackLocale;
  36 + final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates;
  37 + final LocaleListResolutionCallback? localeListResolutionCallback;
  38 + final LocaleResolutionCallback? localeResolutionCallback;
  39 + final Iterable<Locale> supportedLocales;
  40 + final bool showPerformanceOverlay;
  41 + final bool checkerboardRasterCacheImages;
  42 + final bool checkerboardOffscreenLayers;
  43 + final bool showSemanticsDebugger;
  44 + final bool debugShowCheckedModeBanner;
  45 + final Map<LogicalKeySet, Intent>? shortcuts;
  46 + final ScrollBehavior? scrollBehavior;
  47 + final ThemeData? highContrastTheme;
  48 + final ThemeData? highContrastDarkTheme;
  49 + final Map<Type, Action<Intent>>? actions;
  50 + final bool debugShowMaterialGrid;
  51 + final ValueChanged<Routing?>? routingCallback;
  52 + final Transition? defaultTransition;
  53 + final bool? opaqueRoute;
  54 + final VoidCallback? onInit;
  55 + final VoidCallback? onReady;
  56 + final VoidCallback? onDispose;
  57 + final bool? enableLog;
  58 + final LogWriterCallback? logWriterCallback;
  59 + final bool? popGesture;
  60 + final SmartManagement smartManagement;
  61 + final Bindings? initialBinding;
  62 + final Duration? transitionDuration;
  63 + final bool? defaultGlobalState;
  64 + final List<GetPage>? getPages;
  65 + final GetPage? unknownRoute;
  66 + final RouteInformationProvider? routeInformationProvider;
  67 + final RouteInformationParser<Object>? routeInformationParser;
  68 + final RouterDelegate<Object>? routerDelegate;
  69 + final BackButtonDispatcher? backButtonDispatcher;
13 const GetMaterialApp({ 70 const GetMaterialApp({
14 Key? key, 71 Key? key,
15 this.navigatorKey, 72 this.navigatorKey,
@@ -72,63 +129,6 @@ class GetMaterialApp extends StatelessWidget { @@ -72,63 +129,6 @@ class GetMaterialApp extends StatelessWidget {
72 backButtonDispatcher = null, 129 backButtonDispatcher = null,
73 super(key: key); 130 super(key: key);
74 131
75 - final GlobalKey<NavigatorState>? navigatorKey;  
76 - final GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey;  
77 - final Widget? home;  
78 - final Map<String, WidgetBuilder>? routes;  
79 - final String? initialRoute;  
80 - final RouteFactory? onGenerateRoute;  
81 - final InitialRouteListFactory? onGenerateInitialRoutes;  
82 - final RouteFactory? onUnknownRoute;  
83 - final List<NavigatorObserver>? navigatorObservers;  
84 - final TransitionBuilder? builder;  
85 - final String title;  
86 - final GenerateAppTitle? onGenerateTitle;  
87 - final ThemeData? theme;  
88 - final ThemeData? darkTheme;  
89 - final ThemeMode themeMode;  
90 - final CustomTransition? customTransition;  
91 - final Color? color;  
92 - final Map<String, Map<String, String>>? translationsKeys;  
93 - final Translations? translations;  
94 - final TextDirection? textDirection;  
95 - final Locale? locale;  
96 - final Locale? fallbackLocale;  
97 - final Iterable<LocalizationsDelegate<dynamic>>? localizationsDelegates;  
98 - final LocaleListResolutionCallback? localeListResolutionCallback;  
99 - final LocaleResolutionCallback? localeResolutionCallback;  
100 - final Iterable<Locale> supportedLocales;  
101 - final bool showPerformanceOverlay;  
102 - final bool checkerboardRasterCacheImages;  
103 - final bool checkerboardOffscreenLayers;  
104 - final bool showSemanticsDebugger;  
105 - final bool debugShowCheckedModeBanner;  
106 - final Map<LogicalKeySet, Intent>? shortcuts;  
107 - final ScrollBehavior? scrollBehavior;  
108 - final ThemeData? highContrastTheme;  
109 - final ThemeData? highContrastDarkTheme;  
110 - final Map<Type, Action<Intent>>? actions;  
111 - final bool debugShowMaterialGrid;  
112 - final ValueChanged<Routing?>? routingCallback;  
113 - final Transition? defaultTransition;  
114 - final bool? opaqueRoute;  
115 - final VoidCallback? onInit;  
116 - final VoidCallback? onReady;  
117 - final VoidCallback? onDispose;  
118 - final bool? enableLog;  
119 - final LogWriterCallback? logWriterCallback;  
120 - final bool? popGesture;  
121 - final SmartManagement smartManagement;  
122 - final Bindings? initialBinding;  
123 - final Duration? transitionDuration;  
124 - final bool? defaultGlobalState;  
125 - final List<GetPage>? getPages;  
126 - final GetPage? unknownRoute;  
127 - final RouteInformationProvider? routeInformationProvider;  
128 - final RouteInformationParser<Object>? routeInformationParser;  
129 - final RouterDelegate<Object>? routerDelegate;  
130 - final BackButtonDispatcher? backButtonDispatcher;  
131 -  
132 GetMaterialApp.router({ 132 GetMaterialApp.router({
133 Key? key, 133 Key? key,
134 this.routeInformationProvider, 134 this.routeInformationProvider,
@@ -200,31 +200,6 @@ class GetMaterialApp extends StatelessWidget { @@ -200,31 +200,6 @@ class GetMaterialApp extends StatelessWidget {
200 Get.routeInformationParser = routeInformationParser; 200 Get.routeInformationParser = routeInformationParser;
201 } 201 }
202 202
203 - Route<dynamic> generator(RouteSettings settings) {  
204 - return PageRedirect(settings: settings, unknownRoute: unknownRoute).page();  
205 - }  
206 -  
207 - List<Route<dynamic>> initialRoutesGenerate(String name) {  
208 - return [  
209 - PageRedirect(  
210 - settings: RouteSettings(name: name),  
211 - unknownRoute: unknownRoute,  
212 - ).page()  
213 - ];  
214 - }  
215 -  
216 - Widget defaultBuilder(BuildContext context, Widget? child) {  
217 - return Directionality(  
218 - textDirection: textDirection ??  
219 - (rtlLanguages.contains(Get.locale?.languageCode)  
220 - ? TextDirection.rtl  
221 - : TextDirection.ltr),  
222 - child: builder == null  
223 - ? (child ?? Material())  
224 - : builder!(context, child ?? Material()),  
225 - );  
226 - }  
227 -  
228 @override 203 @override
229 Widget build(BuildContext context) => GetBuilder<GetMaterialController>( 204 Widget build(BuildContext context) => GetBuilder<GetMaterialController>(
230 init: Get.rootController, 205 init: Get.rootController,
@@ -270,7 +245,6 @@ class GetMaterialApp extends StatelessWidget { @@ -270,7 +245,6 @@ class GetMaterialApp extends StatelessWidget {
270 ? MaterialApp.router( 245 ? MaterialApp.router(
271 routerDelegate: routerDelegate!, 246 routerDelegate: routerDelegate!,
272 routeInformationParser: routeInformationParser!, 247 routeInformationParser: routeInformationParser!,
273 - scaffoldMessengerKey: scaffoldMessengerKey,  
274 backButtonDispatcher: backButtonDispatcher, 248 backButtonDispatcher: backButtonDispatcher,
275 routeInformationProvider: routeInformationProvider, 249 routeInformationProvider: routeInformationProvider,
276 key: _.unikey, 250 key: _.unikey,
@@ -283,6 +257,8 @@ class GetMaterialApp extends StatelessWidget { @@ -283,6 +257,8 @@ class GetMaterialApp extends StatelessWidget {
283 _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(), 257 _.darkTheme ?? darkTheme ?? theme ?? ThemeData.fallback(),
284 themeMode: _.themeMode ?? themeMode, 258 themeMode: _.themeMode ?? themeMode,
285 locale: Get.locale ?? locale, 259 locale: Get.locale ?? locale,
  260 + scaffoldMessengerKey:
  261 + scaffoldMessengerKey ?? _.scaffoldMessengerKey,
286 localizationsDelegates: localizationsDelegates, 262 localizationsDelegates: localizationsDelegates,
287 localeListResolutionCallback: localeListResolutionCallback, 263 localeListResolutionCallback: localeListResolutionCallback,
288 localeResolutionCallback: localeResolutionCallback, 264 localeResolutionCallback: localeResolutionCallback,
@@ -301,7 +277,8 @@ class GetMaterialApp extends StatelessWidget { @@ -301,7 +277,8 @@ class GetMaterialApp extends StatelessWidget {
301 navigatorKey: (navigatorKey == null 277 navigatorKey: (navigatorKey == null
302 ? Get.key 278 ? Get.key
303 : Get.addKey(navigatorKey!)), 279 : Get.addKey(navigatorKey!)),
304 - scaffoldMessengerKey: scaffoldMessengerKey, 280 + scaffoldMessengerKey:
  281 + scaffoldMessengerKey ?? _.scaffoldMessengerKey,
305 home: home, 282 home: home,
306 routes: routes ?? const <String, WidgetBuilder>{}, 283 routes: routes ?? const <String, WidgetBuilder>{},
307 initialRoute: initialRoute, 284 initialRoute: initialRoute,
@@ -343,4 +320,29 @@ class GetMaterialApp extends StatelessWidget { @@ -343,4 +320,29 @@ class GetMaterialApp extends StatelessWidget {
343 // actions: actions, 320 // actions: actions,
344 ), 321 ),
345 ); 322 );
  323 +
  324 + Widget defaultBuilder(BuildContext context, Widget? child) {
  325 + return Directionality(
  326 + textDirection: textDirection ??
  327 + (rtlLanguages.contains(Get.locale?.languageCode)
  328 + ? TextDirection.rtl
  329 + : TextDirection.ltr),
  330 + child: builder == null
  331 + ? (child ?? Material())
  332 + : builder!(context, child ?? Material()),
  333 + );
  334 + }
  335 +
  336 + Route<dynamic> generator(RouteSettings settings) {
  337 + return PageRedirect(settings: settings, unknownRoute: unknownRoute).page();
  338 + }
  339 +
  340 + List<Route<dynamic>> initialRoutesGenerate(String name) {
  341 + return [
  342 + PageRedirect(
  343 + settings: RouteSettings(name: name),
  344 + unknownRoute: unknownRoute,
  345 + ).page()
  346 + ];
  347 + }
346 } 348 }
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
  2 +
2 import '../../../get_state_manager/get_state_manager.dart'; 3 import '../../../get_state_manager/get_state_manager.dart';
3 import '../../../get_utils/get_utils.dart'; 4 import '../../../get_utils/get_utils.dart';
4 import '../routes/custom_transition.dart'; 5 import '../routes/custom_transition.dart';
@@ -12,6 +13,8 @@ class GetMaterialController extends GetxController { @@ -12,6 +13,8 @@ class GetMaterialController extends GetxController {
12 ThemeData? darkTheme; 13 ThemeData? darkTheme;
13 ThemeMode? themeMode; 14 ThemeMode? themeMode;
14 15
  16 + final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
  17 +
15 bool defaultPopGesture = GetPlatform.isIOS; 18 bool defaultPopGesture = GetPlatform.isIOS;
16 bool defaultOpaqueRoute = true; 19 bool defaultOpaqueRoute = true;
17 20
@@ -31,6 +34,8 @@ class GetMaterialController extends GetxController { @@ -31,6 +34,8 @@ class GetMaterialController extends GetxController {
31 34
32 var _key = GlobalKey<NavigatorState>(debugLabel: 'Key Created by default'); 35 var _key = GlobalKey<NavigatorState>(debugLabel: 'Key Created by default');
33 36
  37 + Map<dynamic, GlobalKey<NavigatorState>> keys = {};
  38 +
34 GlobalKey<NavigatorState> get key => _key; 39 GlobalKey<NavigatorState> get key => _key;
35 40
36 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) { 41 GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
@@ -38,7 +43,10 @@ class GetMaterialController extends GetxController { @@ -38,7 +43,10 @@ class GetMaterialController extends GetxController {
38 return key; 43 return key;
39 } 44 }
40 45
41 - Map<dynamic, GlobalKey<NavigatorState>> keys = {}; 46 + void restartApp() {
  47 + unikey = UniqueKey();
  48 + update();
  49 + }
42 50
43 void setTheme(ThemeData value) { 51 void setTheme(ThemeData value) {
44 if (darkTheme == null) { 52 if (darkTheme == null) {
@@ -57,9 +65,4 @@ class GetMaterialController extends GetxController { @@ -57,9 +65,4 @@ class GetMaterialController extends GetxController {
57 themeMode = value; 65 themeMode = value;
58 update(); 66 update();
59 } 67 }
60 -  
61 - void restartApp() {  
62 - unikey = UniqueKey();  
63 - update();  
64 - }  
65 } 68 }
@@ -5,37 +5,8 @@ import '../../../../instance_manager.dart'; @@ -5,37 +5,8 @@ import '../../../../instance_manager.dart';
5 import '../../../get_navigation.dart'; 5 import '../../../get_navigation.dart';
6 import '../../dialog/dialog_route.dart'; 6 import '../../dialog/dialog_route.dart';
7 import '../../router_report.dart'; 7 import '../../router_report.dart';
8 -import '../../snackbar/snack_route.dart';  
9 import '../default_route.dart'; 8 import '../default_route.dart';
10 9
11 -class Routing {  
12 - String current;  
13 - String previous;  
14 - dynamic args;  
15 - String removed;  
16 - Route<dynamic>? route;  
17 - bool? isBack;  
18 - bool? isSnackbar;  
19 - bool? isBottomSheet;  
20 - bool? isDialog;  
21 -  
22 - Routing({  
23 - this.current = '',  
24 - this.previous = '',  
25 - this.args,  
26 - this.removed = '',  
27 - this.route,  
28 - this.isBack,  
29 - this.isSnackbar,  
30 - this.isBottomSheet,  
31 - this.isDialog,  
32 - });  
33 -  
34 - void update(void fn(Routing value)) {  
35 - fn(this);  
36 - }  
37 -}  
38 -  
39 /// Extracts the name of a route based on it's instance type 10 /// Extracts the name of a route based on it's instance type
40 /// or null if not possible. 11 /// or null if not possible.
41 String? _extractRouteName(Route? route) { 12 String? _extractRouteName(Route? route) {
@@ -58,49 +29,70 @@ String? _extractRouteName(Route? route) { @@ -58,49 +29,70 @@ String? _extractRouteName(Route? route) {
58 return null; 29 return null;
59 } 30 }
60 31
61 -/// This is basically a util for rules about 'what a route is'  
62 -class _RouteData {  
63 - final bool isGetPageRoute;  
64 - final bool isSnackbar;  
65 - final bool isBottomSheet;  
66 - final bool isDialog;  
67 - final String? name; 32 +class GetObserver extends NavigatorObserver {
  33 + final Function(Routing?)? routing;
68 34
69 - _RouteData({  
70 - required this.name,  
71 - required this.isGetPageRoute,  
72 - required this.isSnackbar,  
73 - required this.isBottomSheet,  
74 - required this.isDialog,  
75 - }); 35 + final Routing? _routeSend;
76 36
77 - factory _RouteData.ofRoute(Route? route) {  
78 - return _RouteData(  
79 - name: _extractRouteName(route),  
80 - isGetPageRoute: route is GetPageRoute,  
81 - isSnackbar: route is SnackRoute,  
82 - isDialog: route is GetDialogRoute,  
83 - isBottomSheet: route is GetModalBottomSheetRoute,  
84 - ); 37 + GetObserver([this.routing, this._routeSend]);
  38 +
  39 + @override
  40 + void didPop(Route route, Route? previousRoute) {
  41 + super.didPop(route, previousRoute);
  42 + final currentRoute = _RouteData.ofRoute(route);
  43 + final newRoute = _RouteData.ofRoute(previousRoute);
  44 +
  45 + // if (currentRoute.isSnackbar) {
  46 + // // Get.log("CLOSE SNACKBAR ${currentRoute.name}");
  47 + // Get.log("CLOSE SNACKBAR");
  48 + // } else
  49 +
  50 + if (currentRoute.isBottomSheet || currentRoute.isDialog) {
  51 + Get.log("CLOSE ${currentRoute.name}");
  52 + } else if (currentRoute.isGetPageRoute) {
  53 + Get.log("CLOSE TO ROUTE ${currentRoute.name}");
  54 + }
  55 + if (previousRoute != null) {
  56 + RouterReportManager.reportCurrentRoute(previousRoute);
85 } 57 }
86 -}  
87 58
88 -class GetObserver extends NavigatorObserver {  
89 - final Function(Routing?)? routing; 59 + // Here we use a 'inverse didPush set', meaning that we use
  60 + // previous route instead of 'route' because this is
  61 + // a 'inverse push'
  62 + _routeSend?.update((value) {
  63 + // Only PageRoute is allowed to change current value
  64 + if (previousRoute is PageRoute) {
  65 + value.current = _extractRouteName(previousRoute) ?? '';
  66 + value.previous = newRoute.name ?? '';
  67 + } else if (value.previous.isNotEmpty) {
  68 + value.current = value.previous;
  69 + }
90 70
91 - GetObserver([this.routing, this._routeSend]); 71 + value.args = previousRoute?.settings.arguments;
  72 + value.route = previousRoute;
  73 + value.isBack = true;
  74 + value.removed = '';
  75 + // value.isSnackbar = newRoute.isSnackbar;
  76 + value.isBottomSheet = newRoute.isBottomSheet;
  77 + value.isDialog = newRoute.isDialog;
  78 + });
92 79
93 - final Routing? _routeSend; 80 + // print('currentRoute.isDialog ${currentRoute.isDialog}');
  81 +
  82 + routing?.call(_routeSend);
  83 + }
94 84
95 @override 85 @override
96 void didPush(Route route, Route? previousRoute) { 86 void didPush(Route route, Route? previousRoute) {
97 super.didPush(route, previousRoute); 87 super.didPush(route, previousRoute);
98 final newRoute = _RouteData.ofRoute(route); 88 final newRoute = _RouteData.ofRoute(route);
99 89
100 - if (newRoute.isSnackbar) {  
101 - // Get.log("OPEN SNACKBAR ${newRoute.name}");  
102 - Get.log("OPEN SNACKBAR");  
103 - } else if (newRoute.isBottomSheet || newRoute.isDialog) { 90 + // if (newRoute.isSnackbar) {
  91 + // // Get.log("OPEN SNACKBAR ${newRoute.name}");
  92 + // Get.log("OPEN SNACKBAR");
  93 + // } else
  94 +
  95 + if (newRoute.isBottomSheet || newRoute.isDialog) {
104 Get.log("OPEN ${newRoute.name}"); 96 Get.log("OPEN ${newRoute.name}");
105 } else if (newRoute.isGetPageRoute) { 97 } else if (newRoute.isGetPageRoute) {
106 Get.log("GOING TO ROUTE ${newRoute.name}"); 98 Get.log("GOING TO ROUTE ${newRoute.name}");
@@ -121,7 +113,7 @@ class GetObserver extends NavigatorObserver { @@ -121,7 +113,7 @@ class GetObserver extends NavigatorObserver {
121 value.route = route; 113 value.route = route;
122 value.isBack = false; 114 value.isBack = false;
123 value.removed = ''; 115 value.removed = '';
124 - value.isSnackbar = newRoute.isSnackbar ? true : value.isSnackbar ?? false; 116 + // value.isSnackbar = newRoute.isSnackbar ? true : value.isSnackbar ?? false;
125 value.isBottomSheet = 117 value.isBottomSheet =
126 newRoute.isBottomSheet ? true : value.isBottomSheet ?? false; 118 newRoute.isBottomSheet ? true : value.isBottomSheet ?? false;
127 value.isDialog = newRoute.isDialog ? true : value.isDialog ?? false; 119 value.isDialog = newRoute.isDialog ? true : value.isDialog ?? false;
@@ -133,46 +125,27 @@ class GetObserver extends NavigatorObserver { @@ -133,46 +125,27 @@ class GetObserver extends NavigatorObserver {
133 } 125 }
134 126
135 @override 127 @override
136 - void didPop(Route route, Route? previousRoute) {  
137 - super.didPop(route, previousRoute); 128 + void didRemove(Route route, Route? previousRoute) {
  129 + super.didRemove(route, previousRoute);
  130 + final routeName = _extractRouteName(route);
138 final currentRoute = _RouteData.ofRoute(route); 131 final currentRoute = _RouteData.ofRoute(route);
139 - final newRoute = _RouteData.ofRoute(previousRoute);  
140 132
141 - if (currentRoute.isSnackbar) {  
142 - // Get.log("CLOSE SNACKBAR ${currentRoute.name}");  
143 - Get.log("CLOSE SNACKBAR");  
144 - } else if (currentRoute.isBottomSheet || currentRoute.isDialog) {  
145 - Get.log("CLOSE ${currentRoute.name}");  
146 - } else if (currentRoute.isGetPageRoute) {  
147 - Get.log("CLOSE TO ROUTE ${currentRoute.name}");  
148 - }  
149 - if (previousRoute != null) {  
150 - RouterReportManager.reportCurrentRoute(previousRoute);  
151 - } 133 + Get.log("REMOVING ROUTE $routeName");
152 134
153 - // Here we use a 'inverse didPush set', meaning that we use  
154 - // previous route instead of 'route' because this is  
155 - // a 'inverse push'  
156 _routeSend?.update((value) { 135 _routeSend?.update((value) {
157 - // Only PageRoute is allowed to change current value  
158 - if (previousRoute is PageRoute) {  
159 - value.current = _extractRouteName(previousRoute) ?? '';  
160 - value.previous = newRoute.name ?? '';  
161 - } else if (value.previous.isNotEmpty) {  
162 - value.current = value.previous;  
163 - }  
164 -  
165 - value.args = previousRoute?.settings.arguments;  
166 value.route = previousRoute; 136 value.route = previousRoute;
167 - value.isBack = true;  
168 - value.removed = '';  
169 - value.isSnackbar = newRoute.isSnackbar;  
170 - value.isBottomSheet = newRoute.isBottomSheet;  
171 - value.isDialog = newRoute.isDialog; 137 + value.isBack = false;
  138 + value.removed = routeName ?? '';
  139 + value.previous = routeName ?? '';
  140 + // value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar;
  141 + value.isBottomSheet =
  142 + currentRoute.isBottomSheet ? false : value.isBottomSheet;
  143 + value.isDialog = currentRoute.isDialog ? false : value.isDialog;
172 }); 144 });
173 145
174 - // print('currentRoute.isDialog ${currentRoute.isDialog}');  
175 - 146 + if (route is GetPageRoute) {
  147 + RouterReportManager.reportRouteWillDispose(route);
  148 + }
176 routing?.call(_routeSend); 149 routing?.call(_routeSend);
177 } 150 }
178 151
@@ -201,7 +174,7 @@ class GetObserver extends NavigatorObserver { @@ -201,7 +174,7 @@ class GetObserver extends NavigatorObserver {
201 value.isBack = false; 174 value.isBack = false;
202 value.removed = ''; 175 value.removed = '';
203 value.previous = '$oldName'; 176 value.previous = '$oldName';
204 - value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar; 177 + // value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar;
205 value.isBottomSheet = 178 value.isBottomSheet =
206 currentRoute.isBottomSheet ? false : value.isBottomSheet; 179 currentRoute.isBottomSheet ? false : value.isBottomSheet;
207 value.isDialog = currentRoute.isDialog ? false : value.isDialog; 180 value.isDialog = currentRoute.isDialog ? false : value.isDialog;
@@ -212,29 +185,59 @@ class GetObserver extends NavigatorObserver { @@ -212,29 +185,59 @@ class GetObserver extends NavigatorObserver {
212 185
213 routing?.call(_routeSend); 186 routing?.call(_routeSend);
214 } 187 }
  188 +}
215 189
216 - @override  
217 - void didRemove(Route route, Route? previousRoute) {  
218 - super.didRemove(route, previousRoute);  
219 - final routeName = _extractRouteName(route);  
220 - final currentRoute = _RouteData.ofRoute(route);  
221 -  
222 - Get.log("REMOVING ROUTE $routeName"); 190 +class Routing {
  191 + String current;
  192 + String previous;
  193 + dynamic args;
  194 + String removed;
  195 + Route<dynamic>? route;
  196 + bool? isBack;
  197 + // bool? isSnackbar;
  198 + bool? isBottomSheet;
  199 + bool? isDialog;
223 200
224 - _routeSend?.update((value) {  
225 - value.route = previousRoute;  
226 - value.isBack = false;  
227 - value.removed = routeName ?? '';  
228 - value.previous = routeName ?? '';  
229 - value.isSnackbar = currentRoute.isSnackbar ? false : value.isSnackbar;  
230 - value.isBottomSheet =  
231 - currentRoute.isBottomSheet ? false : value.isBottomSheet;  
232 - value.isDialog = currentRoute.isDialog ? false : value.isDialog; 201 + Routing({
  202 + this.current = '',
  203 + this.previous = '',
  204 + this.args,
  205 + this.removed = '',
  206 + this.route,
  207 + this.isBack,
  208 + // this.isSnackbar,
  209 + this.isBottomSheet,
  210 + this.isDialog,
233 }); 211 });
234 212
235 - if (route is GetPageRoute) {  
236 - RouterReportManager.reportRouteWillDispose(route); 213 + void update(void fn(Routing value)) {
  214 + fn(this);
237 } 215 }
238 - routing?.call(_routeSend); 216 +}
  217 +
  218 +/// This is basically a util for rules about 'what a route is'
  219 +class _RouteData {
  220 + final bool isGetPageRoute;
  221 + //final bool isSnackbar;
  222 + final bool isBottomSheet;
  223 + final bool isDialog;
  224 + final String? name;
  225 +
  226 + _RouteData({
  227 + required this.name,
  228 + required this.isGetPageRoute,
  229 + // required this.isSnackbar,
  230 + required this.isBottomSheet,
  231 + required this.isDialog,
  232 + });
  233 +
  234 + factory _RouteData.ofRoute(Route? route) {
  235 + return _RouteData(
  236 + name: _extractRouteName(route),
  237 + isGetPageRoute: route is GetPageRoute,
  238 + // isSnackbar: route is SnackRoute,
  239 + isDialog: route is GetDialogRoute,
  240 + isBottomSheet: route is GetModalBottomSheetRoute,
  241 + );
239 } 242 }
240 } 243 }
1 import 'dart:async'; 1 import 'dart:async';
2 import 'dart:ui'; 2 import 'dart:ui';
  3 +
3 import 'package:flutter/material.dart'; 4 import 'package:flutter/material.dart';
4 import 'package:flutter/scheduler.dart'; 5 import 'package:flutter/scheduler.dart';
  6 +
5 import '../../../get_core/get_core.dart'; 7 import '../../../get_core/get_core.dart';
6 import '../../get_navigation.dart'; 8 import '../../get_navigation.dart';
7 9
8 -typedef SnackbarStatusCallback = void Function(SnackbarStatus? status);  
9 typedef OnTap = void Function(GetBar snack); 10 typedef OnTap = void Function(GetBar snack);
  11 +typedef SnackbarStatusCallback = void Function(SnackbarStatus? status);
10 12
11 class GetBar<T extends Object> extends StatefulWidget { 13 class GetBar<T extends Object> extends StatefulWidget {
12 - GetBar({  
13 - Key? key,  
14 - this.title,  
15 - this.message,  
16 - this.titleText,  
17 - this.messageText,  
18 - this.icon,  
19 - this.shouldIconPulse = true,  
20 - this.maxWidth,  
21 - this.margin = const EdgeInsets.all(0.0),  
22 - this.padding = const EdgeInsets.all(16),  
23 - this.borderRadius = 0.0,  
24 - this.borderColor,  
25 - this.borderWidth = 1.0,  
26 - this.backgroundColor = const Color(0xFF303030),  
27 - this.leftBarIndicatorColor,  
28 - this.boxShadows,  
29 - this.backgroundGradient,  
30 - this.mainButton,  
31 - this.onTap,  
32 - this.duration,  
33 - this.isDismissible = true,  
34 - this.dismissDirection = SnackDismissDirection.VERTICAL,  
35 - this.showProgressIndicator = false,  
36 - this.progressIndicatorController,  
37 - this.progressIndicatorBackgroundColor,  
38 - this.progressIndicatorValueColor,  
39 - this.snackPosition = SnackPosition.BOTTOM,  
40 - this.snackStyle = SnackStyle.FLOATING,  
41 - this.forwardAnimationCurve = Curves.easeOutCirc,  
42 - this.reverseAnimationCurve = Curves.easeOutCirc,  
43 - this.animationDuration = const Duration(seconds: 1),  
44 - this.barBlur = 0.0,  
45 - this.overlayBlur = 0.0,  
46 - this.overlayColor = Colors.transparent,  
47 - this.userInputForm,  
48 - SnackbarStatusCallback? snackbarStatus,  
49 - }) : snackbarStatus = (snackbarStatus ?? (status) {}),  
50 - super(key: key);  
51 -  
52 /// A callback for you to listen to the different Snack status 14 /// A callback for you to listen to the different Snack status
53 - final SnackbarStatusCallback snackbarStatus; 15 + final SnackbarStatusCallback? snackbarStatus;
54 16
55 /// The title displayed to the user 17 /// The title displayed to the user
56 final String? title; 18 final String? title;
@@ -192,18 +154,78 @@ class GetBar<T extends Object> extends StatefulWidget { @@ -192,18 +154,78 @@ class GetBar<T extends Object> extends StatefulWidget {
192 /// Every other widget is ignored if this is not null. 154 /// Every other widget is ignored if this is not null.
193 final Form? userInputForm; 155 final Form? userInputForm;
194 156
195 - /// Show the snack. It's call [SnackbarStatus.OPENING] state  
196 - /// followed by [SnackbarStatus.OPEN]  
197 - Future<T?>? show<T>() async {  
198 - return Get.showSnackbar(this);  
199 - } 157 + const GetBar({
  158 + Key? key,
  159 + this.title,
  160 + this.message,
  161 + this.titleText,
  162 + this.messageText,
  163 + this.icon,
  164 + this.shouldIconPulse = true,
  165 + this.maxWidth,
  166 + this.margin = const EdgeInsets.all(0.0),
  167 + this.padding = const EdgeInsets.all(16),
  168 + this.borderRadius = 0.0,
  169 + this.borderColor,
  170 + this.borderWidth = 1.0,
  171 + this.backgroundColor = const Color(0xFF303030),
  172 + this.leftBarIndicatorColor,
  173 + this.boxShadows,
  174 + this.backgroundGradient,
  175 + this.mainButton,
  176 + this.onTap,
  177 + this.duration,
  178 + this.isDismissible = true,
  179 + this.dismissDirection = SnackDismissDirection.VERTICAL,
  180 + this.showProgressIndicator = false,
  181 + this.progressIndicatorController,
  182 + this.progressIndicatorBackgroundColor,
  183 + this.progressIndicatorValueColor,
  184 + this.snackPosition = SnackPosition.BOTTOM,
  185 + this.snackStyle = SnackStyle.FLOATING,
  186 + this.forwardAnimationCurve = Curves.easeOutCirc,
  187 + this.reverseAnimationCurve = Curves.easeOutCirc,
  188 + this.animationDuration = const Duration(seconds: 1),
  189 + this.barBlur = 0.0,
  190 + this.overlayBlur = 0.0,
  191 + this.overlayColor = Colors.transparent,
  192 + this.userInputForm,
  193 + this.snackbarStatus,
  194 + }) : super(key: key);
200 195
201 @override 196 @override
202 State createState() { 197 State createState() {
203 return _GetBarState<T>(); 198 return _GetBarState<T>();
204 } 199 }
  200 +
  201 + /// Show the snack. It's call [SnackbarStatus.OPENING] state
  202 + /// followed by [SnackbarStatus.OPEN]
  203 + Future<void> show<T>() async {
  204 + return Get.showSnackbar(this);
  205 + }
205 } 206 }
206 207
  208 +/// Indicates Status of snackbar
  209 +/// [SnackbarStatus.OPEN] Snack is fully open, [SnackbarStatus.CLOSED] Snackbar
  210 +/// has closed,
  211 +/// [SnackbarStatus.OPENING] Starts with the opening animation and ends
  212 +/// with the full
  213 +/// snackbar display, [SnackbarStatus.CLOSING] Starts with the closing animation
  214 +/// and ends
  215 +/// with the full snackbar dispose
  216 +enum SnackbarStatus { OPEN, CLOSED, OPENING, CLOSING }
  217 +
  218 +/// Indicates the direction in which it is possible to dismiss
  219 +/// If vertical, dismiss up will be allowed if [SnackPosition.TOP]
  220 +/// If vertical, dismiss down will be allowed if [SnackPosition.BOTTOM]
  221 +enum SnackDismissDirection { HORIZONTAL, VERTICAL }
  222 +
  223 +/// Indicates if snack is going to start at the [TOP] or at the [BOTTOM]
  224 +enum SnackPosition { TOP, BOTTOM }
  225 +
  226 +/// Indicates if snack will be attached to the edge of the screen or not
  227 +enum SnackStyle { FLOATING, GROUNDED }
  228 +
207 class _GetBarState<K extends Object> extends State<GetBar> 229 class _GetBarState<K extends Object> extends State<GetBar>
208 with TickerProviderStateMixin { 230 with TickerProviderStateMixin {
209 SnackbarStatus? currentStatus; 231 SnackbarStatus? currentStatus;
@@ -223,6 +245,49 @@ class _GetBarState<K extends Object> extends State<GetBar> @@ -223,6 +245,49 @@ class _GetBarState<K extends Object> extends State<GetBar>
223 FocusScopeNode? _focusNode; 245 FocusScopeNode? _focusNode;
224 late FocusAttachment _focusAttachment; 246 late FocusAttachment _focusAttachment;
225 247
  248 + final Completer<Size> _boxHeightCompleter = Completer<Size>();
  249 +
  250 + late VoidCallback _progressListener;
  251 +
  252 + late CurvedAnimation _progressAnimation;
  253 +
  254 + GlobalKey backgroundBoxKey = GlobalKey();
  255 +
  256 + @override
  257 + Widget build(BuildContext context) {
  258 + return Align(
  259 + heightFactor: 1.0,
  260 + child: Material(
  261 + color: widget.snackStyle == SnackStyle.FLOATING
  262 + ? Colors.transparent
  263 + : widget.backgroundColor,
  264 + child: SafeArea(
  265 + minimum: widget.snackPosition == SnackPosition.BOTTOM
  266 + ? EdgeInsets.only(
  267 + bottom: MediaQuery.of(context).viewInsets.bottom)
  268 + : EdgeInsets.only(top: MediaQuery.of(context).padding.top),
  269 + bottom: widget.snackPosition == SnackPosition.BOTTOM,
  270 + top: widget.snackPosition == SnackPosition.TOP,
  271 + left: false,
  272 + right: false,
  273 + child: _getSnack(),
  274 + ),
  275 + ),
  276 + );
  277 + }
  278 +
  279 + @override
  280 + void dispose() {
  281 + _fadeController?.dispose();
  282 +
  283 + widget.progressIndicatorController?.removeListener(_progressListener);
  284 + widget.progressIndicatorController?.dispose();
  285 +
  286 + _focusAttachment.detach();
  287 + _focusNode!.dispose();
  288 + super.dispose();
  289 + }
  290 +
226 @override 291 @override
227 void initState() { 292 void initState() {
228 super.initState(); 293 super.initState();
@@ -250,19 +315,26 @@ Set either a message or messageText"""); @@ -250,19 +315,26 @@ Set either a message or messageText""");
250 _focusAttachment = _focusNode!.attach(context); 315 _focusAttachment = _focusNode!.attach(context);
251 } 316 }
252 317
253 - @override  
254 - void dispose() {  
255 - _fadeController?.dispose();  
256 -  
257 - widget.progressIndicatorController?.removeListener(_progressListener);  
258 - widget.progressIndicatorController?.dispose();  
259 -  
260 - _focusAttachment.detach();  
261 - _focusNode!.dispose();  
262 - super.dispose(); 318 + Widget _buildLeftBarIndicator() {
  319 + if (widget.leftBarIndicatorColor != null) {
  320 + return FutureBuilder<Size>(
  321 + future: _boxHeightCompleter.future,
  322 + builder: (buildContext, snapshot) {
  323 + if (snapshot.hasData) {
  324 + return Container(
  325 + color: widget.leftBarIndicatorColor,
  326 + width: 5.0,
  327 + height: snapshot.data!.height,
  328 + );
  329 + } else {
  330 + return _emptyWidget;
  331 + }
  332 + },
  333 + );
  334 + } else {
  335 + return _emptyWidget;
  336 + }
263 } 337 }
264 -  
265 - final Completer<Size> _boxHeightCompleter = Completer<Size>();  
266 338
267 void _configureLeftBarFuture() { 339 void _configureLeftBarFuture() {
268 SchedulerBinding.instance!.addPostFrameCallback( 340 SchedulerBinding.instance!.addPostFrameCallback(
@@ -277,6 +349,19 @@ Set either a message or messageText"""); @@ -277,6 +349,19 @@ Set either a message or messageText""");
277 ); 349 );
278 } 350 }
279 351
  352 + void _configureProgressIndicatorAnimation() {
  353 + if (widget.showProgressIndicator &&
  354 + widget.progressIndicatorController != null) {
  355 + _progressListener = () {
  356 + setState(() {});
  357 + };
  358 + widget.progressIndicatorController!.addListener(_progressListener);
  359 +
  360 + _progressAnimation = CurvedAnimation(
  361 + curve: Curves.linear, parent: widget.progressIndicatorController!);
  362 + }
  363 + }
  364 +
280 void _configurePulseAnimation() { 365 void _configurePulseAnimation() {
281 _fadeController = 366 _fadeController =
282 AnimationController(vsync: this, duration: _pulseAnimationDuration); 367 AnimationController(vsync: this, duration: _pulseAnimationDuration);
@@ -299,92 +384,6 @@ Set either a message or messageText"""); @@ -299,92 +384,6 @@ Set either a message or messageText""");
299 _fadeController!.forward(); 384 _fadeController!.forward();
300 } 385 }
301 386
302 - late VoidCallback _progressListener;  
303 -  
304 - void _configureProgressIndicatorAnimation() {  
305 - if (widget.showProgressIndicator &&  
306 - widget.progressIndicatorController != null) {  
307 - _progressListener = () {  
308 - setState(() {});  
309 - };  
310 - widget.progressIndicatorController!.addListener(_progressListener);  
311 -  
312 - _progressAnimation = CurvedAnimation(  
313 - curve: Curves.linear, parent: widget.progressIndicatorController!);  
314 - }  
315 - }  
316 -  
317 - @override  
318 - Widget build(BuildContext context) {  
319 - return Align(  
320 - heightFactor: 1.0,  
321 - child: Material(  
322 - color: widget.snackStyle == SnackStyle.FLOATING  
323 - ? Colors.transparent  
324 - : widget.backgroundColor,  
325 - child: SafeArea(  
326 - minimum: widget.snackPosition == SnackPosition.BOTTOM  
327 - ? EdgeInsets.only(  
328 - // bottom: (GetUtils.isGreaterThan(  
329 - // MediaQuery.of(context).viewInsets.bottom,  
330 - // MediaQuery.of(context).padding.bottom)  
331 - // ? MediaQuery.of(context).viewInsets.bottom  
332 - // : MediaQuery.of(context).padding.bottom))  
333 - bottom: MediaQuery.of(context).viewInsets.bottom)  
334 - : EdgeInsets.only(top: MediaQuery.of(context).padding.top),  
335 - bottom: widget.snackPosition == SnackPosition.BOTTOM,  
336 - top: widget.snackPosition == SnackPosition.TOP,  
337 - left: false,  
338 - right: false,  
339 - child: _getSnack(),  
340 - ),  
341 - ),  
342 - );  
343 - }  
344 -  
345 - Widget _getSnack() {  
346 - Widget snack;  
347 -  
348 - if (widget.userInputForm != null) {  
349 - snack = _generateInputSnack();  
350 - } else {  
351 - snack = _generateSnack();  
352 - }  
353 -  
354 - return Stack(  
355 - children: [  
356 - FutureBuilder<Size>(  
357 - future: _boxHeightCompleter.future,  
358 - builder: (context, snapshot) {  
359 - if (snapshot.hasData) {  
360 - if (widget.barBlur == 0) {  
361 - return _emptyWidget;  
362 - }  
363 - return ClipRRect(  
364 - borderRadius: BorderRadius.circular(widget.borderRadius),  
365 - child: BackdropFilter(  
366 - filter: ImageFilter.blur(  
367 - sigmaX: widget.barBlur!, sigmaY: widget.barBlur!),  
368 - child: Container(  
369 - height: snapshot.data!.height,  
370 - width: snapshot.data!.width,  
371 - decoration: BoxDecoration(  
372 - color: Colors.transparent,  
373 - borderRadius: BorderRadius.circular(widget.borderRadius),  
374 - ),  
375 - ),  
376 - ),  
377 - );  
378 - } else {  
379 - return _emptyWidget;  
380 - }  
381 - },  
382 - ),  
383 - snack,  
384 - ],  
385 - );  
386 - }  
387 -  
388 Widget _generateInputSnack() { 387 Widget _generateInputSnack() {
389 return Container( 388 return Container(
390 key: backgroundBoxKey, 389 key: backgroundBoxKey,
@@ -412,9 +411,6 @@ Set either a message or messageText"""); @@ -412,9 +411,6 @@ Set either a message or messageText""");
412 ); 411 );
413 } 412 }
414 413
415 - late CurvedAnimation _progressAnimation;  
416 - GlobalKey backgroundBoxKey = GlobalKey();  
417 -  
418 Widget _generateSnack() { 414 Widget _generateSnack() {
419 return Container( 415 return Container(
420 key: backgroundBoxKey, 416 key: backgroundBoxKey,
@@ -611,25 +607,11 @@ Set either a message or messageText"""); @@ -611,25 +607,11 @@ Set either a message or messageText""");
611 } 607 }
612 } 608 }
613 609
614 - Widget _buildLeftBarIndicator() {  
615 - if (widget.leftBarIndicatorColor != null) {  
616 - return FutureBuilder<Size>(  
617 - future: _boxHeightCompleter.future,  
618 - builder: (buildContext, snapshot) {  
619 - if (snapshot.hasData) {  
620 - return Container(  
621 - color: widget.leftBarIndicatorColor,  
622 - width: 5.0,  
623 - height: snapshot.data!.height,  
624 - );  
625 - } else {  
626 - return _emptyWidget;  
627 - }  
628 - }, 610 + Text _getDefaultNotificationText() {
  611 + return Text(
  612 + widget.message ?? "",
  613 + style: TextStyle(fontSize: 14.0, color: Colors.white),
629 ); 614 );
630 - } else {  
631 - return _emptyWidget;  
632 - }  
633 } 615 }
634 616
635 Widget? _getIcon() { 617 Widget? _getIcon() {
@@ -645,6 +627,53 @@ Set either a message or messageText"""); @@ -645,6 +627,53 @@ Set either a message or messageText""");
645 } 627 }
646 } 628 }
647 629
  630 + Widget? _getMainActionButton() {
  631 + return widget.mainButton;
  632 + }
  633 +
  634 + Widget _getSnack() {
  635 + Widget snack;
  636 +
  637 + if (widget.userInputForm != null) {
  638 + snack = _generateInputSnack();
  639 + } else {
  640 + snack = _generateSnack();
  641 + }
  642 +
  643 + return Stack(
  644 + children: [
  645 + FutureBuilder<Size>(
  646 + future: _boxHeightCompleter.future,
  647 + builder: (context, snapshot) {
  648 + if (snapshot.hasData) {
  649 + if (widget.barBlur == 0) {
  650 + return _emptyWidget;
  651 + }
  652 + return ClipRRect(
  653 + borderRadius: BorderRadius.circular(widget.borderRadius),
  654 + child: BackdropFilter(
  655 + filter: ImageFilter.blur(
  656 + sigmaX: widget.barBlur!, sigmaY: widget.barBlur!),
  657 + child: Container(
  658 + height: snapshot.data!.height,
  659 + width: snapshot.data!.width,
  660 + decoration: BoxDecoration(
  661 + color: Colors.transparent,
  662 + borderRadius: BorderRadius.circular(widget.borderRadius),
  663 + ),
  664 + ),
  665 + ),
  666 + );
  667 + } else {
  668 + return _emptyWidget;
  669 + }
  670 + },
  671 + ),
  672 + snack,
  673 + ],
  674 + );
  675 + }
  676 +
648 Widget _getTitleText() { 677 Widget _getTitleText() {
649 return widget.titleText ?? 678 return widget.titleText ??
650 Text( 679 Text(
@@ -653,36 +682,4 @@ Set either a message or messageText"""); @@ -653,36 +682,4 @@ Set either a message or messageText""");
653 fontSize: 16.0, color: Colors.white, fontWeight: FontWeight.bold), 682 fontSize: 16.0, color: Colors.white, fontWeight: FontWeight.bold),
654 ); 683 );
655 } 684 }
656 -  
657 - Text _getDefaultNotificationText() {  
658 - return Text(  
659 - widget.message ?? "",  
660 - style: TextStyle(fontSize: 14.0, color: Colors.white),  
661 - );  
662 - }  
663 -  
664 - Widget? _getMainActionButton() {  
665 - return widget.mainButton;  
666 - }  
667 } 685 }
668 -  
669 -/// Indicates if snack is going to start at the [TOP] or at the [BOTTOM]  
670 -enum SnackPosition { TOP, BOTTOM }  
671 -  
672 -/// Indicates if snack will be attached to the edge of the screen or not  
673 -enum SnackStyle { FLOATING, GROUNDED }  
674 -  
675 -/// Indicates the direction in which it is possible to dismiss  
676 -/// If vertical, dismiss up will be allowed if [SnackPosition.TOP]  
677 -/// If vertical, dismiss down will be allowed if [SnackPosition.BOTTOM]  
678 -enum SnackDismissDirection { HORIZONTAL, VERTICAL }  
679 -  
680 -/// Indicates Status of snackbar  
681 -/// [SnackbarStatus.OPEN] Snack is fully open, [SnackbarStatus.CLOSED] Snackbar  
682 -/// has closed,  
683 -/// [SnackbarStatus.OPENING] Starts with the opening animation and ends  
684 -/// with the full  
685 -/// snackbar display, [SnackbarStatus.CLOSING] Starts with the closing animation  
686 -/// and ends  
687 -/// with the full snackbar dispose  
688 -enum SnackbarStatus { OPEN, CLOSED, OPENING, CLOSING }  
1 -import 'dart:async';  
2 -import 'dart:ui';  
3 -import 'package:flutter/widgets.dart';  
4 -import '../../../get_core/get_core.dart';  
5 -import '../../get_navigation.dart';  
6 -import 'snack.dart';  
7 -  
8 -class SnackRoute<T> extends OverlayRoute<T> {  
9 - late Animation<double> _filterBlurAnimation;  
10 - late Animation<Color?> _filterColorAnimation;  
11 -  
12 - SnackRoute({  
13 - required this.snack,  
14 - RouteSettings? settings,  
15 - }) : super(settings: settings) {  
16 - _builder = Builder(builder: (_) {  
17 - return GestureDetector(  
18 - child: snack,  
19 - onTap: snack.onTap != null ? () => snack.onTap!(snack) : null,  
20 - );  
21 - });  
22 -  
23 - _configureAlignment(snack.snackPosition);  
24 - _snackbarStatus = snack.snackbarStatus;  
25 - }  
26 -  
27 - _configureAlignment(SnackPosition snackPosition) {  
28 - switch (snack.snackPosition) {  
29 - case SnackPosition.TOP:  
30 - {  
31 - _initialAlignment = Alignment(-1.0, -2.0);  
32 - _endAlignment = Alignment(-1.0, -1.0);  
33 - break;  
34 - }  
35 - case SnackPosition.BOTTOM:  
36 - {  
37 - _initialAlignment = Alignment(-1.0, 2.0);  
38 - _endAlignment = Alignment(-1.0, 1.0);  
39 - break;  
40 - }  
41 - }  
42 - }  
43 -  
44 - GetBar snack;  
45 - Builder? _builder;  
46 -  
47 - final Completer<T> _transitionCompleter = Completer<T>();  
48 -  
49 - late SnackbarStatusCallback _snackbarStatus;  
50 - Alignment? _initialAlignment;  
51 - Alignment? _endAlignment;  
52 - bool _wasDismissedBySwipe = false;  
53 - bool _onTappedDismiss = false;  
54 -  
55 - Timer? _timer;  
56 -  
57 - bool get opaque => false;  
58 -  
59 - @override  
60 - Iterable<OverlayEntry> createOverlayEntries() {  
61 - return <OverlayEntry>[  
62 - if (snack.overlayBlur > 0.0) ...[  
63 - OverlayEntry(  
64 - builder: (context) {  
65 - return GestureDetector(  
66 - onTap: () {  
67 - if (snack.isDismissible && !_onTappedDismiss) {  
68 - _onTappedDismiss = true;  
69 - Get.back();  
70 - }  
71 - },  
72 - child: AnimatedBuilder(  
73 - animation: _filterBlurAnimation,  
74 - builder: (context, child) {  
75 - return BackdropFilter(  
76 - filter: ImageFilter.blur(  
77 - sigmaX: _filterBlurAnimation.value,  
78 - sigmaY: _filterBlurAnimation.value),  
79 - child: Container(  
80 - constraints: BoxConstraints.expand(),  
81 - color: _filterColorAnimation.value,  
82 - ),  
83 - );  
84 - },  
85 - ),  
86 - );  
87 - },  
88 - maintainState: false,  
89 - opaque: opaque,  
90 - ),  
91 - ],  
92 - OverlayEntry(  
93 - builder: (context) {  
94 - final Widget annotatedChild = Semantics(  
95 - child: AlignTransition(  
96 - alignment: _animation!,  
97 - child: snack.isDismissible  
98 - ? _getDismissibleSnack(_builder)  
99 - : _getSnack(),  
100 - ),  
101 - focused: false,  
102 - container: true,  
103 - explicitChildNodes: true,  
104 - );  
105 - return annotatedChild;  
106 - },  
107 - maintainState: false,  
108 - opaque: opaque,  
109 - ),  
110 - ];  
111 - }  
112 -  
113 - String dismissibleKeyGen = "";  
114 -  
115 - Widget _getDismissibleSnack(Widget? child) {  
116 - return Dismissible(  
117 - direction: _getDismissDirection(),  
118 - resizeDuration: null,  
119 - confirmDismiss: (_) {  
120 - if (currentStatus == SnackbarStatus.OPENING ||  
121 - currentStatus == SnackbarStatus.CLOSING) {  
122 - return Future.value(false);  
123 - }  
124 - return Future.value(true);  
125 - },  
126 - key: Key(dismissibleKeyGen),  
127 - onDismissed: (_) {  
128 - dismissibleKeyGen += "1";  
129 - _cancelTimer();  
130 - _wasDismissedBySwipe = true;  
131 -  
132 - if (isCurrent) {  
133 - navigator!.pop();  
134 - } else {  
135 - navigator!.removeRoute(this);  
136 - }  
137 - },  
138 - child: _getSnack(),  
139 - );  
140 - }  
141 -  
142 - Widget _getSnack() {  
143 - return Container(  
144 - margin: snack.margin,  
145 - child: _builder,  
146 - );  
147 - }  
148 -  
149 - DismissDirection _getDismissDirection() {  
150 - if (snack.dismissDirection == SnackDismissDirection.HORIZONTAL) {  
151 - return DismissDirection.horizontal;  
152 - } else {  
153 - if (snack.snackPosition == SnackPosition.TOP) {  
154 - return DismissDirection.up;  
155 - }  
156 - return DismissDirection.down;  
157 - }  
158 - }  
159 -  
160 - @override  
161 - bool get finishedWhenPopped =>  
162 - _controller!.status == AnimationStatus.dismissed;  
163 -  
164 - /// The animation that drives the route's transition and the previous route's  
165 - /// forward transition.  
166 - Animation<Alignment>? _animation;  
167 -  
168 - /// The animation controller that the route uses to drive the transitions.  
169 - ///  
170 - /// The animation itself is exposed by the [animation] property.  
171 - AnimationController? _controller;  
172 -  
173 - /// Called to create the animation controller that will drive the transitions  
174 - /// to this route from the previous one, and back to the previous route  
175 - /// from this one.  
176 - AnimationController createAnimationController() {  
177 - assert(!_transitionCompleter.isCompleted,  
178 - 'Cannot reuse a $runtimeType after disposing it.');  
179 - assert(snack.animationDuration >= Duration.zero);  
180 - return AnimationController(  
181 - duration: snack.animationDuration,  
182 - debugLabel: debugLabel,  
183 - vsync: navigator!,  
184 - );  
185 - }  
186 -  
187 - /// Called to create the animation that exposes the current progress of  
188 - /// the transition controlled by the animation controller created by  
189 - /// `createAnimationController()`.  
190 - Animation<Alignment> createAnimation() {  
191 - assert(!_transitionCompleter.isCompleted,  
192 - 'Cannot reuse a $runtimeType after disposing it.');  
193 - assert(_controller != null);  
194 - return AlignmentTween(begin: _initialAlignment, end: _endAlignment).animate(  
195 - CurvedAnimation(  
196 - parent: _controller!,  
197 - curve: snack.forwardAnimationCurve,  
198 - reverseCurve: snack.reverseAnimationCurve,  
199 - ),  
200 - );  
201 - }  
202 -  
203 - Animation<double> createBlurFilterAnimation() {  
204 - return Tween(begin: 0.0, end: snack.overlayBlur).animate(  
205 - CurvedAnimation(  
206 - parent: _controller!,  
207 - curve: Interval(  
208 - 0.0,  
209 - 0.35,  
210 - curve: Curves.easeInOutCirc,  
211 - ),  
212 - ),  
213 - );  
214 - }  
215 -  
216 - Animation<Color?> createColorFilterAnimation() {  
217 - return ColorTween(begin: Color(0x00000000), end: snack.overlayColor)  
218 - .animate(  
219 - CurvedAnimation(  
220 - parent: _controller!,  
221 - curve: Interval(  
222 - 0.0,  
223 - 0.35,  
224 - curve: Curves.easeInOutCirc,  
225 - ),  
226 - ),  
227 - );  
228 - }  
229 -  
230 - T? _result;  
231 - SnackbarStatus? currentStatus;  
232 -  
233 - void _handleStatusChanged(AnimationStatus status) {  
234 - switch (status) {  
235 - case AnimationStatus.completed:  
236 - currentStatus = SnackbarStatus.OPEN;  
237 - _snackbarStatus(currentStatus);  
238 - if (overlayEntries.isNotEmpty) overlayEntries.first.opaque = opaque;  
239 -  
240 - break;  
241 - case AnimationStatus.forward:  
242 - currentStatus = SnackbarStatus.OPENING;  
243 - _snackbarStatus(currentStatus);  
244 - break;  
245 - case AnimationStatus.reverse:  
246 - currentStatus = SnackbarStatus.CLOSING;  
247 - _snackbarStatus(currentStatus);  
248 - if (overlayEntries.isNotEmpty) overlayEntries.first.opaque = false;  
249 - break;  
250 - case AnimationStatus.dismissed:  
251 - assert(!overlayEntries.first.opaque);  
252 - // We might still be the current route if a subclass is controlling the  
253 - // the transition and hits the dismissed status. For example, the iOS  
254 - // back gesture drives this animation to the dismissed status before  
255 - // popping the navigator.  
256 - currentStatus = SnackbarStatus.CLOSED;  
257 - _snackbarStatus(currentStatus);  
258 -  
259 - if (!isCurrent) {  
260 - navigator!.finalizeRoute(this);  
261 - // assert(overlayEntries.isEmpty);  
262 - }  
263 - break;  
264 - }  
265 - changedInternalState();  
266 - }  
267 -  
268 - @override  
269 - void install() {  
270 - assert(!_transitionCompleter.isCompleted,  
271 - 'Cannot install a $runtimeType after disposing it.');  
272 - _controller = createAnimationController();  
273 - assert(_controller != null,  
274 - '$runtimeType.createAnimationController() returned null.');  
275 - _filterBlurAnimation = createBlurFilterAnimation();  
276 - _filterColorAnimation = createColorFilterAnimation();  
277 - _animation = createAnimation();  
278 - assert(_animation != null, '$runtimeType.createAnimation() returned null.');  
279 - super.install();  
280 - }  
281 -  
282 - @override  
283 - TickerFuture didPush() {  
284 - super.didPush();  
285 - assert(  
286 - _controller != null,  
287 - // ignore: lines_longer_than_80_chars  
288 - '$runtimeType.didPush called before calling install() or after calling dispose().',  
289 - );  
290 - assert(  
291 - !_transitionCompleter.isCompleted,  
292 - 'Cannot reuse a $runtimeType after disposing it.',  
293 - );  
294 - _animation!.addStatusListener(_handleStatusChanged);  
295 - _configureTimer();  
296 - return _controller!.forward();  
297 - }  
298 -  
299 - @override  
300 - void didReplace(Route<dynamic>? oldRoute) {  
301 - assert(  
302 - _controller != null,  
303 - // ignore: lines_longer_than_80_chars  
304 - '$runtimeType.didReplace called before calling install() or after calling dispose().',  
305 - );  
306 - assert(  
307 - !_transitionCompleter.isCompleted,  
308 - 'Cannot reuse a $runtimeType after disposing it.',  
309 - );  
310 -  
311 - if (oldRoute is SnackRoute) {  
312 - _controller!.value = oldRoute._controller!.value;  
313 - }  
314 - _animation!.addStatusListener(_handleStatusChanged);  
315 - super.didReplace(oldRoute);  
316 - }  
317 -  
318 - @override  
319 - bool didPop(T? result) {  
320 - assert(  
321 - _controller != null,  
322 - // ignore: lines_longer_than_80_chars  
323 - '$runtimeType.didPop called before calling install() or after calling dispose().',  
324 - );  
325 - assert(  
326 - !_transitionCompleter.isCompleted,  
327 - 'Cannot reuse a $runtimeType after disposing it.',  
328 - );  
329 -  
330 - _result = result;  
331 - _cancelTimer();  
332 -  
333 - if (_wasDismissedBySwipe) {  
334 - Timer(Duration(milliseconds: 200), () {  
335 - _controller!.reset();  
336 - });  
337 -  
338 - _wasDismissedBySwipe = false;  
339 - } else {  
340 - _controller!.reverse();  
341 - }  
342 -  
343 - return super.didPop(result);  
344 - }  
345 -  
346 - void _configureTimer() {  
347 - if (snack.duration != null) {  
348 - if (_timer != null && _timer!.isActive) {  
349 - _timer!.cancel();  
350 - }  
351 - _timer = Timer(snack.duration!, () {  
352 - if (isCurrent) {  
353 - navigator!.pop();  
354 - } else if (isActive) {  
355 - navigator!.removeRoute(this);  
356 - }  
357 - });  
358 - } else {  
359 - if (_timer != null) {  
360 - _timer!.cancel();  
361 - }  
362 - }  
363 - }  
364 -  
365 - void _cancelTimer() {  
366 - if (_timer != null && _timer!.isActive) {  
367 - _timer!.cancel();  
368 - }  
369 - }  
370 -  
371 - /// Whether this route can perform a transition to the given route.  
372 - /// Subclasses can override this method to restrict the set of routes they  
373 - /// need to coordinate transitions with.  
374 - bool canTransitionTo(SnackRoute<dynamic> nextRoute) => true;  
375 -  
376 - /// Whether this route can perform a transition from the given route.  
377 - ///  
378 - /// Subclasses can override this method to restrict the set of routes they  
379 - /// need to coordinate transitions with.  
380 - bool canTransitionFrom(SnackRoute<dynamic> previousRoute) => true;  
381 -  
382 - @override  
383 - void dispose() {  
384 - assert(!_transitionCompleter.isCompleted,  
385 - 'Cannot dispose a $runtimeType twice.');  
386 - _controller?.dispose();  
387 - _transitionCompleter.complete(_result);  
388 - super.dispose();  
389 - }  
390 -  
391 - /// A short description of this route useful for debugging.  
392 - String get debugLabel => '$runtimeType';  
393 -}  
  1 +import 'dart:async';
  2 +import 'dart:ui';
  3 +
  4 +import 'package:flutter/material.dart';
  5 +
  6 +import '../../../get.dart';
  7 +
  8 +class SnackbarController {
  9 + late Animation<double> _filterBlurAnimation;
  10 + late Animation<Color?> _filterColorAnimation;
  11 + final GetBar<Object> snack;
  12 +
  13 + final Completer _transitionCompleter = Completer();
  14 + late SnackbarStatusCallback? _snackbarStatus;
  15 +
  16 + late final Alignment? _initialAlignment;
  17 + late final Alignment? _endAlignment;
  18 +
  19 + bool _wasDismissedBySwipe = false;
  20 + bool _onTappedDismiss = false;
  21 + Timer? _timer;
  22 +
  23 + /// The animation that drives the route's transition and the previous route's
  24 + /// forward transition.
  25 + late Animation<Alignment> _animation;
  26 +
  27 + /// The animation controller that the route uses to drive the transitions.
  28 + ///
  29 + /// The animation itself is exposed by the [animation] property.
  30 + late AnimationController _controller;
  31 +
  32 + SnackbarStatus? _currentStatus;
  33 +
  34 + final _overlayEntries = <OverlayEntry>[];
  35 +
  36 + OverlayState? _overlayState;
  37 +
  38 + SnackbarController(this.snack);
  39 +
  40 + Future get future => _transitionCompleter.future;
  41 +
  42 + bool get isSnackbarBeingShown => _currentStatus != SnackbarStatus.CLOSED;
  43 +
  44 + Animation<double> createBlurFilterAnimation() {
  45 + return Tween(begin: 0.0, end: snack.overlayBlur).animate(
  46 + CurvedAnimation(
  47 + parent: _controller,
  48 + curve: const Interval(
  49 + 0.0,
  50 + 0.35,
  51 + curve: Curves.easeInOutCirc,
  52 + ),
  53 + ),
  54 + );
  55 + }
  56 +
  57 + Animation<Color?> createColorOverlayColor() {
  58 + return ColorTween(begin: const Color(0x00000000), end: snack.overlayColor)
  59 + .animate(
  60 + CurvedAnimation(
  61 + parent: _controller,
  62 + curve: const Interval(
  63 + 0.0,
  64 + 0.35,
  65 + curve: Curves.easeInOutCirc,
  66 + ),
  67 + ),
  68 + );
  69 + }
  70 +
  71 + void removeEntry() {
  72 + assert(
  73 + !_transitionCompleter.isCompleted,
  74 + 'Cannot remove entry from a disposed snackbar',
  75 + );
  76 +
  77 + _cancelTimer();
  78 +
  79 + if (_wasDismissedBySwipe) {
  80 + Timer(const Duration(milliseconds: 200), () {
  81 + _controller.reset();
  82 + });
  83 +
  84 + _wasDismissedBySwipe = false;
  85 + } else {
  86 + _controller.reverse();
  87 + }
  88 + }
  89 +
  90 + void removeOverlay() {
  91 + for (var element in _overlayEntries) {
  92 + element.remove();
  93 + }
  94 +
  95 + assert(!_transitionCompleter.isCompleted, 'Cannot remove overlay twice.');
  96 + _controller.dispose();
  97 + _overlayEntries.clear();
  98 + _transitionCompleter.complete();
  99 + }
  100 +
  101 + Future<void> show() {
  102 + _configureOverlay();
  103 + return future;
  104 + }
  105 +
  106 + void _cancelTimer() {
  107 + if (_timer != null && _timer!.isActive) {
  108 + _timer!.cancel();
  109 + }
  110 + }
  111 +
  112 + void _configureAlignment(SnackPosition snackPosition) {
  113 + switch (snack.snackPosition) {
  114 + case SnackPosition.TOP:
  115 + {
  116 + _initialAlignment = const Alignment(-1.0, -2.0);
  117 + _endAlignment = const Alignment(-1.0, -1.0);
  118 + break;
  119 + }
  120 + case SnackPosition.BOTTOM:
  121 + {
  122 + _initialAlignment = const Alignment(-1.0, 2.0);
  123 + _endAlignment = const Alignment(-1.0, 1.0);
  124 + break;
  125 + }
  126 + }
  127 + }
  128 +
  129 + void _configureOverlay() {
  130 + _overlayState = Overlay.of(Get.overlayContext!);
  131 + _overlayEntries.clear();
  132 + _overlayEntries.addAll(_createOverlayEntries(_getBodyWidget()));
  133 + _overlayState!.insertAll(_overlayEntries);
  134 + _configureSnackBarDisplay();
  135 + }
  136 +
  137 + void _configureSnackBarDisplay() {
  138 + assert(!_transitionCompleter.isCompleted,
  139 + 'Cannot configure a snackbar after disposing it.');
  140 + _controller = _createAnimationController();
  141 +
  142 + _configureAlignment(snack.snackPosition);
  143 + _snackbarStatus = snack.snackbarStatus;
  144 +
  145 + _filterBlurAnimation = createBlurFilterAnimation();
  146 + _filterColorAnimation = createColorOverlayColor();
  147 + _animation = _createAnimation();
  148 + _animation.addStatusListener(_handleStatusChanged);
  149 + _configureTimer();
  150 + _controller.forward();
  151 + }
  152 +
  153 + void _configureTimer() {
  154 + if (snack.duration != null) {
  155 + if (_timer != null && _timer!.isActive) {
  156 + _timer!.cancel();
  157 + }
  158 + _timer = Timer(snack.duration!, removeEntry);
  159 + } else {
  160 + if (_timer != null) {
  161 + _timer!.cancel();
  162 + }
  163 + }
  164 + }
  165 +
  166 + /// Called to create the animation that exposes the current progress of
  167 + /// the transition controlled by the animation controller created by
  168 + /// `createAnimationController()`.
  169 + Animation<Alignment> _createAnimation() {
  170 + assert(!_transitionCompleter.isCompleted,
  171 + 'Cannot create a animation from a disposed snackbar');
  172 + return AlignmentTween(begin: _initialAlignment, end: _endAlignment).animate(
  173 + CurvedAnimation(
  174 + parent: _controller,
  175 + curve: snack.forwardAnimationCurve,
  176 + reverseCurve: snack.reverseAnimationCurve,
  177 + ),
  178 + );
  179 + }
  180 +
  181 + /// Called to create the animation controller that will drive the transitions
  182 + /// to this route from the previous one, and back to the previous route
  183 + /// from this one.
  184 + AnimationController _createAnimationController() {
  185 + assert(!_transitionCompleter.isCompleted,
  186 + 'Cannot create a animationController from a disposed snackbar');
  187 + assert(snack.animationDuration >= Duration.zero);
  188 + return AnimationController(
  189 + duration: snack.animationDuration,
  190 + debugLabel: '$runtimeType',
  191 + vsync: navigator!,
  192 + );
  193 + }
  194 +
  195 + Iterable<OverlayEntry> _createOverlayEntries(Widget child) {
  196 + return <OverlayEntry>[
  197 + if (snack.overlayBlur > 0.0) ...[
  198 + OverlayEntry(
  199 + builder: (context) => GestureDetector(
  200 + onTap: () {
  201 + if (snack.isDismissible && !_onTappedDismiss) {
  202 + _onTappedDismiss = true;
  203 + Get.back();
  204 + }
  205 + },
  206 + child: AnimatedBuilder(
  207 + animation: _filterBlurAnimation,
  208 + builder: (context, child) {
  209 + return BackdropFilter(
  210 + filter: ImageFilter.blur(
  211 + sigmaX: _filterBlurAnimation.value,
  212 + sigmaY: _filterBlurAnimation.value),
  213 + child: Container(
  214 + constraints: const BoxConstraints.expand(),
  215 + color: _filterColorAnimation.value,
  216 + ),
  217 + );
  218 + },
  219 + ),
  220 + ),
  221 + maintainState: false,
  222 + opaque: false,
  223 + ),
  224 + ],
  225 + OverlayEntry(
  226 + builder: (context) => Semantics(
  227 + child: AlignTransition(
  228 + alignment: _animation,
  229 + child: snack.isDismissible
  230 + ? _getDismissibleSnack(child)
  231 + : _getSnackbarContainer(child),
  232 + ),
  233 + focused: false,
  234 + container: true,
  235 + explicitChildNodes: true,
  236 + ),
  237 + maintainState: false,
  238 + opaque: false,
  239 + ),
  240 + ];
  241 + }
  242 +
  243 + Widget _getBodyWidget() {
  244 + return Builder(builder: (_) {
  245 + return GestureDetector(
  246 + child: snack,
  247 + onTap: snack.onTap != null ? () => snack.onTap?.call(snack) : null,
  248 + );
  249 + });
  250 + }
  251 +
  252 + DismissDirection _getDismissDirection() {
  253 + if (snack.dismissDirection == SnackDismissDirection.HORIZONTAL) {
  254 + return DismissDirection.horizontal;
  255 + } else {
  256 + if (snack.snackPosition == SnackPosition.TOP) {
  257 + return DismissDirection.up;
  258 + }
  259 + return DismissDirection.down;
  260 + }
  261 + }
  262 +
  263 + Widget _getDismissibleSnack(Widget child) {
  264 + return Dismissible(
  265 + direction: _getDismissDirection(),
  266 + resizeDuration: null,
  267 + confirmDismiss: (_) {
  268 + if (_currentStatus == SnackbarStatus.OPENING ||
  269 + _currentStatus == SnackbarStatus.CLOSING) {
  270 + return Future.value(false);
  271 + }
  272 + return Future.value(true);
  273 + },
  274 + key: const Key('dismissible'),
  275 + onDismissed: (_) {
  276 + _cancelTimer();
  277 + _wasDismissedBySwipe = true;
  278 + removeEntry();
  279 + },
  280 + child: _getSnackbarContainer(child),
  281 + );
  282 + }
  283 +
  284 + Widget _getSnackbarContainer(Widget child) {
  285 + return Container(
  286 + margin: snack.margin,
  287 + child: child,
  288 + );
  289 + }
  290 +
  291 + void _handleStatusChanged(AnimationStatus status) {
  292 + switch (status) {
  293 + case AnimationStatus.completed:
  294 + _currentStatus = SnackbarStatus.OPEN;
  295 + _snackbarStatus?.call(_currentStatus);
  296 + if (_overlayEntries.isNotEmpty) _overlayEntries.first.opaque = false;
  297 +
  298 + break;
  299 + case AnimationStatus.forward:
  300 + _currentStatus = SnackbarStatus.OPENING;
  301 + _snackbarStatus?.call(_currentStatus);
  302 + break;
  303 + case AnimationStatus.reverse:
  304 + _currentStatus = SnackbarStatus.CLOSING;
  305 + _snackbarStatus?.call(_currentStatus);
  306 + if (_overlayEntries.isNotEmpty) _overlayEntries.first.opaque = false;
  307 + break;
  308 + case AnimationStatus.dismissed:
  309 + assert(!_overlayEntries.first.opaque);
  310 + _currentStatus = SnackbarStatus.CLOSED;
  311 + _snackbarStatus?.call(_currentStatus);
  312 + removeOverlay();
  313 + break;
  314 + }
  315 + }
  316 +}