Jonny Borges
Committed by GitHub

Merge pull request #2160 from jonataslaw/outlet-refactor

outlet-refactor
... ... @@ -5,24 +5,22 @@ import '../routes/app_pages.dart';
class EnsureAuthMiddleware extends GetMiddleware {
@override
Future<RouteDecoder?> redirect(RouteDecoder route) async {
Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
// you can do whatever you want here
// but it's preferable to make this method fast
// await Future.delayed(Duration(milliseconds: 500));
if (!AuthService.to.isLoggedInValue) {
final path = route.pageSettings?.name as String;
final newRoute = Routes.LOGIN_THEN(path);
final newRoute = Routes.LOGIN_THEN(route.pageSettings!.name);
return RouteDecoder.fromRoute(newRoute);
}
return super.redirect(route);
return await super.redirectDelegate(route);
}
}
class EnsureNotAuthedMiddleware extends GetMiddleware {
@override
Future<RouteDecoder?> redirect(RouteDecoder route) async {
Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
if (AuthService.to.isLoggedInValue) {
//NEVER navigate to auth screen, when user is already authed
return null;
... ... @@ -30,6 +28,6 @@ class EnsureNotAuthedMiddleware extends GetMiddleware {
//OR redirect user to another screen
//return RouteDecoder.fromRoute(Routes.PROFILE);
}
return super.redirect(route);
return await super.redirectDelegate(route);
}
}
... ...
... ... @@ -8,7 +8,9 @@ class HomeView extends GetView<HomeController> {
@override
Widget build(BuildContext context) {
return GetRouterOutlet.builder(
builder: (context, delegate, currentRoute) {
routerDelegate: Get.nestedKey(Routes.HOME),
builder: (context) {
final delegate = context.navigation;
//This router outlet handles the appbar and the bottom navigation bar
final currentLocation = context.location;
var currentIndex = 0;
... ... @@ -22,6 +24,7 @@ class HomeView extends GetView<HomeController> {
body: GetRouterOutlet(
initialRoute: Routes.DASHBOARD,
anchorRoute: Routes.HOME,
//delegate: Get.nestedKey(Routes.HOME),
// key: Get.nestedKey(Routes.HOME),
),
bottomNavigationBar: BottomNavigationBar(
... ...
... ... @@ -8,8 +8,9 @@ import 'drawer.dart';
class RootView extends GetView<RootController> {
@override
Widget build(BuildContext context) {
return GetRouterOutlet.builder(
builder: (context, delegate, current) {
return RouterOutlet.builder(
delegate: Get.nestedKey(null),
builder: (context) {
final title = context.location;
return Scaffold(
drawer: DrawerWidget(),
... ... @@ -17,12 +18,15 @@ class RootView extends GetView<RootController> {
title: Text(title),
centerTitle: true,
),
//body: HomeView(),
body: GetRouterOutlet(
initialRoute: Routes.HOME,
delegate: Get.nestedKey(null),
anchorRoute: '/',
// filterPages: (afterAnchor) {
// return afterAnchor.take(1);
// },
filterPages: (afterAnchor) {
return afterAnchor.take(1);
},
),
);
},
... ...
... ... @@ -2,13 +2,12 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'app/modules/splash/controllers/splash_service.dart';
import 'app/modules/splash/views/splash_view.dart';
import 'app/routes/app_pages.dart';
import 'services/auth_service.dart';
void main() {
runApp(
GetMaterialApp.router(
GetMaterialApp(
title: "Application",
initialBinding: BindingsBuilder(
() {
... ... @@ -17,18 +16,19 @@ void main() {
},
),
getPages: AppPages.routes,
builder: (context, child) {
return FutureBuilder<void>(
key: ValueKey('initFuture'),
future: Get.find<SplashService>().init(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return child ?? SizedBox.shrink();
}
return SplashView();
},
);
},
initialRoute: AppPages.INITIAL,
// builder: (context, child) {
// return FutureBuilder<void>(
// key: ValueKey('initFuture'),
// future: Get.find<SplashService>().init(),
// builder: (context, snapshot) {
// if (snapshot.connectionState == ConnectionState.done) {
// return child ?? SizedBox.shrink();
// }
// return SplashView();
// },
// );
// },
// routeInformationParser: GetInformationParser(
// // initialRoute: Routes.HOME,
// ),
... ...
... ... @@ -576,7 +576,7 @@ extension GetNavigationExt on GetInterface {
Future<T?>? toNamed<T>(
String page, {
dynamic arguments,
int? id,
dynamic id,
bool preventDuplicates = true,
Map<String, String>? parameters,
}) {
... ... @@ -1078,7 +1078,7 @@ extension GetNavigationExt on GetInterface {
GetDelegate? nestedKey(String? key) {
if (key == null) {
throw 'You need to define a ID';
return routerDelegate as GetDelegate;
}
keys.putIfAbsent(
key,
... ... @@ -1091,7 +1091,7 @@ extension GetNavigationExt on GetInterface {
return keys[key];
}
GetDelegate searchDelegate(int? k) {
GetDelegate searchDelegate(dynamic k) {
GetDelegate _key;
if (k == null) {
_key = Get.rootController.rootDelegate;
... ...
... ... @@ -107,7 +107,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
}
var iterator = config;
for (var item in middlewares) {
var redirectRes = await item.redirect(iterator);
var redirectRes = await item.redirectDelegate(iterator);
if (redirectRes == null) return null;
iterator = redirectRes;
}
... ... @@ -312,7 +312,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
if (clearPages) _activePages.clear();
final pageSettings = _buildPageSettings(notFoundRoute.name);
final routeDecoder = await _getRouteDecoder(pageSettings);
final routeDecoder = _getRouteDecoder(pageSettings);
_push(routeDecoder!);
}
... ... @@ -327,12 +327,12 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
Future<T?> toNamed<T>(
String page, {
dynamic arguments,
int? id,
dynamic id,
bool preventDuplicates = true,
Map<String, String>? parameters,
}) async {
final args = _buildPageSettings(page, arguments);
final route = await _getRouteDecoder<T>(args);
final route = _getRouteDecoder<T>(args);
if (route != null) {
return _push<T>(route);
} else {
... ... @@ -380,7 +380,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
Get.addPage(getPage);
final args = _buildPageSettings(routeName, arguments);
final route = await _getRouteDecoder<T>(args);
final route = _getRouteDecoder<T>(args);
final result = await _push<T>(
route!,
rebuildStack: rebuildStack,
... ... @@ -478,7 +478,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
Map<String, String>? parameters,
}) async {
final args = _buildPageSettings(page, arguments);
final route = await _getRouteDecoder<T>(args);
final route = _getRouteDecoder<T>(args);
if (route == null) return null;
while (_activePages.length > 1) {
... ... @@ -497,7 +497,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
Map<String, String>? parameters,
}) async {
final args = _buildPageSettings(page, arguments);
final route = await _getRouteDecoder<T>(args);
final route = _getRouteDecoder<T>(args);
if (route == null) return null;
final newPredicate = predicate ?? (route) => false;
... ... @@ -517,7 +517,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
Map<String, String>? parameters,
}) async {
final args = _buildPageSettings(page, arguments);
final route = await _getRouteDecoder<T>(args);
final route = _getRouteDecoder<T>(args);
if (route == null) return null;
_popWithResult();
return _push<T>(route);
... ... @@ -531,7 +531,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
]) async {
final arguments = _buildPageSettings(page, data);
final route = await _getRouteDecoder<T>(arguments);
final route = _getRouteDecoder<T>(arguments);
if (route == null) return null;
... ... @@ -586,7 +586,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
Future<R?> backAndtoNamed<T, R>(String page,
{T? result, Object? arguments}) async {
final args = _buildPageSettings(page, arguments);
final route = await _getRouteDecoder<R>(args);
final route = _getRouteDecoder<R>(args);
if (route == null) return null;
_popWithResult<T>(result);
return _push<R>(route);
... ... @@ -625,7 +625,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
final index = _activePages.length > 1 ? _activePages.length - 1 : 0;
Get.addPage(page);
final activePage = await _getRouteDecoder(arguments);
final activePage = _getRouteDecoder(arguments);
// final activePage = _configureRouterDecoder<T>(route!, arguments);
... ... @@ -670,7 +670,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
}
@protected
Future<RouteDecoder?> _getRouteDecoder<T>(PageSettings arguments) async {
RouteDecoder? _getRouteDecoder<T>(PageSettings arguments) {
var page = arguments.uri.path;
final parameters = arguments.params;
if (parameters.isNotEmpty) {
... ... @@ -682,10 +682,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
final route = decoder.route;
if (route == null) return null;
final configure = _configureRouterDecoder(decoder, arguments);
final router = await runMiddleware(configure);
return router;
return _configureRouterDecoder(decoder, arguments);
}
@protected
... ... @@ -709,10 +706,14 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
return decoder;
}
Future<T?> _push<T>(RouteDecoder res,
Future<T?> _push<T>(RouteDecoder decoder,
{bool rebuildStack = true,
PreventDuplicateHandlingMode preventDuplicateHandlingMode =
PreventDuplicateHandlingMode.ReorderRoutes}) async {
var mid = await runMiddleware(decoder);
final res = mid ?? decoder;
// if (res == null) res = decoder;
final onStackPage = _activePages
.firstWhereOrNull((element) => element.route?.key == res.route?.key);
... ... @@ -744,7 +745,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
refresh();
}
return res.route?.completer?.future as Future<T?>?;
return decoder.route?.completer?.future as Future<T?>?;
}
@override
... ...
import 'package:flutter/foundation.dart';
import '../../../route_manager.dart';
@immutable
class RouteDecoder {
const RouteDecoder(
this.currentTreeBranch,
... ... @@ -59,6 +62,18 @@ class RouteDecoder {
currentTreeBranch[index] = _route.copy(arguments: arguments);
}
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is RouteDecoder &&
listEquals(other.currentTreeBranch, currentTreeBranch) &&
other.pageSettings == pageSettings;
}
@override
int get hashCode => currentTreeBranch.hashCode ^ pageSettings.hashCode;
}
class ParseRouteTree {
... ...
... ... @@ -20,6 +20,21 @@ abstract class _RouteMiddleware {
/// {@end-tool}
int? priority;
/// This function will be called when the page of
/// the called route is being searched for.
/// It take RouteSettings as a result an redirect to the new settings or
/// give it null and there will be no redirecting.
/// {@tool snippet}
/// ```dart
/// GetPage redirect(String route) {
/// final authService = Get.find<AuthService>();
/// return authService.authed.value ? null : RouteSettings(name: '/login');
/// }
/// ```
/// {@end-tool}
RouteSettings? redirect(String route);
/// Similar to [redirect],
/// This function will be called when the router delegate changes the
/// current route.
///
... ... @@ -30,13 +45,13 @@ abstract class _RouteMiddleware {
/// and no new routes are pushed.
/// {@tool snippet}
/// ```dart
/// RouteDecoder? redirect(RouteDecoder route) {
/// GetNavConfig? redirect(GetNavConfig route) {
/// final authService = Get.find<AuthService>();
/// return authService.authed.value ? null : RouteDecoder.fromRoute('/login');
/// return authService.authed.value ? null : RouteSettings(name: '/login');
/// }
/// ```
/// {@end-tool}
Future<RouteDecoder?> redirect(RouteDecoder route);
Future<RouteDecoder?> redirectDelegate(RouteDecoder route);
/// This function will be called when this Page is called
/// you can use it to change something about the page or give it new page
... ... @@ -86,8 +101,8 @@ class GetMiddleware implements _RouteMiddleware {
GetMiddleware({this.priority});
// @override
// RouteSettings? redirect(String? route) => null;
@override
RouteSettings? redirect(String? route) => null;
@override
GetPage? onPageCalled(GetPage? page) => page;
... ... @@ -105,7 +120,7 @@ class GetMiddleware implements _RouteMiddleware {
void onPageDispose() {}
@override
Future<RouteDecoder?> redirect(RouteDecoder route) =>
Future<RouteDecoder?> redirectDelegate(RouteDecoder route) =>
SynchronousFuture(route);
}
... ... @@ -129,17 +144,17 @@ class MiddlewareRunner {
return page;
}
// RouteSettings? runRedirect(String? route) {
// RouteSettings? to;
// for (final element in _getMiddlewares()) {
// to = element.redirect(route);
// if (to != null) {
// break;
// }
// }
// Get.log('Redirect to $to');
// return to;
// }
RouteSettings? runRedirect(String? route) {
RouteSettings? to;
for (final element in _getMiddlewares()) {
to = element.redirect(route);
if (to != null) {
break;
}
}
Get.log('Redirect to $to');
return to;
}
List<R>? runOnBindingsStart<R>(List<R>? bindings) {
_getMiddlewares().forEach((element) {
... ... @@ -259,11 +274,11 @@ class PageRedirect {
if (match.route!.middlewares == null || match.route!.middlewares!.isEmpty) {
return false;
}
// final newSettings = runner.runRedirect(settings!.name);
// if (newSettings == null) {
// return false;
// }
// settings = newSettings;
final newSettings = runner.runRedirect(settings!.name);
if (newSettings == null) {
return false;
}
settings = newSettings;
return true;
}
... ...
... ... @@ -5,11 +5,7 @@ import '../../../get.dart';
class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
extends StatefulWidget {
final TDelegate routerDelegate;
final Widget Function(
BuildContext context,
TDelegate delegate,
T? currentRoute,
) builder;
final Widget Function(BuildContext context) builder;
//keys
RouterOutlet.builder({
... ... @@ -28,7 +24,9 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
)
pageBuilder,
}) : this.builder(
builder: (context, rDelegate, currentConfig) {
builder: (context) {
final currentConfig = context.delegate.currentConfiguration as T?;
final rDelegate = context.delegate as TDelegate;
var picked =
currentConfig == null ? null : pickPages(currentConfig);
if (picked?.length == 0) {
... ... @@ -45,38 +43,83 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
extends State<RouterOutlet<TDelegate, T>> {
TDelegate get delegate => widget.routerDelegate;
RouterDelegate? delegate;
late ChildBackButtonDispatcher _backButtonDispatcher;
void _listener() {
setState(() {});
}
VoidCallback? disposer;
@override
void initState() {
super.initState();
_getCurrentRoute();
delegate.addListener(onRouterDelegateChanged);
void didChangeDependencies() {
super.didChangeDependencies();
disposer?.call();
final router = Router.of(context);
delegate ??= router.routerDelegate;
delegate?.addListener(_listener);
disposer = () => delegate?.removeListener(_listener);
_backButtonDispatcher =
router.backButtonDispatcher!.createChildBackButtonDispatcher();
}
@override
void dispose() {
delegate.removeListener(onRouterDelegateChanged);
super.dispose();
}
T? currentRoute;
void _getCurrentRoute() {
currentRoute = delegate.currentConfiguration;
}
void onRouterDelegateChanged() {
setState(_getCurrentRoute);
Get.routerDelegate?.removeListener(_listener);
//_backButtonDispatcher.forget(_backButtonDispatcher)
}
@override
Widget build(BuildContext context) {
return widget.builder(context, delegate, currentRoute);
_backButtonDispatcher.takePriority();
return widget.builder(context);
}
}
class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
// class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
// extends State<RouterOutlet<TDelegate, T>> {
// TDelegate get delegate => context.delegate as TDelegate;
// @override
// void initState() {
// super.initState();
// }
// VoidCallback? disposer;
// @override
// void didChangeDependencies() {
// disposer?.call();
// delegate.addListener(onRouterDelegateChanged);
// disposer = () => delegate.removeListener(onRouterDelegateChanged);
// _getCurrentRoute();
// super.didChangeDependencies();
// }
// @override
// void dispose() {
// disposer?.call();
// super.dispose();
// }
// T? currentRoute;
// void _getCurrentRoute() {
// currentRoute = delegate.currentConfiguration;
// }
// void onRouterDelegateChanged() {
// setState(_getCurrentRoute);
// }
// @override
// Widget build(BuildContext context) {
// return widget.builder(context);
// }
// }
class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
GetRouterOutlet({
String? anchorRoute,
required String initialRoute,
... ... @@ -101,7 +144,7 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
}
return ret;
},
emptyPage: (delegate) =>
emptyPage: (delegate) =>
Get.routeTree.matchRoute(initialRoute).route ??
delegate.notFoundRoute,
key: Get.nestedKey(anchorRoute)?.navigatorKey,
... ... @@ -145,8 +188,6 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
GetRouterOutlet.builder({
required Widget Function(
BuildContext context,
GetDelegate delegate,
RouteDecoder? currentRoute,
)
builder,
GetDelegate? routerDelegate,
... ...
... ... @@ -11,7 +11,7 @@ class RedirectMiddleware extends GetMiddleware {
// }
@override
Future<RouteDecoder?> redirect(RouteDecoder route) async {
Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
return RouteDecoder.fromRoute('/second');
}
}
... ... @@ -23,8 +23,8 @@ class RedirectMiddlewareNull extends GetMiddleware {
// }
@override
Future<RouteDecoder?> redirect(RouteDecoder route) async {
return route;
Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
return null;
}
}
... ... @@ -66,7 +66,7 @@ void main() {
),
);
await tester.pump();
// await tester.pump();
Get.toNamed('/first');
... ...