Jonatas

upgrade to 3.4.1

Showing 53 changed files with 1244 additions and 1387 deletions
## [3.4.1]
- Structure organization, and improvements.
## [3.4.0]
- Added '[everAll]' Worker: Listen a List of '.obx'
- Added Workers dispose
... ...
library get;
export 'instance_manager.dart';
export 'route_manager.dart';
export 'state_manager.dart';
export 'utils.dart';
export 'src/instance/instance_manager.dart';
export 'src/navigation/route_manager.dart';
export 'src/state_manager/state_manager.dart';
export 'src/utils/utils.dart';
... ...
export 'src/instance/get_instance.dart';
export 'src/instance/extension_instance.dart';
export 'src/typedefs/typedefs.dart';
export 'src/routes/bindings_interface.dart';
export 'src/routes/custom_transition.dart';
export 'src/routes/transitions_type.dart';
export 'src/routes/get_route.dart';
export 'src/routes/default_route.dart';
export 'src/routes/observers/route_observer.dart';
export 'src/root/root_widget.dart';
export 'src/snackbar/snack_route.dart';
export 'src/bottomsheet/bottomsheet.dart';
export 'src/snackbar/snack.dart';
export 'src/get_main.dart';
export 'src/routes/default_route.dart';
export 'src/root/smart_management.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import 'root/root_controller.dart';
import 'routes/bindings_interface.dart';
import 'routes/transitions_type.dart';
import 'snackbar/snack.dart';
import 'navigation/root/parse_route.dart';
import 'navigation/root/root_controller.dart';
import 'navigation/routes/custom_transition.dart';
import 'navigation/routes/observers/route_observer.dart';
import 'navigation/routes/transitions_type.dart';
import 'utils/utils.dart';
///Use Get.to instead of Navigator.push, Get.off instead of Navigator.pushReplacement,
///Get.offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named"
... ... @@ -12,289 +12,31 @@ import 'snackbar/snack.dart';
///To return to the previous screen, use Get.back().
///No need to pass any context to Get, just put the name of the route inside
///the parentheses and the magic will occur.
///
abstract class GetService {
/// It replaces Navigator.push, but needs no context, and it doesn't have the Navigator.push
/// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
/// of rebuilding every app after a route, use opaque = true as the parameter.
Future<T> to<T>(Widget page,
{bool opaque,
Transition transition,
Duration duration,
int id,
bool fullscreenDialog = false,
Object arguments,
Bindings binding,
bool popGesture});
abstract class GetInterface {
bool defaultPopGesture = GetPlatform.isIOS;
bool defaultOpaqueRoute = true;
Transition defaultTransition;
Duration defaultDurationTransition = Duration(milliseconds: 400);
bool defaultGlobalState = true;
RouteSettings settings;
String defaultSeparator = "_";
/// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed
/// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
/// of rebuilding every app after a route, use opaque = true as the parameter.
Future<T> toNamed<T>(String page, {Object arguments, int id});
final routing = Routing();
/// It replaces Navigator.pushReplacementNamed, but needs no context.
Future<T> offNamed<T>(String page, {Object arguments, int id});
Map<String, String> parameters = {};
/// It replaces Navigator.popUntil, but needs no context.
void until(RoutePredicate predicate, {int id});
ParseRouteTree routeTree;
/// It replaces Navigator.pushAndRemoveUntil, but needs no context.
Future<T> offUntil<T>(Route<T> page, RoutePredicate predicate, {int id});
CustomTransition customTransition;
/// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context.
Future<T> offNamedUntil<T>(String page, RoutePredicate predicate,
{int id, Object arguments});
GetMaterialController getxController = GetMaterialController();
/// It replaces Navigator.popAndPushNamed, but needs no context.
Future<T> offAndToNamed<T>(String page,
{Object arguments, int id, dynamic result});
Locale locale;
/// It replaces Navigator.removeRoute, but needs no context.
void removeRoute(Route<dynamic> route, {int id});
GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
/// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context.
Future<T> offAllNamed<T>(String newRouteName,
{RoutePredicate predicate, Object arguments, int id});
Map<int, GlobalKey<NavigatorState>> keys = {};
bool get isOverlaysOpen;
bool get isOverlaysClosed;
/// It replaces Navigator.pop, but needs no context.
void back({dynamic result, bool closeOverlays = false, int id});
/// It will close as many screens as you define. Times must be> 0;
void close(int times, [int id]);
/// It replaces Navigator.pushReplacement, but needs no context, and it doesn't have the Navigator.pushReplacement
/// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
/// of rebuilding every app after a route, use opaque = true as the parameter.
Future<T> off<T>(Widget page,
{bool opaque = false,
Transition transition,
bool popGesture,
int id,
Object arguments,
Bindings binding,
bool fullscreenDialog = false,
Duration duration});
/// It replaces Navigator.pushAndRemoveUntil, but needs no context
Future<T> offAll<T>(Widget page,
{RoutePredicate predicate,
bool opaque = false,
bool popGesture,
int id,
Object arguments,
Bindings binding,
bool fullscreenDialog = false,
Transition transition});
/// Show a dialog
Future<T> dialog<T>(
Widget child, {
bool barrierDismissible = true,
bool useRootNavigator = true,
// RouteSettings routeSettings
});
/// Api from showGeneralDialog with no context
Future<T> generalDialog<T>({
@required RoutePageBuilder pageBuilder,
String barrierLabel = "Dismiss",
bool barrierDismissible = true,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
bool useRootNavigator = true,
RouteSettings routeSettings,
});
Future<T> defaultDialog<T>({
String title = "Alert",
Widget content,
VoidCallback onConfirm,
VoidCallback onCancel,
VoidCallback onCustom,
Color cancelTextColor,
Color confirmTextColor,
String textConfirm,
String textCancel,
String textCustom,
Widget confirm,
Widget cancel,
Widget custom,
Color backgroundColor,
Color buttonColor,
String middleText = "Dialog made in 3 lines of code",
double radius = 20.0,
List<Widget> actions,
});
Future<T> bottomSheet<T>(
Widget bottomsheet, {
Color backgroundColor,
double elevation,
ShapeBorder shape,
Clip clipBehavior,
Color barrierColor,
bool ignoreSafeArea,
bool isScrollControlled = false,
bool useRootNavigator = false,
bool isDismissible = true,
bool enableDrag = true,
});
void rawSnackbar(
{String title,
String message,
Widget titleText,
Widget messageText,
Widget icon,
bool instantInit = true,
bool shouldIconPulse = true,
double maxWidth,
EdgeInsets margin = const EdgeInsets.all(0.0),
EdgeInsets padding = const EdgeInsets.all(16),
double borderRadius = 0.0,
Color borderColor,
double borderWidth = 1.0,
Color backgroundColor = const Color(0xFF303030),
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
Duration duration = const Duration(seconds: 3),
bool isDismissible = true,
SnackDismissDirection dismissDirection = SnackDismissDirection.VERTICAL,
bool showProgressIndicator = false,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackPosition snackPosition = SnackPosition.BOTTOM,
SnackStyle snackStyle = SnackStyle.FLOATING,
Curve forwardAnimationCurve = Curves.easeOutCirc,
Curve reverseAnimationCurve = Curves.easeOutCirc,
Duration animationDuration = const Duration(seconds: 1),
SnackStatusCallback onStatusChanged,
double barBlur = 0.0,
double overlayBlur = 0.0,
Color overlayColor = Colors.transparent,
Form userInputForm});
void snackbar(String title, String message,
{Color colorText,
Duration duration,
/// with instantInit = false you can put Get.snackbar on initState
bool instantInit = true,
SnackPosition snackPosition,
Widget titleText,
Widget messageText,
Widget icon,
bool shouldIconPulse,
double maxWidth,
EdgeInsets margin,
EdgeInsets padding,
double borderRadius,
Color borderColor,
double borderWidth,
Color backgroundColor,
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
bool isDismissible,
bool showProgressIndicator,
SnackDismissDirection dismissDirection,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackStyle snackStyle,
Curve forwardAnimationCurve,
Curve reverseAnimationCurve,
Duration animationDuration,
double barBlur,
double overlayBlur,
Color overlayColor,
Form userInputForm});
/// INSTANCE MANAGER
GetMaterialController getxController;
void changeTheme(ThemeData theme);
void changeThemeMode(ThemeMode themeMode);
GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey);
GlobalKey<NavigatorState> key;
GlobalKey<NavigatorState> nestedKey(int key);
GlobalKey<NavigatorState> global(int k);
//////////// INSTANCE MANAGER
// setParameter(Map<String, String> param);
/// give current arguments
Object get arguments;
/// give current arguments
Map<String, String> get parameters;
/// give name from current route
String get currentRoute;
/// give name from previous route
String get previousRoute;
/// check if snackbar is open
bool get isSnackbarOpen;
/// check if dialog is open
bool get isDialogOpen;
/// check if bottomsheet is open
bool get isBottomSheetOpen;
/// check a raw current route
Route<dynamic> get rawRoute;
/// give access to currentContext
BuildContext get context;
/// give access to current Overlay Context
BuildContext get overlayContext;
/// give access to Theme.of(context)
ThemeData get theme;
/// give access to TextTheme.of(context)
TextTheme get textTheme;
/// give access to Mediaquery.of(context)
MediaQueryData get mediaQuery;
/// Check if dark mode theme is enable
bool get isDarkMode;
/// Check if dark mode theme is enable on platform on android Q+
bool get isPlatformDarkMode;
/// give access to Theme.of(context).iconTheme.color
Color get iconColor;
/// give access to Focus.of(context).iconTheme.color
FocusNode get focusScope;
/// give access to MediaQuery.of(context).size.height
double get height;
/// give access to MediaQuery.of(context).size.width
double get width;
Map<String, Map<String, String>> translations = {};
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/get_interface.dart';
import 'bottomsheet/bottomsheet.dart';
import 'instance/get_instance.dart';
import 'platform/platform.dart';
import 'root/parse_route.dart';
import 'root/root_controller.dart';
import 'routes/bindings_interface.dart';
import 'routes/default_route.dart';
import 'routes/observers/route_observer.dart';
import 'routes/transitions_type.dart';
import 'snackbar/snack.dart';
///Use to instead of Navigator.push, off instead of Navigator.pushReplacement,
///offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named"
... ... @@ -20,933 +6,7 @@ import 'snackbar/snack.dart';
///To return to the previous screen, use back().
///No need to pass any context to Get, just put the name of the route inside
///the parentheses and the magic will occur.
class GetImpl implements GetService {
bool defaultPopGesture = GetPlatform.isIOS;
bool defaultOpaqueRoute = true;
Transition defaultTransition;
Duration defaultDurationTransition = Duration(milliseconds: 400);
bool defaultGlobalState = true;
RouteSettings settings;
String defaultSeparator = "_";
/// Pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> to<T>(
Widget page, {
bool opaque,
Transition transition,
Duration duration,
int id,
bool fullscreenDialog = false,
Object arguments,
Bindings binding,
preventDuplicates = true,
bool popGesture,
}) {
if (preventDuplicates && '/${page.runtimeType}' == currentRoute) {
return null;
}
return global(id).currentState.push(
GetPageRoute(
opaque: opaque ?? true,
page: () => page,
settings: RouteSettings(
name: '/${page.runtimeType}',
arguments: arguments,
),
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
fullscreenDialog: fullscreenDialog,
binding: binding,
transitionDuration: duration ?? defaultDurationTransition,
),
);
}
/// Pushes a new named [page] to the stack
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> toNamed<T>(
String page, {
Object arguments,
int id,
preventDuplicates = true,
}) {
if (preventDuplicates && page == currentRoute) {
return null;
}
return global(id).currentState.pushNamed(page, arguments: arguments);
}
/// Pop the current named [page] in the stack and push a new one in its place
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> offNamed<T>(
String page, {
Object arguments,
int id,
preventDuplicates = true,
}) {
if (preventDuplicates && page == currentRoute) {
return null;
}
return global(id)
.currentState
.pushReplacementNamed(page, arguments: arguments);
}
/// Calls pop several times in the stack until [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
void until(RoutePredicate predicate, {int id}) {
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return global(id).currentState.popUntil(predicate);
}
/// Push the given [page], and then pop several [pages] in the stack until
/// [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
Future<T> offUntil<T>(Route<T> page, RoutePredicate predicate, {int id}) {
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return global(id).currentState.pushAndRemoveUntil(page, predicate);
}
/// Push the given named [page], and then pop several pages in the stack
/// until [predicate] returns true
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> offNamedUntil<T>(
String page,
RoutePredicate predicate, {
int id,
Object arguments,
}) {
return global(id)
.currentState
.pushNamedAndRemoveUntil(page, predicate, arguments: arguments);
}
/// Pop the current named page and pushes a new [page] to the stack in its place
///
/// You can send any type of value to the other route in the [arguments].
/// It is very similar to `offNamed()` but use a different approach
///
/// The `offNamed()` pop a page, and goes to the next. The `offAndToNamed()` goes
/// to the next page, and removes the previous one. The route transition
/// animation is different.
Future<T> offAndToNamed<T>(String page,
{Object arguments, int id, dynamic result}) {
return global(id)
.currentState
.popAndPushNamed(page, arguments: arguments, result: result);
}
/// Remove a specific [route] from the stack
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void removeRoute(Route<dynamic> route, {int id}) {
return global(id).currentState.removeRoute(route);
}
/// Push a named [page] and remove all other pages from stack
///
/// It has the advantage of not needing context, so you can
/// call from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors
Future<T> offAllNamed<T>(String newRouteName,
{RoutePredicate predicate, Object arguments, int id}) {
var route = (Route<dynamic> rota) => false;
return global(id).currentState.pushNamedAndRemoveUntil(
newRouteName, predicate ?? route,
arguments: arguments);
}
/// Returns true if a snackbar, dialog or bottomsheet is currently showing in the screen
bool get isOverlaysOpen =>
(isSnackbarOpen || isDialogOpen || isBottomSheetOpen);
/// returns true if there is no snackbar, dialog or bottomsheet open
bool get isOverlaysClosed =>
(!isSnackbarOpen && !isDialogOpen && !isBottomSheetOpen);
/// Pop the current page, snackbar, dialog or bottomsheet in the stack
///
/// if your set [closeOverlays] to true, Get.back() will close the currently open
/// snackbar/dialog/bottomsheet AND the current page
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
void back({
dynamic result,
bool closeOverlays = false,
bool canPop = true,
int id,
}) {
if (closeOverlays && isOverlaysOpen) {
navigator.popUntil((route) {
return (isOverlaysClosed);
});
}
if (canPop) {
if (global(id).currentState.canPop()) {
global(id).currentState.pop(result);
}
} else {
global(id).currentState.pop(result);
}
}
/// Close as many routes as defined by [times]
void close(int times, [int id]) {
if ((times == null) || (times < 1)) {
times = 1;
}
int count = 0;
void back = global(id).currentState.popUntil((route) {
return count++ == times;
});
return back;
}
/// Pop the current page and pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> off<T>(
Widget page, {
bool opaque = false,
Transition transition,
bool popGesture,
int id,
Object arguments,
Bindings binding,
bool fullscreenDialog = false,
preventDuplicates = true,
Duration duration,
}) {
if (preventDuplicates && '/${page.runtimeType}' == currentRoute) {
return null;
}
return global(id).currentState.pushReplacement(GetPageRoute(
opaque: opaque ?? true,
page: () => page,
binding: binding,
settings:
RouteSettings(name: '/${page.runtimeType}', arguments: arguments),
fullscreenDialog: fullscreenDialog,
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
transitionDuration: duration ?? defaultDurationTransition));
}
/// Pop all pages in the stack and pushes a new [page] to it
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> offAll<T>(
Widget page, {
RoutePredicate predicate,
bool opaque = false,
bool popGesture,
int id,
Object arguments,
Bindings binding,
bool fullscreenDialog = false,
Duration duration,
Transition transition,
}) {
var route = (Route<dynamic> rota) => false;
return global(id).currentState.pushAndRemoveUntil(
GetPageRoute(
opaque: opaque ?? true,
popGesture: popGesture ?? defaultPopGesture,
page: () => page,
binding: binding,
settings:
RouteSettings(name: '/${page.runtimeType}', arguments: arguments),
fullscreenDialog: fullscreenDialog,
transition: transition ?? defaultTransition,
transitionDuration: duration ?? defaultDurationTransition,
),
predicate ?? route);
}
/// Show a dialog
Future<T> dialog<T>(
Widget child, {
bool barrierDismissible = true,
bool useRootNavigator = true,
// RouteSettings routeSettings
}) {
return showDialog(
barrierDismissible: barrierDismissible,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: 'dialog'),
context: overlayContext,
builder: (_) {
return child;
},
);
}
/// Api from showGeneralDialog with no context
Future<T> generalDialog<T>({
@required RoutePageBuilder pageBuilder,
String barrierLabel = "Dismiss",
bool barrierDismissible = true,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
bool useRootNavigator = true,
RouteSettings routeSettings,
}) {
return showGeneralDialog(
pageBuilder: pageBuilder,
barrierDismissible: barrierDismissible,
barrierLabel: barrierLabel,
barrierColor: barrierColor,
transitionDuration: transitionDuration,
transitionBuilder: transitionBuilder,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: 'dialog'),
context: overlayContext,
);
}
Future<T> defaultDialog<T>({
String title = "Alert",
Widget content,
VoidCallback onConfirm,
VoidCallback onCancel,
VoidCallback onCustom,
Color cancelTextColor,
Color confirmTextColor,
String textConfirm,
String textCancel,
String textCustom,
Widget confirm,
Widget cancel,
Widget custom,
Color backgroundColor,
Color buttonColor,
String middleText = "Dialog made in 3 lines of code",
double radius = 20.0,
List<Widget> actions,
}) {
bool leanCancel = onCancel != null || textCancel != null;
bool leanConfirm = onConfirm != null || textConfirm != null;
actions ??= [];
if (cancel != null) {
actions.add(cancel);
} else {
if (leanCancel) {
actions.add(FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onPressed: () {
onCancel?.call();
back();
},
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8),
child: Text(
textCancel ?? "Cancel",
style: TextStyle(color: cancelTextColor ?? theme.accentColor),
),
shape: RoundedRectangleBorder(
side: BorderSide(
color: buttonColor ?? theme.accentColor,
width: 2,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(100)),
));
}
}
if (confirm != null) {
actions.add(confirm);
} else {
if (leanConfirm) {
actions.add(FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
color: buttonColor ?? theme.accentColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100)),
child: Text(
textConfirm ?? "Ok",
style: TextStyle(color: confirmTextColor ?? theme.primaryColor),
),
onPressed: () {
onConfirm?.call();
}));
}
}
return dialog(AlertDialog(
titlePadding: EdgeInsets.all(8),
contentPadding: EdgeInsets.all(8),
backgroundColor: backgroundColor ?? theme.dialogBackgroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(radius))),
title: Text(title, textAlign: TextAlign.center),
content: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
content ?? Text(middleText ?? "", textAlign: TextAlign.center),
SizedBox(height: 16),
ButtonTheme(
minWidth: 78.0,
height: 34.0,
child: Wrap(
alignment: WrapAlignment.center,
spacing: 8,
runSpacing: 8,
children: actions,
),
)
],
),
// actions: actions, // ?? <Widget>[cancelButton, confirmButton],
buttonPadding: EdgeInsets.zero,
));
}
Future<T> bottomSheet<T>(
Widget bottomsheet, {
Color backgroundColor,
double elevation,
ShapeBorder shape,
Clip clipBehavior,
Color barrierColor,
bool ignoreSafeArea,
bool isScrollControlled = false,
bool useRootNavigator = false,
bool isDismissible = true,
bool enableDrag = true,
}) {
assert(bottomsheet != null);
assert(isScrollControlled != null);
assert(useRootNavigator != null);
assert(isDismissible != null);
assert(enableDrag != null);
return Navigator.of(overlayContext, rootNavigator: useRootNavigator)
.push(GetModalBottomSheetRoute<T>(
builder: (_) => bottomsheet,
theme: Theme.of(key.currentContext, shadowThemeOnly: true),
isScrollControlled: isScrollControlled,
barrierLabel:
MaterialLocalizations.of(key.currentContext).modalBarrierDismissLabel,
backgroundColor: backgroundColor ?? Colors.transparent,
elevation: elevation,
shape: shape,
removeTop: ignoreSafeArea ?? true,
clipBehavior: clipBehavior,
isDismissible: isDismissible,
modalBarrierColor: barrierColor,
settings: RouteSettings(name: "bottomsheet"),
enableDrag: enableDrag,
));
}
void rawSnackbar(
{String title,
String message,
Widget titleText,
Widget messageText,
Widget icon,
bool instantInit = true,
bool shouldIconPulse = true,
double maxWidth,
EdgeInsets margin = const EdgeInsets.all(0.0),
EdgeInsets padding = const EdgeInsets.all(16),
double borderRadius = 0.0,
Color borderColor,
double borderWidth = 1.0,
Color backgroundColor = const Color(0xFF303030),
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
Duration duration = const Duration(seconds: 3),
bool isDismissible = true,
SnackDismissDirection dismissDirection = SnackDismissDirection.VERTICAL,
bool showProgressIndicator = false,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackPosition snackPosition = SnackPosition.BOTTOM,
SnackStyle snackStyle = SnackStyle.FLOATING,
Curve forwardAnimationCurve = Curves.easeOutCirc,
Curve reverseAnimationCurve = Curves.easeOutCirc,
Duration animationDuration = const Duration(seconds: 1),
SnackStatusCallback onStatusChanged,
double barBlur = 0.0,
double overlayBlur = 0.0,
Color overlayColor = Colors.transparent,
Form userInputForm}) {
GetBar getBar = GetBar(
title: title,
message: message,
titleText: titleText,
messageText: messageText,
snackPosition: snackPosition,
borderRadius: borderRadius,
margin: margin,
duration: duration,
barBlur: barBlur,
backgroundColor: backgroundColor,
icon: icon,
shouldIconPulse: shouldIconPulse,
maxWidth: maxWidth,
padding: padding,
borderColor: borderColor,
borderWidth: borderWidth,
leftBarIndicatorColor: leftBarIndicatorColor,
boxShadows: boxShadows,
backgroundGradient: backgroundGradient,
mainButton: mainButton,
onTap: onTap,
isDismissible: isDismissible,
dismissDirection: dismissDirection,
showProgressIndicator: showProgressIndicator ?? false,
progressIndicatorController: progressIndicatorController,
progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
progressIndicatorValueColor: progressIndicatorValueColor,
snackStyle: snackStyle,
forwardAnimationCurve: forwardAnimationCurve,
reverseAnimationCurve: reverseAnimationCurve,
animationDuration: animationDuration,
overlayBlur: overlayBlur,
overlayColor: overlayColor,
userInputForm: userInputForm);
if (instantInit) {
getBar.show();
} else {
SchedulerBinding.instance.addPostFrameCallback((_) {
getBar.show();
});
}
}
void snackbar(String title, String message,
{Color colorText,
Duration duration,
/// with instantInit = false you can put snackbar on initState
bool instantInit = true,
SnackPosition snackPosition,
Widget titleText,
Widget messageText,
Widget icon,
bool shouldIconPulse,
double maxWidth,
EdgeInsets margin,
EdgeInsets padding,
double borderRadius,
Color borderColor,
double borderWidth,
Color backgroundColor,
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
bool isDismissible,
bool showProgressIndicator,
SnackDismissDirection dismissDirection,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackStyle snackStyle,
Curve forwardAnimationCurve,
Curve reverseAnimationCurve,
Duration animationDuration,
double barBlur,
double overlayBlur,
Color overlayColor,
Form userInputForm}) {
GetBar getBar = GetBar(
titleText: (title == null)
? null
: titleText ??
Text(
title,
style: TextStyle(
color: colorText ?? theme.iconTheme.color,
fontWeight: FontWeight.w800,
fontSize: 16),
),
messageText: messageText ??
Text(
message,
style: TextStyle(
color: colorText ?? theme.iconTheme.color,
fontWeight: FontWeight.w300,
fontSize: 14),
),
snackPosition: snackPosition ?? SnackPosition.TOP,
borderRadius: borderRadius ?? 15,
margin: margin ?? EdgeInsets.symmetric(horizontal: 10),
duration: duration ?? Duration(seconds: 3),
barBlur: barBlur ?? 7.0,
backgroundColor: backgroundColor ?? Colors.grey.withOpacity(0.2),
icon: icon,
shouldIconPulse: shouldIconPulse ?? true,
maxWidth: maxWidth,
padding: padding ?? EdgeInsets.all(16),
borderColor: borderColor,
borderWidth: borderWidth,
leftBarIndicatorColor: leftBarIndicatorColor,
boxShadows: boxShadows,
backgroundGradient: backgroundGradient,
mainButton: mainButton,
onTap: onTap,
isDismissible: isDismissible ?? true,
dismissDirection: dismissDirection ?? SnackDismissDirection.VERTICAL,
showProgressIndicator: showProgressIndicator ?? false,
progressIndicatorController: progressIndicatorController,
progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
progressIndicatorValueColor: progressIndicatorValueColor,
snackStyle: snackStyle ?? SnackStyle.FLOATING,
forwardAnimationCurve: forwardAnimationCurve ?? Curves.easeOutCirc,
reverseAnimationCurve: reverseAnimationCurve ?? Curves.easeOutCirc,
animationDuration: animationDuration ?? Duration(seconds: 1),
overlayBlur: overlayBlur ?? 0.0,
overlayColor: overlayColor ?? Colors.transparent,
userInputForm: userInputForm);
if (instantInit) {
getBar.show();
} else {
_routing.isSnackbar = true;
SchedulerBinding.instance.addPostFrameCallback((_) {
getBar.show();
});
}
}
ParseRouteTree routeTree;
void addPages(List<GetPage> getPages) {
if (getPages != null) {
if (routeTree == null) routeTree = ParseRouteTree();
getPages.forEach((element) {
routeTree.addRoute(element);
});
}
}
void addPage(GetPage getPage) {
if (getPage != null) {
if (routeTree == null) routeTree = ParseRouteTree();
routeTree.addRoute(getPage);
}
}
/// change default config of Get
void config(
{bool enableLog,
bool defaultPopGesture,
bool defaultOpaqueRoute,
Duration defaultDurationTransition,
bool defaultGlobalState,
Transition defaultTransition}) {
if (enableLog != null) {
GetConfig.isLogEnable = enableLog;
}
if (defaultPopGesture != null) {
this.defaultPopGesture = defaultPopGesture;
}
if (defaultOpaqueRoute != null) {
this.defaultOpaqueRoute = defaultOpaqueRoute;
}
if (defaultTransition != null) {
this.defaultTransition = defaultTransition;
}
if (defaultDurationTransition != null) {
this.defaultDurationTransition = defaultDurationTransition;
}
if (defaultGlobalState != null) {
this.defaultGlobalState = defaultGlobalState;
}
}
CustomTransition customTransition;
GetMaterialController getxController = GetMaterialController();
Locale locale;
void updateLocale(Locale l) {
locale = l;
forceAppUpdate();
}
void forceAppUpdate() {
void rebuild(Element el) {
el.markNeedsBuild();
el.visitChildren(rebuild);
}
(context as Element).visitChildren(rebuild);
}
Map<String, Map<String, String>> translations = {};
void addTranslations(Map<String, Map<String, String>> tr) {
translations.addAll(tr);
}
void appendTranslations(Map<String, Map<String, String>> tr) {
tr.forEach((key, map) {
if (Get.translations.containsKey(key)) {
Get.translations[key].addAll(map);
} else {
Get.translations[key] = map;
}
});
}
void changeTheme(ThemeData theme) {
getxController.setTheme(theme);
}
void changeThemeMode(ThemeMode themeMode) {
getxController.setThemeMode(themeMode);
}
GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey) {
key = newKey;
return key;
}
GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
Map<int, GlobalKey<NavigatorState>> _keys = {};
GlobalKey<NavigatorState> nestedKey(int key) {
_keys.putIfAbsent(key, () => GlobalKey<NavigatorState>());
return _keys[key];
}
GlobalKey<NavigatorState> global(int k) {
if (k == null) {
return key;
}
if (!_keys.containsKey(k)) {
throw 'route id not found';
}
return _keys[k];
}
/// give access to Routing API from GetObserver
Routing get routing => _routing;
RouteSettings get routeSettings => settings;
final _routing = Routing();
Map<String, String> parameters = {};
// void setRouting(Routing rt) {
// _routing = rt;
// }
void setSettings(RouteSettings settings) {
settings = settings;
}
/// give current arguments
Object get arguments => _routing.args;
/// give name from current route
String get currentRoute => _routing.current;
/// give name from previous route
String get previousRoute => _routing.previous;
/// check if snackbar is open
bool get isSnackbarOpen => _routing.isSnackbar;
/// check if dialog is open
bool get isDialogOpen => _routing.isDialog;
/// check if bottomsheet is open
bool get isBottomSheetOpen => _routing.isBottomSheet;
/// check a raw current route
Route<dynamic> get rawRoute => _routing.route;
/// check if popGesture is enable
bool get isPopGestureEnable => defaultPopGesture;
/// check if default opaque route is enable
bool get isOpaqueRouteDefault => defaultOpaqueRoute;
/// give access to currentContext
BuildContext get context => key.currentContext;
/// give access to current Overlay Context
BuildContext get overlayContext => key.currentState.overlay.context;
/// give access to Theme.of(context)
ThemeData get theme => Theme.of(context);
/// give access to TextTheme.of(context)
TextTheme get textTheme => Theme.of(context).textTheme;
/// give access to Mediaquery.of(context)
MediaQueryData get mediaQuery => MediaQuery.of(context);
/// Check if dark mode theme is enable
bool get isDarkMode => (theme.brightness == Brightness.dark);
/// Check if dark mode theme is enable on platform on android Q+
bool get isPlatformDarkMode =>
(mediaQuery.platformBrightness == Brightness.dark);
/// give access to Theme.of(context).iconTheme.color
Color get iconColor => Theme.of(context).iconTheme.color;
/// give access to FocusScope.of(context)
FocusNode get focusScope => FocusManager.instance.primaryFocus;
/// give access to Immutable MediaQuery.of(context).size.height
double get height => MediaQuery.of(context).size.height;
/// give access to Immutable MediaQuery.of(context).size.width
double get width => MediaQuery.of(context).size.width;
}
class _GetImpl extends GetInterface {}
// ignore: non_constant_identifier_names
final Get = GetImpl();
/// It replaces the Flutter Navigator, but needs no context.
/// You can to use navigator.push(YourRoute()) rather Navigator.push(context, YourRoute());
NavigatorState get navigator => Get.key.currentState;
final Get = _GetImpl();
... ...
import 'package:get/src/typedefs/typedefs.dart';
import '../get_main.dart';
import 'package:get/src/get_interface.dart';
import 'get_instance.dart';
extension Inst on GetImpl {
extension Inst on GetInterface {
void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) {
return GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
}
... ... @@ -19,15 +18,9 @@ extension Inst on GetImpl {
GetInstance().find<S>(tag: tag, instance: instance);
S put<S>(S dependency,
{String tag,
bool permanent = false,
bool overrideAbstract = false,
FcBuilderFunc<S> builder}) =>
GetInstance().put<S>(dependency,
tag: tag,
permanent: permanent,
overrideAbstract: overrideAbstract,
builder: builder);
{String tag, bool permanent = false, FcBuilderFunc<S> builder}) =>
GetInstance()
.put<S>(dependency, tag: tag, permanent: permanent, builder: builder);
bool reset({bool clearFactory = true, bool clearRouteBindings = true}) =>
GetInstance().reset(
... ...
import 'package:get/src/root/smart_management.dart';
import 'package:get/src/rx/rx_interface.dart';
import 'package:get/src/typedefs/typedefs.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
class GetConfig {
//////////// INSTANCE MANAGER
... ... @@ -23,7 +22,7 @@ class GetInstance {
if (_getInstance == null) _getInstance = GetInstance._();
return _getInstance;
}
GetInstance._();
const GetInstance._();
static GetInstance _getInstance;
void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) {
... ... @@ -42,13 +41,10 @@ class GetInstance {
S dependency, {
String tag,
bool permanent = false,
bool overrideAbstract = false,
FcBuilderFunc<S> builder,
}) {
_insert(
isSingleton: true,
replace: overrideAbstract,
//?? (("$S" == "${dependency.runtimeType}") == false),
name: tag,
permanent: permanent,
builder: builder ?? (() => dependency));
... ... @@ -73,18 +69,14 @@ class GetInstance {
void _insert<S>({
bool isSingleton,
String name,
bool replace = true,
bool permanent = false,
FcBuilderFunc<S> builder,
}) {
assert(builder != null);
String key = _getKey(S, name);
if (replace) {
GetConfig._singl[key] = FcBuilder<S>(isSingleton, builder, permanent);
} else {
GetConfig._singl.putIfAbsent(
key, () => FcBuilder<S>(isSingleton, builder, permanent));
}
GetConfig._singl
.putIfAbsent(key, () => FcBuilder<S>(isSingleton, builder, permanent));
}
void removeDependencyByRoute(String routeName) async {
... ... @@ -104,10 +96,6 @@ class GetInstance {
keysToRemove.clear();
}
bool isRouteDependecyNull<S>({String name}) {
return (GetConfig.routesKey[_getKey(S, name)] == null);
}
bool isDependencyInit<S>({String name}) {
String key = _getKey(S, name);
return GetConfig.routesKey.containsKey(key);
... ... @@ -133,6 +121,27 @@ class GetInstance {
}
}
// S putOrFind<S>(S Function() dep, {String tag}) {
// final key = _getKey(S, tag);
// if (GetConfig._singl.containsKey(key)) {
// return GetConfig._singl[key].getSependency() as S;
// } else {
// if (GetConfig._factory.containsKey(key)) {
// S _value = put<S>((GetConfig._factory[key].builder() as S), tag: tag);
// if (GetConfig.smartManagement != SmartManagement.keepFactory) {
// if (!GetConfig._factory[key].fenix) {
// GetConfig._factory.remove(key);
// }
// }
// return _value;
// }
// return GetInstance().put(dep(), tag: tag);
// }
// }
/// Find a instance from required class
S find<S>({String tag, FcBuilderFunc<S> instance}) {
String key = _getKey(S, tag);
... ... @@ -184,24 +193,6 @@ class GetInstance {
}
}
/// Remove dependency of [S] on dependency abstraction. For concrete class use delete
void remove<S>({String tag}) {
String key = _getKey(S, tag);
FcBuilder builder = GetConfig._singl[key] as FcBuilder;
final i = builder.dependency;
if (i is DisposableInterface) {
i.onClose();
if (GetConfig.isLogEnable) print('[GETX] onClose of $key called');
}
if (builder != null) builder.dependency = null;
if (GetConfig._singl.containsKey(key)) {
print('error on remove $key');
} else {
if (GetConfig.isLogEnable) print('[GETX] $key removed from memory');
}
}
String _getKey(Type type, String name) {
return name == null ? type.toString() : type.toString() + name;
}
... ... @@ -214,7 +205,7 @@ class GetInstance {
}
/// Delete class instance on [S] and clean memory
Future<bool> delete<S>({String tag, String key}) async {
Future<bool> delete<S>({String tag, String key, bool force = false}) async {
String newKey;
if (key == null) {
newKey = _getKey(S, tag);
... ... @@ -228,13 +219,16 @@ class GetInstance {
}
FcBuilder builder = GetConfig._singl[newKey] as FcBuilder;
if (builder.permanent) {
if (builder.permanent && !force) {
print(
'[GETX] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.');
return false;
}
final i = builder.dependency;
if (i is GetxService && !force) {
return false;
}
if (i is DisposableInterface) {
await i.onClose();
if (GetConfig.isLogEnable) print('[GETX] onClose of $newKey called');
... ... @@ -258,3 +252,27 @@ class GetInstance {
bool isPrepared<S>({String tag}) =>
GetConfig._factory.containsKey(_getKey(S, tag));
}
typedef FcBuilderFunc<S> = S Function();
typedef FcBuilderFuncAsync<S> = Future<S> Function();
class FcBuilder<S> {
bool isSingleton;
FcBuilderFunc builderFunc;
S dependency;
bool permanent = false;
FcBuilder(this.isSingleton, this.builderFunc, this.permanent);
S getSependency() {
if (isSingleton) {
if (dependency == null) {
dependency = builderFunc() as S;
}
return dependency;
} else {
return builderFunc() as S;
}
}
}
... ...
export 'get_instance.dart';
export 'extension_instance.dart';
export '../navigation/routes/bindings_interface.dart';
... ...
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/src/get_interface.dart';
import 'package:get/src/instance/instance_manager.dart';
import 'package:get/src/navigation/route_manager.dart';
import 'root/parse_route.dart';
import 'routes/bindings_interface.dart';
/// It replaces the Flutter Navigator, but needs no context.
/// You can to use navigator.push(YourRoute()) rather Navigator.push(context, YourRoute());
NavigatorState get navigator => Get.key.currentState;
extension GetNavigation on GetInterface {
/// Pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> to<T>(
Widget page, {
bool opaque,
Transition transition,
Duration duration,
int id,
bool fullscreenDialog = false,
Object arguments,
Bindings binding,
preventDuplicates = true,
bool popGesture,
}) {
if (preventDuplicates && '/${page.runtimeType}' == currentRoute) {
return null;
}
return global(id).currentState.push(
GetPageRoute(
opaque: opaque ?? true,
page: () => page,
settings: RouteSettings(
name: '/${page.runtimeType}',
arguments: arguments,
),
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
fullscreenDialog: fullscreenDialog,
binding: binding,
transitionDuration: duration ?? defaultDurationTransition,
),
);
}
/// Pushes a new named [page] to the stack
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> toNamed<T>(
String page, {
Object arguments,
int id,
preventDuplicates = true,
}) {
if (preventDuplicates && page == currentRoute) {
return null;
}
return global(id).currentState.pushNamed(page, arguments: arguments);
}
/// Pop the current named [page] in the stack and push a new one in its place
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> offNamed<T>(
String page, {
Object arguments,
int id,
preventDuplicates = true,
}) {
if (preventDuplicates && page == currentRoute) {
return null;
}
return global(id)
.currentState
.pushReplacementNamed(page, arguments: arguments);
}
/// Calls pop several times in the stack until [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
void until(RoutePredicate predicate, {int id}) {
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return global(id).currentState.popUntil(predicate);
}
/// Push the given [page], and then pop several [pages] in the stack until
/// [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
Future<T> offUntil<T>(Route<T> page, RoutePredicate predicate, {int id}) {
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return global(id).currentState.pushAndRemoveUntil(page, predicate);
}
/// Push the given named [page], and then pop several pages in the stack
/// until [predicate] returns true
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> offNamedUntil<T>(
String page,
RoutePredicate predicate, {
int id,
Object arguments,
}) {
return global(id)
.currentState
.pushNamedAndRemoveUntil(page, predicate, arguments: arguments);
}
/// Pop the current named page and pushes a new [page] to the stack in its place
///
/// You can send any type of value to the other route in the [arguments].
/// It is very similar to `offNamed()` but use a different approach
///
/// The `offNamed()` pop a page, and goes to the next. The `offAndToNamed()` goes
/// to the next page, and removes the previous one. The route transition
/// animation is different.
Future<T> offAndToNamed<T>(String page,
{Object arguments, int id, dynamic result}) {
return global(id)
.currentState
.popAndPushNamed(page, arguments: arguments, result: result);
}
/// Remove a specific [route] from the stack
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void removeRoute(Route<dynamic> route, {int id}) {
return global(id).currentState.removeRoute(route);
}
/// Push a named [page] and remove all other pages from stack
///
/// It has the advantage of not needing context, so you can
/// call from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors
Future<T> offAllNamed<T>(String newRouteName,
{RoutePredicate predicate, Object arguments, int id}) {
var route = (Route<dynamic> rota) => false;
return global(id).currentState.pushNamedAndRemoveUntil(
newRouteName, predicate ?? route,
arguments: arguments);
}
/// Returns true if a snackbar, dialog or bottomsheet is currently showing in the screen
bool get isOverlaysOpen =>
(isSnackbarOpen || isDialogOpen || isBottomSheetOpen);
/// returns true if there is no snackbar, dialog or bottomsheet open
bool get isOverlaysClosed =>
(!isSnackbarOpen && !isDialogOpen && !isBottomSheetOpen);
/// Pop the current page, snackbar, dialog or bottomsheet in the stack
///
/// if your set [closeOverlays] to true, Get.back() will close the currently open
/// snackbar/dialog/bottomsheet AND the current page
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
void back({
dynamic result,
bool closeOverlays = false,
bool canPop = true,
int id,
}) {
if (closeOverlays && isOverlaysOpen) {
navigator.popUntil((route) {
return (isOverlaysClosed);
});
}
if (canPop) {
if (global(id).currentState.canPop()) {
global(id).currentState.pop(result);
}
} else {
global(id).currentState.pop(result);
}
}
/// Close as many routes as defined by [times]
void close(int times, [int id]) {
if ((times == null) || (times < 1)) {
times = 1;
}
int count = 0;
void back = global(id).currentState.popUntil((route) {
return count++ == times;
});
return back;
}
/// Pop the current page and pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> off<T>(
Widget page, {
bool opaque = false,
Transition transition,
bool popGesture,
int id,
Object arguments,
Bindings binding,
bool fullscreenDialog = false,
preventDuplicates = true,
Duration duration,
}) {
if (preventDuplicates && '/${page.runtimeType}' == currentRoute) {
return null;
}
return global(id).currentState.pushReplacement(GetPageRoute(
opaque: opaque ?? true,
page: () => page,
binding: binding,
settings:
RouteSettings(name: '/${page.runtimeType}', arguments: arguments),
fullscreenDialog: fullscreenDialog,
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
transitionDuration: duration ?? defaultDurationTransition));
}
/// Pop all pages in the stack and pushes a new [page] to it
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future<T> offAll<T>(
Widget page, {
RoutePredicate predicate,
bool opaque = false,
bool popGesture,
int id,
Object arguments,
Bindings binding,
bool fullscreenDialog = false,
Duration duration,
Transition transition,
}) {
var route = (Route<dynamic> rota) => false;
return global(id).currentState.pushAndRemoveUntil(
GetPageRoute(
opaque: opaque ?? true,
popGesture: popGesture ?? defaultPopGesture,
page: () => page,
binding: binding,
settings:
RouteSettings(name: '/${page.runtimeType}', arguments: arguments),
fullscreenDialog: fullscreenDialog,
transition: transition ?? defaultTransition,
transitionDuration: duration ?? defaultDurationTransition,
),
predicate ?? route);
}
/// Show a dialog
Future<T> dialog<T>(
Widget child, {
bool barrierDismissible = true,
bool useRootNavigator = true,
// RouteSettings routeSettings
}) {
return showDialog(
barrierDismissible: barrierDismissible,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: 'dialog'),
context: overlayContext,
builder: (_) {
return child;
},
);
}
/// Api from showGeneralDialog with no context
Future<T> generalDialog<T>({
@required RoutePageBuilder pageBuilder,
String barrierLabel = "Dismiss",
bool barrierDismissible = true,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
bool useRootNavigator = true,
RouteSettings routeSettings,
}) {
return showGeneralDialog(
pageBuilder: pageBuilder,
barrierDismissible: barrierDismissible,
barrierLabel: barrierLabel,
barrierColor: barrierColor,
transitionDuration: transitionDuration,
transitionBuilder: transitionBuilder,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: 'dialog'),
context: overlayContext,
);
}
Future<T> defaultDialog<T>({
String title = "Alert",
Widget content,
VoidCallback onConfirm,
VoidCallback onCancel,
VoidCallback onCustom,
Color cancelTextColor,
Color confirmTextColor,
String textConfirm,
String textCancel,
String textCustom,
Widget confirm,
Widget cancel,
Widget custom,
Color backgroundColor,
Color buttonColor,
String middleText = "Dialog made in 3 lines of code",
double radius = 20.0,
List<Widget> actions,
}) {
bool leanCancel = onCancel != null || textCancel != null;
bool leanConfirm = onConfirm != null || textConfirm != null;
actions ??= [];
if (cancel != null) {
actions.add(cancel);
} else {
if (leanCancel) {
actions.add(FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onPressed: () {
onCancel?.call();
back();
},
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8),
child: Text(
textCancel ?? "Cancel",
style: TextStyle(color: cancelTextColor ?? theme.accentColor),
),
shape: RoundedRectangleBorder(
side: BorderSide(
color: buttonColor ?? theme.accentColor,
width: 2,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(100)),
));
}
}
if (confirm != null) {
actions.add(confirm);
} else {
if (leanConfirm) {
actions.add(FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
color: buttonColor ?? theme.accentColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100)),
child: Text(
textConfirm ?? "Ok",
style: TextStyle(color: confirmTextColor ?? theme.primaryColor),
),
onPressed: () {
onConfirm?.call();
}));
}
}
return dialog(AlertDialog(
titlePadding: EdgeInsets.all(8),
contentPadding: EdgeInsets.all(8),
backgroundColor: backgroundColor ?? theme.dialogBackgroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(radius))),
title: Text(title, textAlign: TextAlign.center),
content: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
content ?? Text(middleText ?? "", textAlign: TextAlign.center),
SizedBox(height: 16),
ButtonTheme(
minWidth: 78.0,
height: 34.0,
child: Wrap(
alignment: WrapAlignment.center,
spacing: 8,
runSpacing: 8,
children: actions,
),
)
],
),
// actions: actions, // ?? <Widget>[cancelButton, confirmButton],
buttonPadding: EdgeInsets.zero,
));
}
Future<T> bottomSheet<T>(
Widget bottomsheet, {
Color backgroundColor,
double elevation,
ShapeBorder shape,
Clip clipBehavior,
Color barrierColor,
bool ignoreSafeArea,
bool isScrollControlled = false,
bool useRootNavigator = false,
bool isDismissible = true,
bool enableDrag = true,
}) {
assert(bottomsheet != null);
assert(isScrollControlled != null);
assert(useRootNavigator != null);
assert(isDismissible != null);
assert(enableDrag != null);
return Navigator.of(overlayContext, rootNavigator: useRootNavigator)
.push(GetModalBottomSheetRoute<T>(
builder: (_) => bottomsheet,
theme: Theme.of(key.currentContext, shadowThemeOnly: true),
isScrollControlled: isScrollControlled,
barrierLabel:
MaterialLocalizations.of(key.currentContext).modalBarrierDismissLabel,
backgroundColor: backgroundColor ?? Colors.transparent,
elevation: elevation,
shape: shape,
removeTop: ignoreSafeArea ?? true,
clipBehavior: clipBehavior,
isDismissible: isDismissible,
modalBarrierColor: barrierColor,
settings: RouteSettings(name: "bottomsheet"),
enableDrag: enableDrag,
));
}
void rawSnackbar(
{String title,
String message,
Widget titleText,
Widget messageText,
Widget icon,
bool instantInit = true,
bool shouldIconPulse = true,
double maxWidth,
EdgeInsets margin = const EdgeInsets.all(0.0),
EdgeInsets padding = const EdgeInsets.all(16),
double borderRadius = 0.0,
Color borderColor,
double borderWidth = 1.0,
Color backgroundColor = const Color(0xFF303030),
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
Duration duration = const Duration(seconds: 3),
bool isDismissible = true,
SnackDismissDirection dismissDirection = SnackDismissDirection.VERTICAL,
bool showProgressIndicator = false,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackPosition snackPosition = SnackPosition.BOTTOM,
SnackStyle snackStyle = SnackStyle.FLOATING,
Curve forwardAnimationCurve = Curves.easeOutCirc,
Curve reverseAnimationCurve = Curves.easeOutCirc,
Duration animationDuration = const Duration(seconds: 1),
SnackStatusCallback onStatusChanged,
double barBlur = 0.0,
double overlayBlur = 0.0,
Color overlayColor = Colors.transparent,
Form userInputForm}) {
GetBar getBar = GetBar(
title: title,
message: message,
titleText: titleText,
messageText: messageText,
snackPosition: snackPosition,
borderRadius: borderRadius,
margin: margin,
duration: duration,
barBlur: barBlur,
backgroundColor: backgroundColor,
icon: icon,
shouldIconPulse: shouldIconPulse,
maxWidth: maxWidth,
padding: padding,
borderColor: borderColor,
borderWidth: borderWidth,
leftBarIndicatorColor: leftBarIndicatorColor,
boxShadows: boxShadows,
backgroundGradient: backgroundGradient,
mainButton: mainButton,
onTap: onTap,
isDismissible: isDismissible,
dismissDirection: dismissDirection,
showProgressIndicator: showProgressIndicator ?? false,
progressIndicatorController: progressIndicatorController,
progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
progressIndicatorValueColor: progressIndicatorValueColor,
snackStyle: snackStyle,
forwardAnimationCurve: forwardAnimationCurve,
reverseAnimationCurve: reverseAnimationCurve,
animationDuration: animationDuration,
overlayBlur: overlayBlur,
overlayColor: overlayColor,
userInputForm: userInputForm);
if (instantInit) {
getBar.show();
} else {
SchedulerBinding.instance.addPostFrameCallback((_) {
getBar.show();
});
}
}
void snackbar(String title, String message,
{Color colorText,
Duration duration,
/// with instantInit = false you can put snackbar on initState
bool instantInit = true,
SnackPosition snackPosition,
Widget titleText,
Widget messageText,
Widget icon,
bool shouldIconPulse,
double maxWidth,
EdgeInsets margin,
EdgeInsets padding,
double borderRadius,
Color borderColor,
double borderWidth,
Color backgroundColor,
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
bool isDismissible,
bool showProgressIndicator,
SnackDismissDirection dismissDirection,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackStyle snackStyle,
Curve forwardAnimationCurve,
Curve reverseAnimationCurve,
Duration animationDuration,
double barBlur,
double overlayBlur,
Color overlayColor,
Form userInputForm}) {
GetBar getBar = GetBar(
titleText: (title == null)
? null
: titleText ??
Text(
title,
style: TextStyle(
color: colorText ?? theme.iconTheme.color,
fontWeight: FontWeight.w800,
fontSize: 16),
),
messageText: messageText ??
Text(
message,
style: TextStyle(
color: colorText ?? theme.iconTheme.color,
fontWeight: FontWeight.w300,
fontSize: 14),
),
snackPosition: snackPosition ?? SnackPosition.TOP,
borderRadius: borderRadius ?? 15,
margin: margin ?? EdgeInsets.symmetric(horizontal: 10),
duration: duration ?? Duration(seconds: 3),
barBlur: barBlur ?? 7.0,
backgroundColor: backgroundColor ?? Colors.grey.withOpacity(0.2),
icon: icon,
shouldIconPulse: shouldIconPulse ?? true,
maxWidth: maxWidth,
padding: padding ?? EdgeInsets.all(16),
borderColor: borderColor,
borderWidth: borderWidth,
leftBarIndicatorColor: leftBarIndicatorColor,
boxShadows: boxShadows,
backgroundGradient: backgroundGradient,
mainButton: mainButton,
onTap: onTap,
isDismissible: isDismissible ?? true,
dismissDirection: dismissDirection ?? SnackDismissDirection.VERTICAL,
showProgressIndicator: showProgressIndicator ?? false,
progressIndicatorController: progressIndicatorController,
progressIndicatorBackgroundColor: progressIndicatorBackgroundColor,
progressIndicatorValueColor: progressIndicatorValueColor,
snackStyle: snackStyle ?? SnackStyle.FLOATING,
forwardAnimationCurve: forwardAnimationCurve ?? Curves.easeOutCirc,
reverseAnimationCurve: reverseAnimationCurve ?? Curves.easeOutCirc,
animationDuration: animationDuration ?? Duration(seconds: 1),
overlayBlur: overlayBlur ?? 0.0,
overlayColor: overlayColor ?? Colors.transparent,
userInputForm: userInputForm);
if (instantInit) {
getBar.show();
} else {
routing.isSnackbar = true;
SchedulerBinding.instance.addPostFrameCallback((_) {
getBar.show();
});
}
}
void addPages(List<GetPage> getPages) {
if (getPages != null) {
if (routeTree == null) routeTree = ParseRouteTree();
getPages.forEach((element) {
routeTree.addRoute(element);
});
}
}
void addPage(GetPage getPage) {
if (getPage != null) {
if (routeTree == null) routeTree = ParseRouteTree();
routeTree.addRoute(getPage);
}
}
/// change default config of Get
void config(
{bool enableLog,
bool defaultPopGesture,
bool defaultOpaqueRoute,
Duration defaultDurationTransition,
bool defaultGlobalState,
Transition defaultTransition}) {
if (enableLog != null) {
GetConfig.isLogEnable = enableLog;
}
if (defaultPopGesture != null) {
this.defaultPopGesture = defaultPopGesture;
}
if (defaultOpaqueRoute != null) {
this.defaultOpaqueRoute = defaultOpaqueRoute;
}
if (defaultTransition != null) {
this.defaultTransition = defaultTransition;
}
if (defaultDurationTransition != null) {
this.defaultDurationTransition = defaultDurationTransition;
}
if (defaultGlobalState != null) {
this.defaultGlobalState = defaultGlobalState;
}
}
void updateLocale(Locale l) {
locale = l;
forceAppUpdate();
}
void forceAppUpdate() {
void rebuild(Element el) {
el.markNeedsBuild();
el.visitChildren(rebuild);
}
(context as Element).visitChildren(rebuild);
}
void addTranslations(Map<String, Map<String, String>> tr) {
translations.addAll(tr);
}
void appendTranslations(Map<String, Map<String, String>> tr) {
tr.forEach((key, map) {
if (Get.translations.containsKey(key)) {
Get.translations[key].addAll(map);
} else {
Get.translations[key] = map;
}
});
}
void changeTheme(ThemeData theme) {
getxController.setTheme(theme);
}
void changeThemeMode(ThemeMode themeMode) {
getxController.setThemeMode(themeMode);
}
GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey) {
key = newKey;
return key;
}
GlobalKey<NavigatorState> nestedKey(int key) {
keys.putIfAbsent(key, () => GlobalKey<NavigatorState>());
return keys[key];
}
GlobalKey<NavigatorState> global(int k) {
if (k == null) {
return key;
}
if (!keys.containsKey(k)) {
throw 'route id not found';
}
return keys[k];
}
RouteSettings get routeSettings => settings;
void setSettings(RouteSettings settings) {
settings = settings;
}
/// give current arguments
Object get arguments => routing.args;
/// give name from current route
String get currentRoute => routing.current;
/// give name from previous route
String get previousRoute => routing.previous;
/// check if snackbar is open
bool get isSnackbarOpen => routing.isSnackbar;
/// check if dialog is open
bool get isDialogOpen => routing.isDialog;
/// check if bottomsheet is open
bool get isBottomSheetOpen => routing.isBottomSheet;
/// check a raw current route
Route<dynamic> get rawRoute => routing.route;
/// check if popGesture is enable
bool get isPopGestureEnable => defaultPopGesture;
/// check if default opaque route is enable
bool get isOpaqueRouteDefault => defaultOpaqueRoute;
/// give access to currentContext
BuildContext get context => key.currentContext;
/// give access to current Overlay Context
BuildContext get overlayContext => key.currentState.overlay.context;
/// give access to Theme.of(context)
ThemeData get theme => Theme.of(context);
/// give access to TextTheme.of(context)
TextTheme get textTheme => Theme.of(context).textTheme;
/// give access to Mediaquery.of(context)
MediaQueryData get mediaQuery => MediaQuery.of(context);
/// Check if dark mode theme is enable
bool get isDarkMode => (theme.brightness == Brightness.dark);
/// Check if dark mode theme is enable on platform on android Q+
bool get isPlatformDarkMode =>
(mediaQuery.platformBrightness == Brightness.dark);
/// give access to Theme.of(context).iconTheme.color
Color get iconColor => Theme.of(context).iconTheme.color;
/// give access to FocusScope.of(context)
FocusNode get focusScope => FocusManager.instance.primaryFocus;
/// give access to Immutable MediaQuery.of(context).size.height
double get height => MediaQuery.of(context).size.height;
/// give access to Immutable MediaQuery.of(context).size.width
double get width => MediaQuery.of(context).size.width;
}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/routes/get_route.dart';
import 'package:get/src/navigation/routes/get_route.dart';
class GetPageMatch {
GetPageMatch(this.route);
... ...
import 'package:flutter/material.dart';
import 'package:get/src/state/get_state.dart';
import 'package:get/src/state_manager/simple/get_state.dart';
class GetMaterialController extends GetxController {
Key key;
... ...
... ... @@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/routes/get_route.dart';
import 'package:get/src/navigation/routes/get_route.dart';
import 'root_controller.dart';
import 'smart_management.dart';
... ...
export 'routes/custom_transition.dart';
export 'routes/transitions_type.dart';
export 'routes/get_route.dart';
export 'routes/default_route.dart';
export 'routes/observers/route_observer.dart';
export 'root/root_widget.dart';
export 'snackbar/snack_route.dart';
export 'bottomsheet/bottomsheet.dart';
export 'snackbar/snack.dart';
export '../get_main.dart';
export 'routes/default_route.dart';
export 'root/smart_management.dart';
export 'extension_navigation.dart';
... ...
... ... @@ -3,10 +3,10 @@ import 'dart:ui' show lerpDouble;
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/route_manager.dart';
import 'package:get/src/navigation/route_manager.dart';
import 'package:get/src/get_main.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/utils.dart';
import 'package:get/src/utils/utils.dart';
import 'bindings_interface.dart';
import 'custom_transition.dart';
import 'default_transitions.dart';
... ... @@ -130,14 +130,6 @@ class GetPageRoute<T> extends PageRoute<T> {
bool get popGestureInProgress => isPopGestureInProgress(this);
@override
void dispose() {
if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {
GetInstance().removeDependencyByRoute("${settings.name}");
}
super.dispose();
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
if (fullscreenDialog && transition == null) {
... ... @@ -393,6 +385,15 @@ class GetPageRoute<T> extends PageRoute<T> {
: child);
}
}
@override
void dispose() {
if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {
Future.delayed(Duration.zero,
() => GetInstance().removeDependencyByRoute("${settings.name}"));
}
super.dispose();
}
}
const double _kBackGestureWidth = 20.0;
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/routes/bindings_interface.dart';
import 'package:get/src/navigation/routes/bindings_interface.dart';
import 'custom_transition.dart';
import 'transitions_type.dart';
... ...
... ... @@ -375,11 +375,12 @@ class _GetBarState<K extends Object> extends State<GetBar>
child: SafeArea(
minimum: widget.snackPosition == SnackPosition.BOTTOM
? EdgeInsets.only(
bottom: (GetUtils.isGreaterThan(
MediaQuery.of(context).viewInsets.bottom,
MediaQuery.of(context).padding.bottom)
? MediaQuery.of(context).viewInsets.bottom
: MediaQuery.of(context).padding.bottom))
// bottom: (GetUtils.isGreaterThan(
// MediaQuery.of(context).viewInsets.bottom,
// MediaQuery.of(context).padding.bottom)
// ? MediaQuery.of(context).viewInsets.bottom
// : MediaQuery.of(context).padding.bottom))
bottom: MediaQuery.of(context).viewInsets.bottom)
: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
bottom: widget.snackPosition == SnackPosition.BOTTOM,
top: widget.snackPosition == SnackPosition.TOP,
... ...
... ... @@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/root/smart_management.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'rx_impl.dart';
import 'rx_interface.dart';
... ... @@ -63,9 +63,10 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> {
controller?.onStart();
}
if (widget.initState != null) widget.initState(this);
// if (isCreator && GetConfig.smartManagement == SmartManagement.onlyBuilder) {
// controller?.onStart();
// }
if (widget.global &&
GetConfig.smartManagement == SmartManagement.onlyBuilder) {
controller?.onStart();
}
subs = _observer.subject.stream.listen((data) => setState(() {}));
super.initState();
}
... ...
import 'dart:async';
import 'package:flutter/scheduler.dart';
import 'package:get/src/rx/rx_callbacks.dart';
import 'package:get/src/state_manager/rx/rx_callbacks.dart';
abstract class RxInterface<T> {
RxInterface([T initial]);
... ... @@ -21,6 +21,8 @@ abstract class RxInterface<T> {
StreamSubscription<T> listen(ValueCallback<T> callback);
}
abstract class GetxService extends DisposableInterface {}
abstract class DisposableInterface {
/// Called at the exact moment that the widget is allocated in memory.
/// Do not overwrite this method.
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/rx/rx_interface.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
import 'rx_impl.dart';
Widget obx(Widget Function() builder) {
... ...
import 'dart:collection';
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/root/smart_management.dart';
import 'package:get/src/rx/rx_interface.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
class GetxController extends DisposableInterface {
final HashSet<UpdaterBuilder> _updaters = HashSet<UpdaterBuilder>();
... ... @@ -97,7 +97,8 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
controller?.onStart();
}
if (isCreator && GetConfig.smartManagement == SmartManagement.onlyBuilder) {
if (widget.global &&
GetConfig.smartManagement == SmartManagement.onlyBuilder) {
controller?.onStart();
}
}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
abstract class GetWidget<T> extends StatelessWidget {
const GetWidget({Key key}) : super(key: key);
T get controller => GetInstance().find();
abstract class GetView<T> extends StatelessWidget {
const GetView({Key key}) : super(key: key);
T get controller => GetInstance().find<T>();
@override
Widget build(BuildContext context);
}
abstract class GetView<T> extends StatelessWidget {
const GetView({Key key}) : super(key: key);
T get controller => GetInstance().find();
abstract class GetWidget<T> extends StatelessWidget {
GetWidget({Key key}) : super(key: key);
final Set<T> _value = Set<T>();
T get controller {
if (_value.isEmpty) _value.add(GetInstance().find<T>());
return _value.first;
}
@override
Widget build(BuildContext context);
... ...
// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';
// import 'package:get/src/instance/get_instance.dart';
// import 'package:get/state_manager.dart';
// abstract class GetState<T> extends DisposableInterface {
// GetState(this.initialValue) {
// _state = initialValue;
// }
// final Set<StateSetter> _updaters = Set<StateSetter>();
// @protected
// void update(T value, [bool condition = true]) {
// if (!condition) return;
// _state = value;
// _updaters.forEach((rs) => rs(() {}));
// }
// T _state;
// final T initialValue;
// void addListener(StateSetter value) {
// _updaters.add(value);
// }
// void removeListener(StateSetter value) {
// _updaters.add(value);
// }
// // @protected
// T get state => _state;
// @protected
// void updater(void fn(T value)) {
// fn(_state);
// update(_state);
// }
// }
// class StateBuilder<T extends GetState> extends StatefulWidget {
// final Widget Function(dynamic) builder;
// final bool global;
// final String tag;
// final bool autoRemove;
// final bool assignId;
// final void Function(State state) initState, dispose, didChangeDependencies;
// final void Function(StateBuilder oldWidget, State state) didUpdateWidget;
// final T Function() state;
// const StateBuilder({
// Key key,
// this.state,
// this.global = true,
// @required this.builder,
// this.autoRemove = true,
// this.assignId = false,
// this.initState,
// this.tag,
// this.dispose,
// this.didChangeDependencies,
// this.didUpdateWidget,
// }) : assert(builder != null),
// super(key: key);
// @override
// _StateBuilderState<T> createState() => _StateBuilderState<T>();
// }
// class _StateBuilderState<T extends GetState> extends State<StateBuilder<T>> {
// T controller;
// bool isCreator = false;
// @override
// void initState() {
// super.initState();
// if (widget.initState != null) widget.initState(this);
// if (widget.global) {
// final isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);
// final isRegistred = GetInstance().isRegistred<T>(tag: widget.tag);
// if (isPrepared) {
// isCreator = true;
// } else if (isRegistred) {
// isCreator = false;
// } else {
// isCreator = true;
// }
// if (isCreator) {
// controller?.onStart();
// }
// final instance = GetInstance().putOrFind(widget.state, tag: widget.tag);
// controller = instance;
// controller._updaters.add(setState);
// } else {
// controller = widget.state();
// isCreator = true;
// controller._updaters.add(setState);
// controller?.onStart();
// }
// }
// @override
// void dispose() {
// super.dispose();
// if (widget.dispose != null) widget.dispose(this);
// if (isCreator || widget.assignId) {
// if (widget.autoRemove && GetInstance().isRegistred<T>(tag: widget.tag)) {
// controller._updaters.remove(setState);
// GetInstance().delete<T>(tag: widget.tag);
// }
// } else {
// controller._updaters.remove(setState);
// }
// }
// @override
// void didChangeDependencies() {
// super.didChangeDependencies();
// if (widget.didChangeDependencies != null) {
// widget.didChangeDependencies(this);
// }
// }
// @override
// void didUpdateWidget(StateBuilder oldWidget) {
// super.didUpdateWidget(oldWidget as StateBuilder<T>);
// if (widget.didUpdateWidget != null) widget.didUpdateWidget(oldWidget, this);
// }
// @override
// Widget build(BuildContext context) {
// return widget.builder(controller.state);
// }
// }
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/rx/rx_obx.dart';
import 'package:get/src/state_manager/rx/rx_obx.dart';
import 'get_state.dart';
class MixinBuilder<T extends GetxController> extends StatelessWidget {
... ...
export 'simple/get_state.dart';
export 'simple/immutable_state.dart';
export 'simple/get_view.dart';
export 'simple/mixin_state.dart';
export 'rx/rx_interface.dart';
export 'rx/rx_impl.dart';
export 'rx/rx_event.dart';
export 'rx/rx_obx.dart';
export 'rx/rx_getbuilder.dart';
... ...
typedef FcBuilderFunc<S> = S Function();
typedef FcBuilderFuncAsync<S> = Future<S> Function();
class FcBuilder<S> {
bool isSingleton;
FcBuilderFunc builderFunc;
S dependency;
bool permanent = false;
FcBuilder(this.isSingleton, this.builderFunc, this.permanent);
S getSependency() {
if (isSingleton) {
if (dependency == null) {
dependency = builderFunc() as S;
}
return dependency;
} else {
return builderFunc() as S;
}
}
}
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
extension MDQ on BuildContext {
extension ContextExtensionss on BuildContext {
/// The same of [MediaQuery.of(context).size]
Size get mediaQuerySize => MediaQuery.of(this).size;
... ... @@ -52,8 +53,17 @@ extension MDQ on BuildContext {
}
/// similar to [MediaQuery.of(context).padding]
ThemeData get theme => Theme.of(this);
/// similar to [MediaQuery.of(context).padding]
TextTheme get textTheme => Theme.of(this).textTheme;
/// similar to [MediaQuery.of(context).padding]
EdgeInsets get mediaQueryPadding => MediaQuery.of(this).padding;
/// similar to [MediaQuery.of(context).padding]
MediaQueryData get mediaQuery => MediaQuery.of(this);
/// similar to [MediaQuery.of(context).viewPadding]
EdgeInsets get mediaQueryViewPadding => MediaQuery.of(this).viewPadding;
... ...
import 'package:get/src/regex/regex.dart';
import 'package:get/src/utils/regex/regex.dart';
class GetUtils {
/// Checks if data is null.
... ...
... ... @@ -53,19 +53,22 @@ extension GetNumUtils on num {
}
extension GetDynamicUtils on dynamic {
/// It's This is overloading the IDE's options. Only the most useful and popular options will stay here.
bool get isNull => GetUtils.isNull(this);
bool get isNullOrBlank => GetUtils.isNullOrBlank(this);
bool get isOneAKind => GetUtils.isOneAKind(this);
bool isLengthLowerThan(int maxLength) =>
GetUtils.isLengthLowerThan(this, maxLength);
bool isLengthGreaterThan(int maxLength) =>
GetUtils.isLengthGreaterThan(this, maxLength);
bool isLengthGreaterOrEqual(int maxLength) =>
GetUtils.isLengthGreaterOrEqual(this, maxLength);
bool isLengthLowerOrEqual(int maxLength) =>
GetUtils.isLengthLowerOrEqual(this, maxLength);
bool isLengthEqualTo(int maxLength) =>
GetUtils.isLengthEqualTo(this, maxLength);
bool isLengthBetween(int minLength, int maxLength) =>
GetUtils.isLengthBetween(this, minLength, maxLength);
// bool get isOneAKind => GetUtils.isOneAKind(this);
// bool isLengthLowerThan(int maxLength) =>
// GetUtils.isLengthLowerThan(this, maxLength);
// bool isLengthGreaterThan(int maxLength) =>
// GetUtils.isLengthGreaterThan(this, maxLength);
// bool isLengthGreaterOrEqual(int maxLength) =>
// GetUtils.isLengthGreaterOrEqual(this, maxLength);
// bool isLengthLowerOrEqual(int maxLength) =>
// GetUtils.isLengthLowerOrEqual(this, maxLength);
// bool isLengthEqualTo(int maxLength) =>
// GetUtils.isLengthEqualTo(this, maxLength);
// bool isLengthBetween(int minLength, int maxLength) =>
// GetUtils.isLengthBetween(this, minLength, maxLength);
}
... ...
export 'context_extensions/extensions.dart';
export 'queue/get_queue.dart';
export 'platform/platform.dart';
export 'regex/get_utils.dart';
export 'regex/get_utils_extensions.dart';
... ...
export 'src/state/get_state.dart';
export 'src/state/get_view.dart';
export 'src/state/mixin_state.dart';
export 'src/rx/rx_interface.dart';
export 'src/rx/rx_impl.dart';
export 'src/rx/rx_event.dart';
export 'src/rx/rx_obx.dart';
export 'src/rx/rx_getbuilder.dart';
export 'src/context_extensions/extensions.dart';
export 'src/queue/get_queue.dart';
export 'src/platform/platform.dart';
export 'src/regex/get_utils.dart';
export 'src/regex/get_utils_extensions.dart';
... ... @@ -21,7 +21,7 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.1.0-nullsafety"
charcode:
dependency: transitive
description:
... ... @@ -42,7 +42,7 @@ packages:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.13"
version: "1.15.0-nullsafety"
fake_async:
dependency: transitive
description:
... ... @@ -73,7 +73,7 @@ packages:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.8"
version: "1.3.0-nullsafety"
path:
dependency: transitive
description:
... ... @@ -134,13 +134,13 @@ packages:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.0-nullsafety"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
version: "2.1.0-nullsafety"
sdks:
dart: ">=2.9.0-14.0.dev <3.0.0"
dart: ">=2.9.0-18.0 <2.9.0"
... ...
name: get
description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
version: 3.4.0
description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with GetX.
version: 3.4.1
homepage: https://github.com/jonataslaw/get
environment:
... ...