Jonny Borges
Committed by GitHub

Merge pull request #2696 from jonataslaw/refactor-root

Refactor root
... ... @@ -23,7 +23,7 @@ jobs:
# https://github.com/marketplace/actions/flutter-action
- uses: subosito/flutter-action@v2
with:
flutter-version: "3.0.5"
flutter-version: "3.7.3"
channel: "stable"
- run: flutter pub get
#- run: flutter analyze
... ...
... ... @@ -34,6 +34,7 @@
/android/
/web/
/macos/
/windows/
# Web related
lib/generated_plugin_registrant.dart
... ...
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
# This file should be version controlled.
version:
revision: 7c6f9dd2396dfe7deb6fd11edc12c10786490083
channel: dev
revision: 9944297138845a94256f1cf37beb88ff9a8e811a
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
- platform: android
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
- platform: ios
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
- platform: linux
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
- platform: macos
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
- platform: web
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
- platform: windows
create_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
base_revision: 9944297138845a94256f1cf37beb88ff9a8e811a
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
... ...
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
... ...
... ... @@ -27,6 +27,24 @@ class InstanceInfo {
}
}
extension ResetInstance on GetInterface {
/// Clears all registered instances (and/or tags).
/// Even the persistent ones.
/// This should be used at the end or tearDown of unit tests.
///
/// `clearFactory` clears the callbacks registered by [lazyPut]
/// `clearRouteBindings` clears Instances associated with routes.
///
bool resetInstance({bool clearRouteBindings = true}) {
// if (clearFactory) _factory.clear();
// deleteAll(force: true);
if (clearRouteBindings) RouterReportManager.instance.clearRouteKeys();
Inst._singl.clear();
return true;
}
}
extension Inst on GetInterface {
T call<T>() => find<T>();
... ... @@ -311,22 +329,6 @@ extension Inst on GetInterface {
return name == null ? type.toString() : type.toString() + name;
}
/// Clears all registered instances (and/or tags).
/// Even the persistent ones.
/// This should be used at the end or tearDown of unit tests.
///
/// `clearFactory` clears the callbacks registered by [lazyPut]
/// `clearRouteBindings` clears Instances associated with routes.
///
bool resetInstance({bool clearRouteBindings = true}) {
// if (clearFactory) _factory.clear();
// deleteAll(force: true);
if (clearRouteBindings) RouterReportManager.instance.clearRouteKeys();
_singl.clear();
return true;
}
/// Delete registered Class Instance [S] (or [tag]) and, closes any open
/// controllers `DisposableInterface`, cleans up the memory
///
... ...
... ... @@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import '../../get.dart';
import 'dialog/dialog_route.dart';
import 'root/get_root.dart';
/// It replaces the Flutter Navigator, but needs no context.
/// You can to use navigator.push(YourRoute()) rather
... ... @@ -219,8 +220,8 @@ extension ExtensionDialog on GetInterface {
),
child: Text(
textConfirm ?? "Ok",
style:
TextStyle(color: confirmTextColor ?? theme.backgroundColor),
style: TextStyle(
color: confirmTextColor ?? theme.colorScheme.background),
),
onPressed: () {
onConfirm?.call();
... ... @@ -1009,36 +1010,36 @@ extension GetNavigationExt on GetInterface {
}
return Uri.tryParse(name)?.toString() ?? name;
}
/// change default config of Get
void config(
{bool? enableLog,
LogWriterCallback? logWriterCallback,
bool? defaultPopGesture,
bool? defaultOpaqueRoute,
Duration? defaultDurationTransition,
bool? defaultGlobalState,
Transition? defaultTransition}) {
if (enableLog != null) {
Get.isLogEnable = enableLog;
}
if (logWriterCallback != null) {
Get.log = logWriterCallback;
}
if (defaultPopGesture != null) {
_getxController.defaultPopGesture = defaultPopGesture;
}
if (defaultOpaqueRoute != null) {
_getxController.defaultOpaqueRoute = defaultOpaqueRoute;
}
if (defaultTransition != null) {
_getxController.defaultTransition = defaultTransition;
}
if (defaultDurationTransition != null) {
_getxController.defaultTransitionDuration = defaultDurationTransition;
}
}
//TODO: Deprecated
// /// change default config of Get
// void config(
// {bool? enableLog,
// LogWriterCallback? logWriterCallback,
// bool? defaultPopGesture,
// bool? defaultOpaqueRoute,
// Duration? defaultDurationTransition,
// bool? defaultGlobalState,
// Transition? defaultTransition}) {
// if (enableLog != null) {
// Get.isLogEnable = enableLog;
// }
// if (logWriterCallback != null) {
// Get.log = logWriterCallback;
// }
// if (defaultPopGesture != null) {
// _getxController.defaultPopGesture = defaultPopGesture;
// }
// if (defaultOpaqueRoute != null) {
// _getxController.defaultOpaqueRoute = defaultOpaqueRoute;
// }
// if (defaultTransition != null) {
// _getxController.defaultTransition = defaultTransition;
// }
// if (defaultDurationTransition != null) {
// _getxController.defaultTransitionDuration = defaultDurationTransition;
// }
// }
Future<void> updateLocale(Locale l) async {
Get.locale = l;
... ... @@ -1062,22 +1063,22 @@ extension GetNavigationExt on GetInterface {
await engine.performReassemble();
}
void appUpdate() => _getxController.update();
void appUpdate() => rootController.update();
void changeTheme(ThemeData theme) {
_getxController.setTheme(theme);
rootController.setTheme(theme);
}
void changeThemeMode(ThemeMode themeMode) {
_getxController.setThemeMode(themeMode);
rootController.setThemeMode(themeMode);
}
GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
return _getxController.addKey(newKey);
return rootController.addKey(newKey);
}
GetDelegate? nestedKey(String? key) {
return _getxController.nestedKey(key);
return rootController.nestedKey(key);
}
GetDelegate searchDelegate(dynamic k) {
... ... @@ -1106,7 +1107,7 @@ extension GetNavigationExt on GetInterface {
/// give current arguments
//dynamic get arguments => routing.args;
dynamic get arguments => _getxController.rootDelegate.arguments();
dynamic get arguments => rootController.rootDelegate.arguments();
/// give name from current route
String get currentRoute => routing.current;
... ... @@ -1219,11 +1220,13 @@ extension GetNavigationExt on GetInterface {
// /// give access to Immutable MediaQuery.of(context).size.width
// double get width => MediaQuery.of(context).size.width;
GlobalKey<NavigatorState> get key => _getxController.key;
GlobalKey<NavigatorState> get key => rootController.key;
Map<dynamic, GetDelegate> get keys => rootController.keys;
Map<dynamic, GetDelegate> get keys => _getxController.keys;
GetRootState get rootController => GetRootState.controller;
GetMaterialController get rootController => _getxController;
ConfigData get _getxController => GetRootState.controller.config;
bool get defaultPopGesture => _getxController.defaultPopGesture;
bool get defaultOpaqueRoute => _getxController.defaultOpaqueRoute;
... ... @@ -1246,20 +1249,18 @@ extension GetNavigationExt on GetInterface {
Routing get routing => _getxController.routing;
Map<String, String?> get parameters =>
_getxController.rootDelegate.parameters;
set parameters(Map<String, String?> newParameters) =>
_getxController.parameters = newParameters;
rootController.parameters = newParameters;
set testMode(bool isTest) => rootController.testMode = isTest;
bool get testMode => _getxController.testMode;
set testMode(bool isTest) => _getxController.testMode = isTest;
Map<String, String?> get parameters => rootController.rootDelegate.parameters;
/// Casts the stored router delegate to a desired type
TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() =>
_getxController.routerDelegate as TDelegate?;
static final GetMaterialController _getxController =
Get.find<GetMaterialController>();
}
extension OverlayExt on GetInterface {
... ...
... ... @@ -7,11 +7,10 @@ import '../../../get_instance/get_instance.dart';
import '../../../get_state_manager/get_state_manager.dart';
import '../../../get_utils/get_utils.dart';
import '../../get_navigation.dart';
import '../router_report.dart';
import 'get_root.dart';
class GetCupertinoApp extends StatelessWidget {
final GlobalKey<NavigatorState>? navigatorKey;
final Widget? home;
final Map<String, WidgetBuilder>? routes;
final String? initialRoute;
... ... @@ -197,58 +196,44 @@ class GetCupertinoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Binds(
binds: [
Bind.lazyPut<GetMaterialController>(
() => GetMaterialController(
ConfigData(
backButtonDispatcher: backButtonDispatcher,
binds: binds,
customTransition: customTransition,
defaultGlobalState: defaultGlobalState,
defaultTransition: defaultTransition,
enableLog: enableLog,
fallbackLocale: fallbackLocale,
getPages: getPages,
home: home,
initialRoute: initialRoute,
locale: locale,
logWriterCallback: logWriterCallback,
navigatorKey: navigatorKey,
navigatorObservers: navigatorObservers,
onDispose: onDispose,
onInit: onInit,
onReady: onReady,
opaqueRoute: opaqueRoute,
popGesture: popGesture,
routeInformationParser: routeInformationParser,
routeInformationProvider: routeInformationProvider,
routerDelegate: routerDelegate,
routingCallback: routingCallback,
scaffoldMessengerKey: GlobalKey<ScaffoldMessengerState>(),
smartManagement: smartManagement,
transitionDuration: transitionDuration,
translations: translations,
translationsKeys: translationsKeys,
unknownRoute: unknownRoute,
),
),
onClose: () {
Get.clearTranslations();
RouterReportManager.dispose();
Get.resetInstance(clearRouteBindings: true);
},
),
...binds,
],
return GetRoot(
config: ConfigData(
backButtonDispatcher: backButtonDispatcher,
binds: binds,
customTransition: customTransition,
defaultGlobalState: defaultGlobalState,
defaultTransition: defaultTransition,
enableLog: enableLog,
fallbackLocale: fallbackLocale,
getPages: getPages,
home: home,
initialRoute: initialRoute,
locale: locale,
logWriterCallback: logWriterCallback,
navigatorKey: navigatorKey,
navigatorObservers: navigatorObservers,
onDispose: onDispose,
onInit: onInit,
onReady: onReady,
routeInformationParser: routeInformationParser,
routeInformationProvider: routeInformationProvider,
routerDelegate: routerDelegate,
routingCallback: routingCallback,
scaffoldMessengerKey: GlobalKey<ScaffoldMessengerState>(),
smartManagement: smartManagement,
transitionDuration: transitionDuration,
translations: translations,
translationsKeys: translationsKeys,
unknownRoute: unknownRoute,
),
child: Builder(builder: (context) {
final controller = context.listen<GetMaterialController>();
final controller = GetRoot.of(context);
return CupertinoApp.router(
routerDelegate: controller.routerDelegate,
routeInformationParser: controller.routeInformationParser,
routerDelegate: controller.config.routerDelegate,
routeInformationParser: controller.config.routeInformationParser,
backButtonDispatcher: backButtonDispatcher,
routeInformationProvider: routeInformationProvider,
key: controller.unikey,
key: controller.config.unikey,
builder: (context, child) => Directionality(
textDirection: textDirection ??
(rtlLanguages.contains(Get.locale?.languageCode)
... ...
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/instance_manager.dart';
import '../../../get_core/get_core.dart';
import '../../../get_instance/get_instance.dart';
import '../../../get_state_manager/get_state_manager.dart';
import '../../../get_utils/get_utils.dart';
import '../../get_navigation.dart';
import '../router_report.dart';
import 'get_root.dart';
class GetMaterialApp extends StatelessWidget {
final GlobalKey<NavigatorState>? navigatorKey;
... ... @@ -193,58 +192,61 @@ class GetMaterialApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Binds(
binds: [
Bind.lazyPut<GetMaterialController>(
() => GetMaterialController(
ConfigData(
backButtonDispatcher: backButtonDispatcher,
binds: binds,
customTransition: customTransition,
defaultGlobalState: defaultGlobalState,
defaultTransition: defaultTransition,
enableLog: enableLog,
fallbackLocale: fallbackLocale,
getPages: getPages,
home: home,
initialRoute: initialRoute,
locale: locale,
logWriterCallback: logWriterCallback,
navigatorKey: navigatorKey,
navigatorObservers: navigatorObservers,
onDispose: onDispose,
onInit: onInit,
onReady: onReady,
opaqueRoute: opaqueRoute,
popGesture: popGesture,
routeInformationParser: routeInformationParser,
routeInformationProvider: routeInformationProvider,
routerDelegate: routerDelegate,
routingCallback: routingCallback,
scaffoldMessengerKey: scaffoldMessengerKey,
smartManagement: smartManagement,
transitionDuration: transitionDuration,
translations: translations,
translationsKeys: translationsKeys,
unknownRoute: unknownRoute,
),
),
onClose: () {
Get.clearTranslations();
RouterReportManager.dispose();
Get.resetInstance(clearRouteBindings: true);
},
),
...binds,
],
return GetRoot(
config: ConfigData(
backButtonDispatcher: backButtonDispatcher,
binds: binds,
customTransition: customTransition,
defaultGlobalState: defaultGlobalState,
defaultTransition: defaultTransition,
enableLog: enableLog,
fallbackLocale: fallbackLocale,
getPages: getPages,
home: home,
initialRoute: initialRoute,
locale: locale,
logWriterCallback: logWriterCallback,
navigatorKey: navigatorKey,
navigatorObservers: navigatorObservers,
onDispose: onDispose,
onInit: onInit,
onReady: onReady,
routeInformationParser: routeInformationParser,
routeInformationProvider: routeInformationProvider,
routerDelegate: routerDelegate,
routingCallback: routingCallback,
scaffoldMessengerKey: scaffoldMessengerKey,
smartManagement: smartManagement,
transitionDuration: transitionDuration,
translations: translations,
translationsKeys: translationsKeys,
unknownRoute: unknownRoute,
theme: theme,
darkTheme: darkTheme,
themeMode: themeMode,
),
// binds: [
// Bind.lazyPut<GetMaterialController>(
// () => GetMaterialController(
// ),
// onClose: () {
// Get.clearTranslations();
// RouterReportManager.dispose();
// Get.resetInstance(clearRouteBindings: true);
// },
// ),
// ...binds,
// ],
child: Builder(builder: (context) {
final controller = context.listen<GetMaterialController>();
final controller = GetRoot.of(context);
print('ROUTERRRR ${controller.config.routerDelegate}');
return MaterialApp.router(
routerDelegate: controller.routerDelegate,
routeInformationParser: controller.routeInformationParser,
routerDelegate: controller.config.routerDelegate,
routeInformationParser: controller.config.routeInformationParser,
backButtonDispatcher: backButtonDispatcher,
routeInformationProvider: routeInformationProvider,
key: controller.unikey,
key: controller.config.unikey,
builder: (context, child) => Directionality(
textDirection: textDirection ??
(rtlLanguages.contains(Get.locale?.languageCode)
... ... @@ -257,15 +259,13 @@ class GetMaterialApp extends StatelessWidget {
title: title,
onGenerateTitle: onGenerateTitle,
color: color,
theme: controller.theme ?? theme ?? ThemeData.fallback(),
darkTheme: controller.darkTheme ??
darkTheme ??
theme ??
theme: controller.config.theme ?? ThemeData.fallback(),
darkTheme: controller.config.darkTheme ??
controller.config.theme ??
ThemeData.fallback(),
themeMode: controller.themeMode ?? themeMode,
themeMode: controller.config.themeMode,
locale: Get.locale ?? locale,
scaffoldMessengerKey:
scaffoldMessengerKey ?? controller.scaffoldMessengerKey,
scaffoldMessengerKey: controller.config.scaffoldMessengerKey,
localizationsDelegates: localizationsDelegates,
localeListResolutionCallback: localeListResolutionCallback,
localeResolutionCallback: localeResolutionCallback,
... ...
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import '../../../get.dart';
import '../router_report.dart';
class ConfigData {
final ValueChanged<Routing?>? routingCallback;
final Transition? defaultTransition;
final VoidCallback? onInit;
final VoidCallback? onReady;
final VoidCallback? onDispose;
final bool? enableLog;
final LogWriterCallback? logWriterCallback;
final SmartManagement smartManagement;
final List<Bind> binds;
final Duration? transitionDuration;
final bool? defaultGlobalState;
final List<GetPage>? getPages;
final GetPage? unknownRoute;
final RouteInformationProvider? routeInformationProvider;
final RouteInformationParser<Object>? routeInformationParser;
final RouterDelegate<Object>? routerDelegate;
final BackButtonDispatcher? backButtonDispatcher;
final List<NavigatorObserver>? navigatorObservers;
final GlobalKey<NavigatorState>? navigatorKey;
final GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey;
final Map<String, Map<String, String>>? translationsKeys;
final Translations? translations;
final Locale? locale;
final Locale? fallbackLocale;
final String? initialRoute;
final CustomTransition? customTransition;
final Widget? home;
final bool testMode;
final Key? unikey;
final ThemeData? theme;
final ThemeData? darkTheme;
final ThemeMode? themeMode;
final bool defaultPopGesture;
final bool defaultOpaqueRoute;
final Duration defaultTransitionDuration;
final Curve defaultTransitionCurve;
final Curve defaultDialogTransitionCurve;
final Duration defaultDialogTransitionDuration;
final Routing routing;
final Map<String, String?> parameters;
ConfigData({
required this.routingCallback,
required this.defaultTransition,
required this.onInit,
required this.onReady,
required this.onDispose,
required this.enableLog,
required this.logWriterCallback,
required this.smartManagement,
required this.binds,
required this.transitionDuration,
required this.defaultGlobalState,
required this.getPages,
required this.unknownRoute,
required this.routeInformationProvider,
required this.routeInformationParser,
required this.routerDelegate,
required this.backButtonDispatcher,
required this.navigatorObservers,
required this.navigatorKey,
required this.scaffoldMessengerKey,
required this.translationsKeys,
required this.translations,
required this.locale,
required this.fallbackLocale,
required this.initialRoute,
required this.customTransition,
required this.home,
this.theme,
this.darkTheme,
this.themeMode,
this.unikey,
this.testMode = false,
this.defaultOpaqueRoute = true,
this.defaultTransitionDuration = const Duration(milliseconds: 300),
this.defaultTransitionCurve = Curves.easeOutQuad,
this.defaultDialogTransitionCurve = Curves.easeOutQuad,
this.defaultDialogTransitionDuration = const Duration(milliseconds: 300),
this.parameters = const {},
Routing? routing,
bool? defaultPopGesture,
}) : defaultPopGesture = defaultPopGesture ?? GetPlatform.isIOS,
routing = routing ?? Routing();
ConfigData copyWith({
ValueChanged<Routing?>? routingCallback,
Transition? defaultTransition,
VoidCallback? onInit,
VoidCallback? onReady,
VoidCallback? onDispose,
bool? enableLog,
LogWriterCallback? logWriterCallback,
SmartManagement? smartManagement,
List<Bind>? binds,
Duration? transitionDuration,
bool? defaultGlobalState,
List<GetPage>? getPages,
GetPage? unknownRoute,
RouteInformationProvider? routeInformationProvider,
RouteInformationParser<Object>? routeInformationParser,
RouterDelegate<Object>? routerDelegate,
BackButtonDispatcher? backButtonDispatcher,
List<NavigatorObserver>? navigatorObservers,
GlobalKey<NavigatorState>? navigatorKey,
GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey,
Map<String, Map<String, String>>? translationsKeys,
Translations? translations,
Locale? locale,
Locale? fallbackLocale,
String? initialRoute,
CustomTransition? customTransition,
Widget? home,
bool? testMode,
Key? unikey,
ThemeData? theme,
ThemeData? darkTheme,
ThemeMode? themeMode,
bool? defaultPopGesture,
bool? defaultOpaqueRoute,
Duration? defaultTransitionDuration,
Curve? defaultTransitionCurve,
Curve? defaultDialogTransitionCurve,
Duration? defaultDialogTransitionDuration,
Routing? routing,
Map<String, String?>? parameters,
}) {
return ConfigData(
routingCallback: routingCallback ?? this.routingCallback,
defaultTransition: defaultTransition ?? this.defaultTransition,
onInit: onInit ?? this.onInit,
onReady: onReady ?? this.onReady,
onDispose: onDispose ?? this.onDispose,
enableLog: enableLog ?? this.enableLog,
logWriterCallback: logWriterCallback ?? this.logWriterCallback,
smartManagement: smartManagement ?? this.smartManagement,
binds: binds ?? this.binds,
transitionDuration: transitionDuration ?? this.transitionDuration,
defaultGlobalState: defaultGlobalState ?? this.defaultGlobalState,
getPages: getPages ?? this.getPages,
unknownRoute: unknownRoute ?? this.unknownRoute,
routeInformationProvider:
routeInformationProvider ?? this.routeInformationProvider,
routeInformationParser:
routeInformationParser ?? this.routeInformationParser,
routerDelegate: routerDelegate ?? this.routerDelegate,
backButtonDispatcher: backButtonDispatcher ?? this.backButtonDispatcher,
navigatorObservers: navigatorObservers ?? this.navigatorObservers,
navigatorKey: navigatorKey ?? this.navigatorKey,
scaffoldMessengerKey: scaffoldMessengerKey ?? this.scaffoldMessengerKey,
translationsKeys: translationsKeys ?? this.translationsKeys,
translations: translations ?? this.translations,
locale: locale ?? this.locale,
fallbackLocale: fallbackLocale ?? this.fallbackLocale,
initialRoute: initialRoute ?? this.initialRoute,
customTransition: customTransition ?? this.customTransition,
home: home ?? this.home,
testMode: testMode ?? this.testMode,
unikey: unikey ?? this.unikey,
theme: theme ?? this.theme,
darkTheme: darkTheme ?? this.darkTheme,
themeMode: themeMode ?? this.themeMode,
defaultPopGesture: defaultPopGesture ?? this.defaultPopGesture,
defaultOpaqueRoute: defaultOpaqueRoute ?? this.defaultOpaqueRoute,
defaultTransitionDuration:
defaultTransitionDuration ?? this.defaultTransitionDuration,
defaultTransitionCurve:
defaultTransitionCurve ?? this.defaultTransitionCurve,
defaultDialogTransitionCurve:
defaultDialogTransitionCurve ?? this.defaultDialogTransitionCurve,
defaultDialogTransitionDuration: defaultDialogTransitionDuration ??
this.defaultDialogTransitionDuration,
routing: routing ?? this.routing,
parameters: parameters ?? this.parameters,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ConfigData &&
other.routingCallback == routingCallback &&
other.defaultTransition == defaultTransition &&
other.onInit == onInit &&
other.onReady == onReady &&
other.onDispose == onDispose &&
other.enableLog == enableLog &&
other.logWriterCallback == logWriterCallback &&
other.smartManagement == smartManagement &&
listEquals(other.binds, binds) &&
other.transitionDuration == transitionDuration &&
other.defaultGlobalState == defaultGlobalState &&
listEquals(other.getPages, getPages) &&
other.unknownRoute == unknownRoute &&
other.routeInformationProvider == routeInformationProvider &&
other.routeInformationParser == routeInformationParser &&
other.routerDelegate == routerDelegate &&
other.backButtonDispatcher == backButtonDispatcher &&
listEquals(other.navigatorObservers, navigatorObservers) &&
other.navigatorKey == navigatorKey &&
other.scaffoldMessengerKey == scaffoldMessengerKey &&
mapEquals(other.translationsKeys, translationsKeys) &&
other.translations == translations &&
other.locale == locale &&
other.fallbackLocale == fallbackLocale &&
other.initialRoute == initialRoute &&
other.customTransition == customTransition &&
other.home == home &&
other.testMode == testMode &&
other.unikey == unikey &&
other.theme == theme &&
other.darkTheme == darkTheme &&
other.themeMode == themeMode &&
other.defaultPopGesture == defaultPopGesture &&
other.defaultOpaqueRoute == defaultOpaqueRoute &&
other.defaultTransitionDuration == defaultTransitionDuration &&
other.defaultTransitionCurve == defaultTransitionCurve &&
other.defaultDialogTransitionCurve == defaultDialogTransitionCurve &&
other.defaultDialogTransitionDuration ==
defaultDialogTransitionDuration &&
other.routing == routing &&
mapEquals(other.parameters, parameters);
}
@override
int get hashCode {
return routingCallback.hashCode ^
defaultTransition.hashCode ^
onInit.hashCode ^
onReady.hashCode ^
onDispose.hashCode ^
enableLog.hashCode ^
logWriterCallback.hashCode ^
smartManagement.hashCode ^
binds.hashCode ^
transitionDuration.hashCode ^
defaultGlobalState.hashCode ^
getPages.hashCode ^
unknownRoute.hashCode ^
routeInformationProvider.hashCode ^
routeInformationParser.hashCode ^
routerDelegate.hashCode ^
backButtonDispatcher.hashCode ^
navigatorObservers.hashCode ^
navigatorKey.hashCode ^
scaffoldMessengerKey.hashCode ^
translationsKeys.hashCode ^
translations.hashCode ^
locale.hashCode ^
fallbackLocale.hashCode ^
initialRoute.hashCode ^
customTransition.hashCode ^
home.hashCode ^
testMode.hashCode ^
unikey.hashCode ^
theme.hashCode ^
darkTheme.hashCode ^
themeMode.hashCode ^
defaultPopGesture.hashCode ^
defaultOpaqueRoute.hashCode ^
defaultTransitionDuration.hashCode ^
defaultTransitionCurve.hashCode ^
defaultDialogTransitionCurve.hashCode ^
defaultDialogTransitionDuration.hashCode ^
routing.hashCode ^
parameters.hashCode;
}
}
class GetRoot extends StatefulWidget {
GetRoot({
Key? key,
required this.config,
required this.child,
}) : super(key: key);
final ConfigData config;
final Widget child;
@override
State<GetRoot> createState() => GetRootState();
static GetRootState of(BuildContext context) {
// Handles the case where the input context is a navigator element.
GetRootState? root;
if (context is StatefulElement && context.state is GetRootState) {
root = context.state as GetRootState;
}
root = context.findRootAncestorStateOfType<GetRootState>() ?? root;
assert(() {
if (root == null) {
throw FlutterError(
'GetRoot operation requested with a context that does not include a GetRoot.\n'
'The context used must be that of a '
'widget that is a descendant of a GetRoot widget.',
);
}
return true;
}());
return root!;
}
}
class GetRootState extends State<GetRoot> with WidgetsBindingObserver {
static GetRootState? _controller;
static GetRootState get controller {
if (_controller == null) {
throw Exception('GetRoot is not part of the three');
} else {
return _controller!;
}
}
late ConfigData config;
@override
void initState() {
config = widget.config;
GetRootState._controller = this;
ambiguate(Engine.instance)!.addObserver(this);
onInit();
super.initState();
}
// @override
// void didUpdateWidget(covariant GetRoot oldWidget) {
// if (oldWidget.config != widget.config) {
// config = widget.config;
// }
// super.didUpdateWidget(oldWidget);
// }
void onClose() {
config.onDispose?.call();
Get.clearTranslations();
RouterReportManager.instance.clearRouteKeys();
RouterReportManager.dispose();
Get.resetInstance(clearRouteBindings: true);
_controller = null;
ambiguate(Engine.instance)!.removeObserver(this);
}
@override
void dispose() {
onClose();
super.dispose();
}
void onInit() {
if (config.getPages == null && config.home == null) {
throw 'You need add pages or home';
}
if (config.routerDelegate == null) {
final newDelegate = GetDelegate.createDelegate(
pages: config.getPages ??
[
GetPage(
name: cleanRouteName("/${config.home.runtimeType}"),
page: () => config.home!,
),
],
notFoundRoute: config.unknownRoute,
navigatorKey: config.navigatorKey,
navigatorObservers: (config.navigatorObservers == null
? <NavigatorObserver>[
GetObserver(config.routingCallback, Get.routing)
]
: <NavigatorObserver>[
GetObserver(config.routingCallback, config.routing),
...config.navigatorObservers!
]),
);
config = config.copyWith(routerDelegate: newDelegate);
}
if (config.routeInformationParser == null) {
final newRouteInformationParser =
GetInformationParser.createInformationParser(
initialRoute: config.initialRoute ??
config.getPages?.first.name ??
cleanRouteName("/${config.home.runtimeType}"),
);
config =
config.copyWith(routeInformationParser: newRouteInformationParser);
}
if (config.locale != null) Get.locale = config.locale;
if (config.fallbackLocale != null) {
Get.fallbackLocale = config.fallbackLocale;
}
if (config.translations != null) {
Get.addTranslations(config.translations!.keys);
} else if (config.translationsKeys != null) {
Get.addTranslations(config.translationsKeys!);
}
Get.smartManagement = config.smartManagement;
config.onInit?.call();
Get.isLogEnable = config.enableLog ?? kDebugMode;
Get.log = config.logWriterCallback ?? defaultLogWriterCallback;
if (config.defaultTransition == null) {
config = config.copyWith(defaultTransition: getThemeTransition());
}
// defaultOpaqueRoute = config.opaqueRoute ?? true;
// defaultPopGesture = config.popGesture ?? GetPlatform.isIOS;
// defaultTransitionDuration =
// config.transitionDuration ?? Duration(milliseconds: 300);
Future(() => onReady());
}
set parameters(Map<String, String?> newParameters) {
// rootController.parameters = newParameters;
config = config.copyWith(parameters: newParameters);
}
set testMode(bool isTest) {
config = config.copyWith(testMode: isTest);
// _getxController.testMode = isTest;
}
void onReady() {
config.onReady?.call();
}
Transition? getThemeTransition() {
final platform = Get.theme.platform;
final matchingTransition =
Get.theme.pageTransitionsTheme.builders[platform];
switch (matchingTransition) {
case CupertinoPageTransitionsBuilder():
return Transition.cupertino;
case ZoomPageTransitionsBuilder():
return Transition.zoom;
case FadeUpwardsPageTransitionsBuilder():
return Transition.fade;
case OpenUpwardsPageTransitionsBuilder():
return Transition.native;
default:
return null;
}
}
@override
void didChangeLocales(List<Locale>? locales) {
Get.asap(() {
final locale = Get.deviceLocale;
if (locale != null) {
Get.updateLocale(locale);
}
});
}
void setTheme(ThemeData value) {
if (config.darkTheme == null) {
config = config.copyWith(theme: value);
} else {
if (value.brightness == Brightness.light) {
config = config.copyWith(theme: value);
} else {
config = config.copyWith(darkTheme: value);
}
}
update();
}
void setThemeMode(ThemeMode value) {
config = config.copyWith(themeMode: value);
update();
}
void restartApp() {
config = config.copyWith(unikey: UniqueKey());
update();
}
void update() {
setState(() {});
}
GlobalKey<NavigatorState> get key => rootDelegate.navigatorKey;
GetDelegate get rootDelegate => config.routerDelegate as GetDelegate;
RouteInformationParser<Object> get informationParser =>
config.routeInformationParser!;
GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
rootDelegate.navigatorKey = newKey;
return key;
}
Map<dynamic, GetDelegate> keys = {};
GetDelegate? nestedKey(String? key) {
if (key == null) {
return rootDelegate;
}
keys.putIfAbsent(
key,
() => GetDelegate(
showHashOnUrl: true,
//debugLabel: 'Getx nested key: ${key.toString()}',
pages: RouteDecoder.fromRoute(key).currentChildrens ?? [],
),
);
return keys[key];
}
@override
Widget build(BuildContext context) {
return widget.child;
}
String cleanRouteName(String name) {
name = name.replaceAll('() => ', '');
/// uncommonent for URL styling.
// name = name.paramCase!;
if (!name.startsWith('/')) {
name = '/$name';
}
return Uri.tryParse(name)?.toString() ?? name;
}
}
... ...
... ... @@ -3,278 +3,49 @@ import 'package:flutter/material.dart';
import '../../../get.dart';
class ConfigData {
final ValueChanged<Routing?>? routingCallback;
final Transition? defaultTransition;
final bool? opaqueRoute;
final VoidCallback? onInit;
final VoidCallback? onReady;
final VoidCallback? onDispose;
final bool? enableLog;
final LogWriterCallback? logWriterCallback;
final bool? popGesture;
final SmartManagement smartManagement;
final List<Bind> binds;
final Duration? transitionDuration;
final bool? defaultGlobalState;
final List<GetPage>? getPages;
final GetPage? unknownRoute;
final RouteInformationProvider? routeInformationProvider;
final RouteInformationParser<Object>? routeInformationParser;
final RouterDelegate<Object>? routerDelegate;
final BackButtonDispatcher? backButtonDispatcher;
final List<NavigatorObserver>? navigatorObservers;
final GlobalKey<NavigatorState>? navigatorKey;
final GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey;
final Map<String, Map<String, String>>? translationsKeys;
final Translations? translations;
final Locale? locale;
final Locale? fallbackLocale;
final String? initialRoute;
final CustomTransition? customTransition;
final Widget? home;
ConfigData({
required this.routingCallback,
required this.defaultTransition,
required this.opaqueRoute,
required this.onInit,
required this.onReady,
required this.onDispose,
required this.enableLog,
required this.logWriterCallback,
required this.popGesture,
required this.smartManagement,
required this.binds,
required this.transitionDuration,
required this.defaultGlobalState,
required this.getPages,
required this.unknownRoute,
required this.routeInformationProvider,
required this.routeInformationParser,
required this.routerDelegate,
required this.backButtonDispatcher,
required this.navigatorObservers,
required this.navigatorKey,
required this.scaffoldMessengerKey,
required this.translationsKeys,
required this.translations,
required this.locale,
required this.fallbackLocale,
required this.initialRoute,
required this.customTransition,
required this.home,
});
}
class GetMaterialController extends FullLifeCycleController {
GetMaterialController(this.config);
late final RouterDelegate<Object> routerDelegate;
late final RouteInformationParser<Object> routeInformationParser;
final ConfigData config;
@override
void onReady() {
config.onReady?.call();
super.onReady();
}
@override
void onInit() {
super.onInit();
if (config.getPages == null && config.home == null) {
throw 'You need add pages or home';
}
print('route delefate from onInit');
routerDelegate = config.routerDelegate ??
createDelegate(
pages: config.getPages ??
[
GetPage(
name: cleanRouteName("/${config.home.runtimeType}"),
page: () => config.home!,
),
],
notFoundRoute: config.unknownRoute,
navigatorKey: config.navigatorKey,
navigatorObservers: (config.navigatorObservers == null
? <NavigatorObserver>[
GetObserver(config.routingCallback, Get.routing)
]
: <NavigatorObserver>[
GetObserver(config.routingCallback, routing),
...config.navigatorObservers!
]),
);
routeInformationParser = config.routeInformationParser ??
createInformationParser(
initialRoute: config.initialRoute ??
config.getPages?.first.name ??
cleanRouteName("/${config.home.runtimeType}"),
);
if (config.locale != null) Get.locale = config.locale;
if (config.fallbackLocale != null) {
Get.fallbackLocale = config.fallbackLocale;
}
if (config.translations != null) {
Get.addTranslations(config.translations!.keys);
} else if (config.translationsKeys != null) {
Get.addTranslations(config.translationsKeys!);
}
customTransition = config.customTransition;
Get.smartManagement = config.smartManagement;
config.onInit?.call();
Get.isLogEnable = config.enableLog ?? kDebugMode;
Get.log = config.logWriterCallback ?? defaultLogWriterCallback;
defaultTransition = config.defaultTransition ?? getThemeTransition();
defaultOpaqueRoute = config.opaqueRoute ?? true;
defaultPopGesture = config.popGesture ?? GetPlatform.isIOS;
defaultTransitionDuration =
config.transitionDuration ?? Duration(milliseconds: 300);
}
Transition? getThemeTransition() {
final platform = Get.theme.platform;
final matchingTransition =
Get.theme.pageTransitionsTheme.builders[platform];
switch (matchingTransition) {
case CupertinoPageTransitionsBuilder():
return Transition.cupertino;
case ZoomPageTransitionsBuilder():
return Transition.zoom;
case FadeUpwardsPageTransitionsBuilder():
return Transition.fade;
case OpenUpwardsPageTransitionsBuilder():
return Transition.native;
default:
return null;
}
}
String cleanRouteName(String name) {
name = name.replaceAll('() => ', '');
/// uncommonent for URL styling.
// name = name.paramCase!;
if (!name.startsWith('/')) {
name = '/$name';
}
return Uri.tryParse(name)?.toString() ?? name;
}
bool testMode = false;
Key? unikey;
ThemeData? theme;
ThemeData? darkTheme;
ThemeMode? themeMode;
final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
bool defaultPopGesture = GetPlatform.isIOS;
bool defaultOpaqueRoute = true;
Transition? defaultTransition;
Duration defaultTransitionDuration = Duration(milliseconds: 300);
Curve defaultTransitionCurve = Curves.easeOutQuad;
Curve defaultDialogTransitionCurve = Curves.easeOutQuad;
Duration defaultDialogTransitionDuration = Duration(milliseconds: 300);
final routing = Routing();
Map<String, String?> parameters = {};
CustomTransition? customTransition;
Map<dynamic, GetDelegate> keys = {};
GlobalKey<NavigatorState> get key => rootDelegate.navigatorKey;
GetDelegate get rootDelegate => routerDelegate as GetDelegate;
GlobalKey<NavigatorState>? addKey(GlobalKey<NavigatorState> newKey) {
rootDelegate.navigatorKey = newKey;
return key;
}
@override
void didChangeLocales(List<Locale>? locales) {
Get.asap(() {
final locale = Get.deviceLocale;
if (locale != null) {
Get.updateLocale(locale);
}
});
}
void restartApp() {
unikey = UniqueKey();
update();
}
void setTheme(ThemeData value) {
if (darkTheme == null) {
theme = value;
} else {
if (value.brightness == Brightness.light) {
theme = value;
} else {
darkTheme = value;
}
}
update();
}
void setThemeMode(ThemeMode value) {
themeMode = value;
update();
}
GetDelegate? nestedKey(String? key) {
if (key == null) {
return routerDelegate as GetDelegate;
}
keys.putIfAbsent(
key,
() => GetDelegate(
showHashOnUrl: true,
//debugLabel: 'Getx nested key: ${key.toString()}',
pages: RouteDecoder.fromRoute(key).currentChildrens ?? [],
),
);
return keys[key];
}
GetInformationParser createInformationParser({String initialRoute = '/'}) {
return GetInformationParser(
initialRoute: initialRoute,
);
}
GetDelegate createDelegate({
GetPage<dynamic>? notFoundRoute,
List<GetPage> pages = const [],
List<NavigatorObserver>? navigatorObservers,
TransitionDelegate<dynamic>? transitionDelegate,
PopMode backButtonPopMode = PopMode.history,
PreventDuplicateHandlingMode preventDuplicateHandlingMode =
PreventDuplicateHandlingMode.reorderRoutes,
GlobalKey<NavigatorState>? navigatorKey,
}) {
return GetDelegate(
notFoundRoute: notFoundRoute,
navigatorObservers: navigatorObservers,
transitionDelegate: transitionDelegate,
backButtonPopMode: backButtonPopMode,
preventDuplicateHandlingMode: preventDuplicateHandlingMode,
pages: pages,
navigatorKey: navigatorKey,
);
}
}
// class GetMaterialController extends FullLifeCycleController {
// GetMaterialController(this.config);
// // late final RouterDelegate<Object> routerDelegate;
// // late final RouteInformationParser<Object> routeInformationParser;
// final ConfigData config;
// // bool testMode = false;
// // Key? unikey;
// // ThemeData? theme;
// // ThemeData? darkTheme;
// // ThemeMode? themeMode;
// // final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
// // bool defaultPopGesture = GetPlatform.isIOS;
// // bool defaultOpaqueRoute = true;
// // Transition? defaultTransition;
// // Duration defaultTransitionDuration = Duration(milliseconds: 300);
// // Curve defaultTransitionCurve = Curves.easeOutQuad;
// // Curve defaultDialogTransitionCurve = Curves.easeOutQuad;
// // Duration defaultDialogTransitionDuration = Duration(milliseconds: 300);
// // final routing = Routing();
// // Map<String, String?> parameters = {};
// // CustomTransition? customTransition;
// // Map<dynamic, GetDelegate> keys = {};
// // GetDelegate? nestedKey(String? key) {
// // if (key == null) {
// // return routerDelegate as GetDelegate;
// // }
// // keys.putIfAbsent(
// // key,
// // () => GetDelegate(
// // showHashOnUrl: true,
// // //debugLabel: 'Getx nested key: ${key.toString()}',
// // pages: RouteDecoder.fromRoute(key).currentChildrens ?? [],
// // ),
// // );
// // return keys[key];
// // }
// }
... ...
import 'dart:collection';
import 'package:flutter/widgets.dart';
import '../../get.dart';
class RouterReportManager<T> {
... ...
... ... @@ -4,6 +4,11 @@ import 'package:flutter/widgets.dart';
import '../../../get.dart';
class GetInformationParser extends RouteInformationParser<RouteDecoder> {
factory GetInformationParser.createInformationParser(
{String initialRoute = '/'}) {
return GetInformationParser(initialRoute: initialRoute);
}
final String initialRoute;
GetInformationParser({
... ... @@ -19,7 +24,7 @@ class GetInformationParser extends RouteInformationParser<RouteDecoder> {
if (location == '/') {
//check if there is a corresponding page
//if not, relocate to initialRoute
if (!(Get.rootController.routerDelegate as GetDelegate)
if (!(Get.rootController.rootDelegate)
.registeredRoutes
.any((element) => element.name == '/')) {
location = initialRoute;
... ...
... ... @@ -43,8 +43,10 @@ class GetPage<T> extends Page<T> {
@override
final String name;
final bool inheritParentPath;
final List<GetPage> children;
final List<GetMiddleware>? middlewares;
final List<GetMiddleware> middlewares;
final PathDecoded path;
final GetPage? unknownRoute;
final bool showCupertinoParallax;
... ... @@ -73,7 +75,7 @@ class GetPage<T> extends Page<T> {
this.customTransition,
this.fullscreenDialog = false,
this.children = const <GetPage>[],
this.middlewares,
this.middlewares = const [],
this.unknownRoute,
this.arguments,
this.showCupertinoParallax = true,
... ... @@ -81,6 +83,7 @@ class GetPage<T> extends Page<T> {
this.preventDuplicateHandlingMode =
PreventDuplicateHandlingMode.reorderRoutes,
this.completer,
this.inheritParentPath = true,
LocalKey? key,
}) : path = _nameToRegex(name),
assert(name.startsWith('/'),
... ... @@ -92,7 +95,7 @@ class GetPage<T> extends Page<T> {
);
// settings = RouteSettings(name: name, arguments: Get.arguments);
GetPage<T> copy({
GetPage<T> copyWith({
LocalKey? key,
String? name,
GetPageBuilder? page,
... ... @@ -121,6 +124,7 @@ class GetPage<T> extends Page<T> {
Object? arguments,
bool? showCupertinoParallax,
Completer<T?>? completer,
bool? inheritParentPath,
}) {
return GetPage(
key: key ?? this.key,
... ... @@ -153,6 +157,7 @@ class GetPage<T> extends Page<T> {
showCupertinoParallax:
showCupertinoParallax ?? this.showCupertinoParallax,
completer: completer ?? this.completer,
inheritParentPath: inheritParentPath ?? this.inheritParentPath,
);
}
... ...
... ... @@ -12,6 +12,27 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
ChangeNotifier,
PopNavigatorRouterDelegateMixin<RouteDecoder>,
IGetNavigation {
factory GetDelegate.createDelegate({
GetPage<dynamic>? notFoundRoute,
List<GetPage> pages = const [],
List<NavigatorObserver>? navigatorObservers,
TransitionDelegate<dynamic>? transitionDelegate,
PopMode backButtonPopMode = PopMode.history,
PreventDuplicateHandlingMode preventDuplicateHandlingMode =
PreventDuplicateHandlingMode.reorderRoutes,
GlobalKey<NavigatorState>? navigatorKey,
}) {
return GetDelegate(
notFoundRoute: notFoundRoute,
navigatorObservers: navigatorObservers,
transitionDelegate: transitionDelegate,
backButtonPopMode: backButtonPopMode,
preventDuplicateHandlingMode: preventDuplicateHandlingMode,
pages: pages,
navigatorKey: navigatorKey,
);
}
final List<RouteDecoder> _activePages = <RouteDecoder>[];
final PopMode backButtonPopMode;
final PreventDuplicateHandlingMode preventDuplicateHandlingMode;
... ... @@ -84,7 +105,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
Future<RouteDecoder?> runMiddleware(RouteDecoder config) async {
final middlewares = config.currentTreeBranch.last.middlewares;
if (middlewares == null) {
if (middlewares.isEmpty) {
return config;
}
var iterator = config;
... ... @@ -145,10 +166,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
return currentConfiguration?.pageSettings;
}
Future<T?> _removeHistoryEntry<T>(RouteDecoder entry, T result) async {
return _unsafeHistoryRemove<T>(entry, result);
}
Future<void> _pushHistory(RouteDecoder config) async {
if (config.route!.preventDuplicates) {
final originalEntryIndex = _activePages.indexWhere(
... ... @@ -560,7 +577,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
_activePages.remove(RouteDecoder.fromRoute(name));
}
bool get canBack {
return _activePages.length > 1;
}
... ... @@ -691,7 +707,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
decoder.parameters.addAll(parameters);
}
decoder.route = decoder.route?.copy(
decoder.route = decoder.route?.copyWith(
completer: _activePages.isEmpty ? null : Completer(),
arguments: arguments,
parameters: parameters,
... ... @@ -786,7 +802,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
if (wasPopup) return true;
if (_canPop(popMode ?? backButtonPopMode)) {
await _pop(popMode ?? backButtonPopMode, result);
await _pop(popMode ?? backButtonPopMode, result);
notifyListeners();
return true;
}
... ... @@ -801,7 +817,6 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
notifyListeners();
}
bool _onPopVisualRoute(Route<dynamic> route, dynamic result) {
final didPop = route.didPop(result);
if (!didPop) {
... ...
... ... @@ -7,6 +7,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import '../../../get.dart';
import '../root/get_root.dart';
const double _kBackGestureWidth = 20.0;
... ... @@ -716,8 +717,8 @@ Cannot read the previousTitle for a route that has not yet been installed''',
));
default:
final customTransition =
context.get<GetMaterialController>().customTransition;
final customTransition = GetRoot.of(context).config.customTransition;
if (customTransition != null) {
return customTransition.buildTransition(context, route.curve,
route.alignment, animation, secondaryAnimation, child);
... ...
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'get_route.dart';
class RouteMatcher {
final RouteNode _root = RouteNode('/', '/');
RouteNode addRoute(String path) {
final segments = _parsePath(path);
var currentNode = _root;
for (final segment in segments) {
final existingChild = currentNode.findChild(segment);
if (existingChild != null) {
currentNode = existingChild;
} else {
final newChild = RouteNode(segment, path);
currentNode.addChild(newChild);
currentNode = newChild;
}
}
return currentNode;
}
void removeRoute(String path) {
final segments = _parsePath(path);
var currentNode = _root;
RouteNode? nodeToDelete;
// Traverse the tree to find the node to delete
for (final segment in segments) {
final child = currentNode.findChild(segment);
if (child == null) {
return; // Node not found, nothing to delete
}
if (child.nodeSegments.length == segments.length) {
nodeToDelete = child;
break;
}
currentNode = child;
}
if (nodeToDelete == null) {
return; // Node not found, nothing to delete
}
final parent = nodeToDelete.parent!;
parent.nodeSegments.remove(nodeToDelete);
}
RouteNode? _findChild(RouteNode currentNode, String segment) {
return currentNode.nodeSegments
.firstWhereOrNull((node) => node.matches(segment));
}
MatchResult? matchRoute(String path) {
final uri = Uri.parse(path);
final segments = _parsePath(uri.path);
var currentNode = _root;
final parameters = <String, String>{};
final urlParameters = uri.queryParameters;
for (final segment in segments) {
if (segment.isEmpty) continue;
final child = _findChild(currentNode, segment);
if (child == null) {
return null;
} else {
if (child.path.startsWith(':')) {
parameters[child.path.substring(1)] = segment;
}
if (child.nodeSegments.length == segments.length) {
return null;
}
currentNode = child;
}
}
return MatchResult(
currentNode,
parameters,
path,
urlParameters: urlParameters,
);
}
List<String> _parsePath(String path) {
return path.split('/').where((segment) => segment.isNotEmpty).toList();
}
}
class RouteTreeResult {
final GetPage? route;
final MatchResult matchResult;
RouteTreeResult({
required this.route,
required this.matchResult,
});
@override
String toString() {
return 'RouteTreeResult(route: $route, matchResult: $matchResult)';
}
RouteTreeResult configure(String page, Object? arguments) {
return copyWith(
route: route?.copyWith(
key: ValueKey(page),
settings: RouteSettings(name: page, arguments: arguments),
completer: Completer(),
arguments: arguments,
));
}
RouteTreeResult copyWith({
GetPage? route,
MatchResult? matchResult,
}) {
return RouteTreeResult(
route: route ?? this.route,
matchResult: matchResult ?? this.matchResult,
);
}
}
class RouteTree {
static final instance = RouteTree();
final Map<String, GetPage> tree = {};
final RouteMatcher matcher = RouteMatcher();
void addRoute(GetPage route) {
matcher.addRoute(route.name);
tree[route.name] = route;
handleChild(route);
}
void addRoutes(List<GetPage> routes) {
for (var route in routes) {
addRoute(route);
}
}
void handleChild(GetPage route) {
final children = route.children;
for (var child in children) {
final middlewares = List.of(route.middlewares);
final bindings = List.of(route.bindings);
middlewares.addAll(child.middlewares);
bindings.addAll(child.bindings);
child = child.copyWith(middlewares: middlewares, bindings: bindings);
if (child.inheritParentPath) {
child = child.copyWith(
name: ('${route.path}/${child.path}').replaceAll(r'//', '/'));
}
addRoute(child);
}
}
void removeRoute(GetPage route) {
matcher.removeRoute(route.name);
tree.remove(route.path);
}
void removeRoutes(List<GetPage> routes) {
for (var route in routes) {
removeRoute(route);
}
}
RouteTreeResult? matchRoute(String path) {
final matchResult = matcher.matchRoute(path);
if (matchResult != null) {
final route = tree[matchResult.node.originalPath];
return RouteTreeResult(
route: route,
matchResult: matchResult,
);
}
return null;
}
}
/// A class representing the result of a route matching operation.
class MatchResult {
/// The route found that matches the result
final RouteNode node;
/// The current path of match, eg: adding 'user/:id' the match result for 'user/123' will be: 'user/123'
final String currentPath;
/// Route parameters eg: adding 'user/:id' the match result for 'user/123' will be: {id: 123}
final Map<String, String> parameters;
/// Route url parameters eg: adding 'user' the match result for 'user?foo=bar' will be: {foo: bar}
final Map<String, String> urlParameters;
MatchResult(this.node, this.parameters, this.currentPath,
{this.urlParameters = const {}});
@override
String toString() =>
'MatchResult(node: $node, currentPath: $currentPath, parameters: $parameters, urlParameters: $urlParameters)';
}
// A class representing a node in a routing tree.
class RouteNode {
String path;
String originalPath;
RouteNode? parent;
List<RouteNode> nodeSegments = [];
RouteNode(this.path, this.originalPath, {this.parent});
bool get isRoot => parent == null;
String get fullPath {
if (isRoot) {
return '/';
} else {
final parentPath = parent?.fullPath == '/' ? '' : parent?.fullPath;
return '$parentPath/$path';
}
}
bool get hasChildren => nodeSegments.isNotEmpty;
void addChild(RouteNode child) {
nodeSegments.add(child);
child.parent = this;
}
RouteNode? findChild(String name) {
return nodeSegments.firstWhereOrNull((node) => node.path == name);
}
bool matches(String name) {
return name == path || path == '*' || path.startsWith(':');
}
@override
String toString() =>
'RouteNode(name: $path, nodeSegments: $nodeSegments, fullPath: $fullPath )';
}
extension Foo<T> on Iterable<T> {
T? firstWhereOrNull(bool Function(T element) test) {
for (var element in this) {
if (test(element)) return element;
}
return null;
}
}
... ...
... ... @@ -14,9 +14,9 @@ class RouteDecoder {
factory RouteDecoder.fromRoute(String location) {
var uri = Uri.parse(location);
final args = PageSettings(uri);
final decoder = (Get.rootController.routerDelegate as GetDelegate)
.matchRoute(location, arguments: args);
decoder.route = decoder.route?.copy(
final decoder =
(Get.rootController.rootDelegate).matchRoute(location, arguments: args);
decoder.route = decoder.route?.copyWith(
completer: null,
arguments: args,
parameters: args.params,
... ... @@ -60,7 +60,7 @@ class RouteDecoder {
final _route = route;
if (_route != null) {
final index = currentTreeBranch.indexOf(_route);
currentTreeBranch[index] = _route.copy(arguments: arguments);
currentTreeBranch[index] = _route.copyWith(arguments: arguments);
}
}
... ... @@ -86,7 +86,6 @@ class ParseRouteTree {
RouteDecoder matchRoute(String name, {PageSettings? arguments}) {
final uri = Uri.parse(name);
// /home/profile/123 => home,profile,123 => /,/home,/home/profile,/home/profile/123
final split = uri.path.split('/').where((element) => element.isNotEmpty);
var curPath = '/';
final cumulativePaths = <String>[
... ... @@ -106,7 +105,7 @@ class ParseRouteTree {
.where((element) => element.value != null)
///Prevent page be disposed
.map((e) => MapEntry(e.key, e.value!.copy(key: ValueKey(e.key))))
.map((e) => MapEntry(e.key, e.value!.copyWith(key: ValueKey(e.key))))
.toList();
final params = Map<String, String>.from(uri.queryParameters);
... ... @@ -120,7 +119,7 @@ class ParseRouteTree {
//copy parameters to all pages.
final mappedTreeBranch = treeBranch
.map(
(e) => e.value.copy(
(e) => e.value.copyWith(
parameters: {
if (e.value.parameters != null) ...e.value.parameters!,
...params,
... ... @@ -185,8 +184,8 @@ class ParseRouteTree {
for (var page in route.children) {
// Add Parent middlewares to children
final parentMiddlewares = [
if (page.middlewares != null) ...page.middlewares!,
if (route.middlewares != null) ...route.middlewares!
if (page.middlewares.isNotEmpty) ...page.middlewares,
if (route.middlewares.isNotEmpty) ...route.middlewares
];
result.add(
_addChild(
... ... @@ -203,7 +202,7 @@ class ParseRouteTree {
parentPath,
[
...parentMiddlewares,
if (child.middlewares != null) ...child.middlewares!,
if (child.middlewares.isNotEmpty) ...child.middlewares,
],
));
}
... ... @@ -214,7 +213,7 @@ class ParseRouteTree {
/// Change the Path for a [GetPage]
GetPage _addChild(
GetPage origin, String parentPath, List<GetMiddleware> middlewares) {
return origin.copy(
return origin.copyWith(
middlewares: middlewares,
name: (parentPath + origin.name).replaceAll(r'//', '/'),
// key:
... ...
... ... @@ -131,7 +131,7 @@ class MiddlewareRunner {
List<GetMiddleware> _getMiddlewares() {
final _m = _middlewares ?? <GetMiddleware>[];
return _m
return List.of(_m)
..sort(
(a, b) => (a.priority ?? 0).compareTo(b.priority ?? 0),
);
... ... @@ -248,7 +248,7 @@ class PageRedirect {
addPageParameter(route!);
// No middlewares found return match.
if (match.route!.middlewares == null || match.route!.middlewares!.isEmpty) {
if (match.route!.middlewares.isEmpty) {
return false;
}
final newSettings = runner.runRedirect(settings!.name);
... ...
... ... @@ -4,7 +4,7 @@ version: 5.0.0-beta.52
homepage: https://github.com/jonataslaw/getx
environment:
sdk: '>=2.16.0 <4.0.0'
sdk: '>=2.17.0 <4.0.0'
dependencies:
flutter:
... ...
... ... @@ -7,7 +7,7 @@ import '../../navigation/utils/wrapper.dart';
void main() {
testWidgets("Get.defaultDialog smoke test", (tester) async {
await tester.pumpWidget(Wrapper(child: Container()));
await tester.pump();
await tester.pumpAndSettle();
final BuildContext context = tester.element(find.byType(Container));
... ...