WIP
successfully decoupled the logical routes from the visual routes
Showing
14 changed files
with
252 additions
and
73 deletions
| 1 | +import 'package:example_nav2/app/modules/home/controllers/home_controller.dart'; | ||
| 2 | +import 'package:flutter/material.dart'; | ||
| 3 | + | ||
| 4 | +import 'package:get/get.dart'; | ||
| 5 | + | ||
| 6 | +class DashboardView extends GetView<HomeController> { | ||
| 7 | + @override | ||
| 8 | + Widget build(BuildContext context) { | ||
| 9 | + return Scaffold( | ||
| 10 | + body: Center( | ||
| 11 | + child: Text( | ||
| 12 | + 'DashboardView is working', | ||
| 13 | + style: TextStyle(fontSize: 20), | ||
| 14 | + ), | ||
| 15 | + ), | ||
| 16 | + ); | ||
| 17 | + } | ||
| 18 | +} | 
| 1 | +import 'package:example_nav2/app/modules/home/views/dashboard_view.dart'; | ||
| 2 | +import 'package:example_nav2/app/routes/app_pages.dart'; | ||
| 1 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; | 
| 2 | 4 | ||
| 3 | import 'package:get/get.dart'; | 5 | import 'package:get/get.dart'; | 
| 6 | +import 'package:get/get_navigation/src/nav2/get_router_delegate.dart'; | ||
| 7 | +import 'package:get/get_navigation/src/nav2/router_outlet.dart'; | ||
| 4 | 8 | ||
| 5 | import '../controllers/home_controller.dart'; | 9 | import '../controllers/home_controller.dart'; | 
| 6 | 10 | ||
| 7 | class HomeView extends GetView<HomeController> { | 11 | class HomeView extends GetView<HomeController> { | 
| 8 | @override | 12 | @override | 
| 9 | Widget build(BuildContext context) { | 13 | Widget build(BuildContext context) { | 
| 10 | - return Scaffold( | ||
| 11 | - appBar: AppBar( | ||
| 12 | - title: Text('HomeView'), | ||
| 13 | - centerTitle: true, | ||
| 14 | - ), | ||
| 15 | - body: Center( | ||
| 16 | - child: Text( | ||
| 17 | - 'HomeView is working', | ||
| 18 | - style: TextStyle(fontSize: 20), | ||
| 19 | - ), | ||
| 20 | - ), | 14 | + return GetRouterOutlet.builder( | 
| 15 | + builder: (context, delegate, currentRoute) { | ||
| 16 | + final title = currentRoute?.title; | ||
| 17 | + final currentName = currentRoute?.name; | ||
| 18 | + var currentIndex = 0; | ||
| 19 | + if (currentName?.startsWith(Routes.PRODUCTS) == true) currentIndex = 2; | ||
| 20 | + if (currentName?.startsWith(Routes.PROFILE) == true) currentIndex = 1; | ||
| 21 | + return Scaffold( | ||
| 22 | + appBar: title == null | ||
| 23 | + ? null | ||
| 24 | + : AppBar( | ||
| 25 | + title: Text(title), | ||
| 26 | + centerTitle: true, | ||
| 27 | + ), | ||
| 28 | + body: GetRouterOutlet( | ||
| 29 | + emptyStackPage: (delegate) => DashboardView(), | ||
| 30 | + pickPages: (currentNavStack) { | ||
| 31 | + // will take any route after home | ||
| 32 | + final res = currentNavStack.pickAfterRoute(Routes.HOME); | ||
| 33 | + print('''RouterOutlet rebuild: | ||
| 34 | + currentStack: $currentNavStack | ||
| 35 | + pickedStack: $res'''); | ||
| 36 | + return res; | ||
| 37 | + }, | ||
| 38 | + ), | ||
| 39 | + bottomNavigationBar: BottomNavigationBar( | ||
| 40 | + currentIndex: currentIndex, | ||
| 41 | + onTap: (value) { | ||
| 42 | + final getDelegate = Get.getDelegate(); | ||
| 43 | + if (getDelegate == null) return; | ||
| 44 | + switch (value) { | ||
| 45 | + case 0: | ||
| 46 | + getDelegate.offUntil(Routes.HOME); | ||
| 47 | + break; | ||
| 48 | + case 1: | ||
| 49 | + getDelegate.toNamed(Routes.PROFILE); | ||
| 50 | + break; | ||
| 51 | + case 2: | ||
| 52 | + getDelegate.toNamed(Routes.PRODUCTS); | ||
| 53 | + break; | ||
| 54 | + default: | ||
| 55 | + } | ||
| 56 | + }, | ||
| 57 | + items: [ | ||
| 58 | + // Routes.Home + [Empty] | ||
| 59 | + BottomNavigationBarItem( | ||
| 60 | + icon: Icon(Icons.home), | ||
| 61 | + label: 'Home', | ||
| 62 | + ), | ||
| 63 | + // Routes.Home + Routes.Profile | ||
| 64 | + BottomNavigationBarItem( | ||
| 65 | + icon: Icon(Icons.account_box_rounded), | ||
| 66 | + label: 'Profile', | ||
| 67 | + ), | ||
| 68 | + // Routes.Home + Routes.Products | ||
| 69 | + BottomNavigationBarItem( | ||
| 70 | + icon: Icon(Icons.account_box_rounded), | ||
| 71 | + label: 'Products', | ||
| 72 | + ), | ||
| 73 | + ], | ||
| 74 | + ), | ||
| 75 | + ); | ||
| 76 | + }, | ||
| 21 | ); | 77 | ); | 
| 22 | } | 78 | } | 
| 23 | } | 79 | } | 
| @@ -5,8 +5,10 @@ import '../controllers/product_details_controller.dart'; | @@ -5,8 +5,10 @@ import '../controllers/product_details_controller.dart'; | ||
| 5 | class ProductDetailsBinding extends Bindings { | 5 | class ProductDetailsBinding extends Bindings { | 
| 6 | @override | 6 | @override | 
| 7 | void dependencies() { | 7 | void dependencies() { | 
| 8 | - Get.lazyPut<ProductDetailsController>( | ||
| 9 | - () => ProductDetailsController(), | 8 | + Get.create<ProductDetailsController>( | 
| 9 | + () => ProductDetailsController( | ||
| 10 | + Get.parameters['productId'] ?? '', | ||
| 11 | + ), | ||
| 10 | ); | 12 | ); | 
| 11 | } | 13 | } | 
| 12 | } | 14 | } | 
| @@ -4,18 +4,20 @@ import 'package:get/get.dart'; | @@ -4,18 +4,20 @@ import 'package:get/get.dart'; | ||
| 4 | 4 | ||
| 5 | import '../controllers/product_details_controller.dart'; | 5 | import '../controllers/product_details_controller.dart'; | 
| 6 | 6 | ||
| 7 | -class ProductDetailsView extends GetView<ProductDetailsController> { | 7 | +class ProductDetailsView extends GetWidget<ProductDetailsController> { | 
| 8 | @override | 8 | @override | 
| 9 | Widget build(BuildContext context) { | 9 | Widget build(BuildContext context) { | 
| 10 | return Scaffold( | 10 | return Scaffold( | 
| 11 | - appBar: AppBar( | ||
| 12 | - title: Text('ProductDetailsView'), | ||
| 13 | - centerTitle: true, | ||
| 14 | - ), | ||
| 15 | body: Center( | 11 | body: Center( | 
| 16 | - child: Text( | ||
| 17 | - 'ProductDetailsView is working', | ||
| 18 | - style: TextStyle(fontSize: 20), | 12 | + child: Column( | 
| 13 | + mainAxisSize: MainAxisSize.min, | ||
| 14 | + children: [ | ||
| 15 | + Text( | ||
| 16 | + 'ProductDetailsView is working', | ||
| 17 | + style: TextStyle(fontSize: 20), | ||
| 18 | + ), | ||
| 19 | + Text('ProductId: ${controller.productId}') | ||
| 20 | + ], | ||
| 19 | ), | 21 | ), | 
| 20 | ), | 22 | ), | 
| 21 | ); | 23 | ); | 
| 1 | +import 'package:example_nav2/app/models/demo_product.dart'; | ||
| 1 | import 'package:get/get.dart'; | 2 | import 'package:get/get.dart'; | 
| 2 | 3 | ||
| 3 | class ProductsController extends GetxController { | 4 | class ProductsController extends GetxController { | 
| 4 | - //TODO: Implement ProductsController | 5 | + final products = <DemoProduct>[].obs; | 
| 5 | 6 | ||
| 6 | - final count = 0.obs; | ||
| 7 | - @override | ||
| 8 | - void onInit() { | ||
| 9 | - super.onInit(); | 7 | + void loadDemoProductsFromSomeWhere() { | 
| 8 | + products.add( | ||
| 9 | + DemoProduct( | ||
| 10 | + name: 'Product added on: ${DateTime.now().toString()}', | ||
| 11 | + id: DateTime.now().millisecondsSinceEpoch.toString(), | ||
| 12 | + ), | ||
| 13 | + ); | ||
| 10 | } | 14 | } | 
| 11 | 15 | ||
| 12 | @override | 16 | @override | 
| 13 | void onReady() { | 17 | void onReady() { | 
| 14 | super.onReady(); | 18 | super.onReady(); | 
| 19 | + loadDemoProductsFromSomeWhere(); | ||
| 15 | } | 20 | } | 
| 16 | - | ||
| 17 | - @override | ||
| 18 | - void onClose() {} | ||
| 19 | - void increment() => count.value++; | ||
| 20 | } | 21 | } | 
| 1 | +import 'package:example_nav2/app/routes/app_pages.dart'; | ||
| 1 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; | 
| 2 | 3 | ||
| 3 | import 'package:get/get.dart'; | 4 | import 'package:get/get.dart'; | 
| @@ -8,14 +9,29 @@ class ProductsView extends GetView<ProductsController> { | @@ -8,14 +9,29 @@ class ProductsView extends GetView<ProductsController> { | ||
| 8 | @override | 9 | @override | 
| 9 | Widget build(BuildContext context) { | 10 | Widget build(BuildContext context) { | 
| 10 | return Scaffold( | 11 | return Scaffold( | 
| 11 | - appBar: AppBar( | ||
| 12 | - title: Text('ProductsView'), | ||
| 13 | - centerTitle: true, | 12 | + floatingActionButton: FloatingActionButton.extended( | 
| 13 | + onPressed: controller.loadDemoProductsFromSomeWhere, | ||
| 14 | + label: Text('Add'), | ||
| 14 | ), | 15 | ), | 
| 15 | - body: Center( | ||
| 16 | - child: Text( | ||
| 17 | - 'ProductsView is working', | ||
| 18 | - style: TextStyle(fontSize: 20), | 16 | + body: Obx( | 
| 17 | + () => RefreshIndicator( | ||
| 18 | + onRefresh: () async { | ||
| 19 | + controller.products.clear(); | ||
| 20 | + controller.loadDemoProductsFromSomeWhere(); | ||
| 21 | + }, | ||
| 22 | + child: ListView.builder( | ||
| 23 | + itemCount: controller.products.length, | ||
| 24 | + itemBuilder: (context, index) { | ||
| 25 | + final item = controller.products[index]; | ||
| 26 | + return ListTile( | ||
| 27 | + onTap: () { | ||
| 28 | + Get.getDelegate()?.toNamed(Routes.PRODUCT_DETAILS(item.id)); | ||
| 29 | + }, | ||
| 30 | + title: Text(item.name), | ||
| 31 | + subtitle: Text(item.id), | ||
| 32 | + ); | ||
| 33 | + }, | ||
| 34 | + ), | ||
| 19 | ), | 35 | ), | 
| 20 | ), | 36 | ), | 
| 21 | ); | 37 | ); | 
| @@ -8,10 +8,6 @@ class ProfileView extends GetView<ProfileController> { | @@ -8,10 +8,6 @@ class ProfileView extends GetView<ProfileController> { | ||
| 8 | @override | 8 | @override | 
| 9 | Widget build(BuildContext context) { | 9 | Widget build(BuildContext context) { | 
| 10 | return Scaffold( | 10 | return Scaffold( | 
| 11 | - appBar: AppBar( | ||
| 12 | - title: Text('ProfileView'), | ||
| 13 | - centerTitle: true, | ||
| 14 | - ), | ||
| 15 | body: Center( | 11 | body: Center( | 
| 16 | child: Text( | 12 | child: Text( | 
| 17 | 'ProfileView is working', | 13 | 'ProfileView is working', | 
| 1 | import 'package:get/get.dart'; | 1 | import 'package:get/get.dart'; | 
| 2 | - | 2 | +import 'package:get/get_navigation/src/nav2/router_outlet.dart'; | 
| 3 | import '../modules/home/bindings/home_binding.dart'; | 3 | import '../modules/home/bindings/home_binding.dart'; | 
| 4 | import '../modules/home/views/home_view.dart'; | 4 | import '../modules/home/views/home_view.dart'; | 
| 5 | import '../modules/product_details/bindings/product_details_binding.dart'; | 5 | import '../modules/product_details/bindings/product_details_binding.dart'; | 
| @@ -22,24 +22,34 @@ class AppPages { | @@ -22,24 +22,34 @@ class AppPages { | ||
| 22 | GetPage( | 22 | GetPage( | 
| 23 | name: _Paths.HOME, | 23 | name: _Paths.HOME, | 
| 24 | page: () => HomeView(), | 24 | page: () => HomeView(), | 
| 25 | - binding: HomeBinding(), | 25 | + //TODO: don't group bindings in one place, and instead make each page use its own binding | 
| 26 | + bindings: [ | ||
| 27 | + HomeBinding(), | ||
| 28 | + //These must use [Get.lazyPut] or [Get.create] because their view is created long after they are declared | ||
| 29 | + ProfileBinding(), | ||
| 30 | + ProductsBinding(), | ||
| 31 | + ProductDetailsBinding(), | ||
| 32 | + ], | ||
| 33 | + title: null, | ||
| 34 | + middlewares: [ | ||
| 35 | + RouterOutletContainerMiddleWare(_Paths.HOME), | ||
| 36 | + ], | ||
| 26 | children: [ | 37 | children: [ | 
| 27 | GetPage( | 38 | GetPage( | 
| 28 | name: _Paths.PROFILE, | 39 | name: _Paths.PROFILE, | 
| 29 | page: () => ProfileView(), | 40 | page: () => ProfileView(), | 
| 30 | - binding: ProfileBinding(), | 41 | + title: 'Profile', | 
| 31 | ), | 42 | ), | 
| 32 | - ], | ||
| 33 | - ), | ||
| 34 | - GetPage( | ||
| 35 | - name: _Paths.PRODUCTS, | ||
| 36 | - page: () => ProductsView(), | ||
| 37 | - binding: ProductsBinding(), | ||
| 38 | - children: [ | ||
| 39 | GetPage( | 43 | GetPage( | 
| 40 | - name: _Paths.PRODUCT_DETAILS, | ||
| 41 | - page: () => ProductDetailsView(), | ||
| 42 | - binding: ProductDetailsBinding(), | 44 | + name: _Paths.PRODUCTS, | 
| 45 | + page: () => ProductsView(), | ||
| 46 | + title: 'Products', | ||
| 47 | + children: [ | ||
| 48 | + GetPage( | ||
| 49 | + name: _Paths.PRODUCT_DETAILS, | ||
| 50 | + page: () => ProductDetailsView(), | ||
| 51 | + ), | ||
| 52 | + ], | ||
| 43 | ), | 53 | ), | 
| 44 | ], | 54 | ], | 
| 45 | ), | 55 | ), | 
| @@ -5,12 +5,12 @@ abstract class Routes { | @@ -5,12 +5,12 @@ abstract class Routes { | ||
| 5 | Routes._(); | 5 | Routes._(); | 
| 6 | 6 | ||
| 7 | static const HOME = _Paths.HOME; | 7 | static const HOME = _Paths.HOME; | 
| 8 | - static const PROFILE = _Paths.PROFILE; | 8 | + static const PROFILE = _Paths.HOME + _Paths.PROFILE; | 
| 9 | 9 | ||
| 10 | static const SETTINGS = _Paths.SETTINGS; | 10 | static const SETTINGS = _Paths.SETTINGS; | 
| 11 | 11 | ||
| 12 | - static const PRODUCTS = _Paths.PRODUCTS; | ||
| 13 | - static PRODUCT_DETAILS(String productId) => '${_Paths.PRODUCTS}/$productId'; | 12 | + static const PRODUCTS = _Paths.HOME + _Paths.PRODUCTS; | 
| 13 | + static String PRODUCT_DETAILS(String productId) => '$PRODUCTS/$productId'; | ||
| 14 | } | 14 | } | 
| 15 | 15 | ||
| 16 | abstract class _Paths { | 16 | abstract class _Paths { | 
| 1 | import 'package:flutter/widgets.dart'; | 1 | import 'package:flutter/widgets.dart'; | 
| 2 | +import 'package:get/get_navigation/src/nav2/get_router_delegate.dart'; | ||
| 2 | 3 | ||
| 3 | import '../../get_core/src/get_interface.dart'; | 4 | import '../../get_core/src/get_interface.dart'; | 
| 4 | 5 | ||
| 6 | +import '../../route_manager.dart'; | ||
| 5 | import 'get_instance.dart'; | 7 | import 'get_instance.dart'; | 
| 6 | 8 | ||
| 7 | extension Inst on GetInterface { | 9 | extension Inst on GetInterface { | 
| @@ -127,4 +129,6 @@ extension Inst on GetInterface { | @@ -127,4 +129,6 @@ extension Inst on GetInterface { | ||
| 127 | /// Casts the stored router delegate to a desired type | 129 | /// Casts the stored router delegate to a desired type | 
| 128 | TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() => | 130 | TDelegate? delegate<TDelegate extends RouterDelegate<TPage>, TPage>() => | 
| 129 | routerDelegate as TDelegate?; | 131 | routerDelegate as TDelegate?; | 
| 132 | + | ||
| 133 | + GetDelegate? getDelegate() => delegate<GetDelegate, GetPage>(); | ||
| 130 | } | 134 | } | 
| 1 | import 'dart:async'; | 1 | import 'dart:async'; | 
| 2 | 2 | ||
| 3 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; | 
| 4 | +import 'package:get/get_navigation/src/nav2/router_outlet.dart'; | ||
| 4 | import '../../../get.dart'; | 5 | import '../../../get.dart'; | 
| 5 | import '../../../get_state_manager/src/simple/list_notifier.dart'; | 6 | import '../../../get_state_manager/src/simple/list_notifier.dart'; | 
| 6 | 7 | ||
| @@ -8,7 +9,7 @@ class GetDelegate extends RouterDelegate<GetPage> | @@ -8,7 +9,7 @@ class GetDelegate extends RouterDelegate<GetPage> | ||
| 8 | with ListenableMixin, ListNotifierMixin { | 9 | with ListenableMixin, ListNotifierMixin { | 
| 9 | final List<GetPage> routes = <GetPage>[]; | 10 | final List<GetPage> routes = <GetPage>[]; | 
| 10 | 11 | ||
| 11 | - final GetPage? notFoundRoute; | 12 | + GetPage? notFoundRoute; | 
| 12 | 13 | ||
| 13 | final List<NavigatorObserver>? dipNavObservers; | 14 | final List<NavigatorObserver>? dipNavObservers; | 
| 14 | final TransitionDelegate<dynamic>? transitionDelegate; | 15 | final TransitionDelegate<dynamic>? transitionDelegate; | 
| @@ -19,15 +20,27 @@ class GetDelegate extends RouterDelegate<GetPage> | @@ -19,15 +20,27 @@ class GetDelegate extends RouterDelegate<GetPage> | ||
| 19 | GetDelegate( | 20 | GetDelegate( | 
| 20 | {this.notFoundRoute, this.dipNavObservers, this.transitionDelegate}); | 21 | {this.notFoundRoute, this.dipNavObservers, this.transitionDelegate}); | 
| 21 | 22 | ||
| 23 | + List<GetPage> getVisiblePages() { | ||
| 24 | + return routes.where((r) { | ||
| 25 | + final mware = | ||
| 26 | + (r.middlewares ?? []).whereType<RouterOutletContainerMiddleWare>(); | ||
| 27 | + if (mware.length == 0) return true; | ||
| 28 | + return r.name == mware.first.stayAt; | ||
| 29 | + }).toList(); | ||
| 30 | + } | ||
| 31 | + | ||
| 22 | /// Called by the [Router] at startup with the structure that the | 32 | /// Called by the [Router] at startup with the structure that the | 
| 23 | /// [RouteInformationParser] obtained from parsing the initial route. | 33 | /// [RouteInformationParser] obtained from parsing the initial route. | 
| 24 | @override | 34 | @override | 
| 25 | Widget build(BuildContext context) { | 35 | Widget build(BuildContext context) { | 
| 36 | + final pages = getVisiblePages(); | ||
| 26 | return Navigator( | 37 | return Navigator( | 
| 27 | key: navigatorKey, | 38 | key: navigatorKey, | 
| 28 | onPopPage: _onPopPage, | 39 | onPopPage: _onPopPage, | 
| 29 | - pages: routes.toList(), | ||
| 30 | - observers: [GetObserver()], | 40 | + pages: pages, | 
| 41 | + observers: [ | ||
| 42 | + GetObserver(), | ||
| 43 | + ], | ||
| 31 | transitionDelegate: | 44 | transitionDelegate: | 
| 32 | transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(), | 45 | transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(), | 
| 33 | ); | 46 | ); | 
| @@ -73,13 +86,12 @@ class GetDelegate extends RouterDelegate<GetPage> | @@ -73,13 +86,12 @@ class GetDelegate extends RouterDelegate<GetPage> | ||
| 73 | } | 86 | } | 
| 74 | 87 | ||
| 75 | GetPage _notFound() { | 88 | GetPage _notFound() { | 
| 76 | - return notFoundRoute ?? | ||
| 77 | - GetPage( | ||
| 78 | - name: '/404', | ||
| 79 | - page: () => Scaffold( | ||
| 80 | - body: Text('not found'), | ||
| 81 | - ), | ||
| 82 | - ); | 89 | + return notFoundRoute ??= GetPage( | 
| 90 | + name: '/404', | ||
| 91 | + page: () => Scaffold( | ||
| 92 | + body: Text('not found'), | ||
| 93 | + ), | ||
| 94 | + ); | ||
| 83 | } | 95 | } | 
| 84 | 96 | ||
| 85 | Future<T?> pushRoute<T>( | 97 | Future<T?> pushRoute<T>( | 
| 1 | -import 'dart:js'; | ||
| 2 | - | ||
| 3 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; | 
| 2 | +import 'package:get/get_navigation/src/nav2/get_router_delegate.dart'; | ||
| 4 | import '../../../get.dart'; | 3 | import '../../../get.dart'; | 
| 5 | 4 | ||
| 6 | class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> | 5 | class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> | 
| @@ -23,13 +22,13 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> | @@ -23,13 +22,13 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object> | ||
| 23 | TDelegate? delegate, | 22 | TDelegate? delegate, | 
| 24 | required List<T> Function(TDelegate routerDelegate) currentNavStack, | 23 | required List<T> Function(TDelegate routerDelegate) currentNavStack, | 
| 25 | required List<T> Function(List<T> currentNavStack) pickPages, | 24 | required List<T> Function(List<T> currentNavStack) pickPages, | 
| 26 | - required Widget Function(T? page) pageBuilder, | 25 | + required Widget Function(TDelegate, T? page) pageBuilder, | 
| 27 | }) : this.builder( | 26 | }) : this.builder( | 
| 28 | builder: (context, rDelegate, currentConfig) { | 27 | builder: (context, rDelegate, currentConfig) { | 
| 29 | final currentStack = currentNavStack(rDelegate); | 28 | final currentStack = currentNavStack(rDelegate); | 
| 30 | final picked = pickPages(currentStack); | 29 | final picked = pickPages(currentStack); | 
| 31 | - if (picked.length == 0) return pageBuilder(null); | ||
| 32 | - return pageBuilder(picked.last); | 30 | + if (picked.length == 0) return pageBuilder(rDelegate, null); | 
| 31 | + return pageBuilder(rDelegate, picked.last); | ||
| 33 | }, | 32 | }, | 
| 34 | delegate: delegate, | 33 | delegate: delegate, | 
| 35 | ); | 34 | ); | 
| @@ -66,3 +65,53 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> | @@ -66,3 +65,53 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> | ||
| 66 | return widget.builder(context, delegate, currentRoute); | 65 | return widget.builder(context, delegate, currentRoute); | 
| 67 | } | 66 | } | 
| 68 | } | 67 | } | 
| 68 | + | ||
| 69 | +class GetRouterOutlet extends RouterOutlet<GetDelegate, GetPage> { | ||
| 70 | + GetRouterOutlet.builder({ | ||
| 71 | + required Widget Function( | ||
| 72 | + BuildContext context, | ||
| 73 | + GetDelegate delegate, | ||
| 74 | + GetPage? currentRoute, | ||
| 75 | + ) | ||
| 76 | + builder, | ||
| 77 | + GetDelegate? routerDelegate, | ||
| 78 | + }) : super.builder( | ||
| 79 | + builder: builder, | ||
| 80 | + delegate: routerDelegate, | ||
| 81 | + ); | ||
| 82 | + | ||
| 83 | + GetRouterOutlet({ | ||
| 84 | + Widget Function(GetDelegate delegate)? emptyStackPage, | ||
| 85 | + required List<GetPage> Function(List<GetPage> currentNavStack) pickPages, | ||
| 86 | + }) : super( | ||
| 87 | + pageBuilder: (rDelegate, page) => | ||
| 88 | + (page?.page() ?? | ||
| 89 | + emptyStackPage?.call(rDelegate) ?? | ||
| 90 | + rDelegate.notFoundRoute?.page()) ?? | ||
| 91 | + SizedBox.shrink(), | ||
| 92 | + currentNavStack: (routerDelegate) => routerDelegate.routes, | ||
| 93 | + pickPages: pickPages, | ||
| 94 | + delegate: Get.routerDelegate as GetDelegate, | ||
| 95 | + ); | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | +class RouterOutletContainerMiddleWare extends GetMiddleware { | ||
| 99 | + final String stayAt; | ||
| 100 | + | ||
| 101 | + RouterOutletContainerMiddleWare(this.stayAt); | ||
| 102 | + @override | ||
| 103 | + RouteSettings? redirect(String? route) { | ||
| 104 | + print('RouterOutletContainerMiddleWare: Redirect called ($route)'); | ||
| 105 | + return null; | ||
| 106 | + } | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +extension PagesListExt on List<GetPage> { | ||
| 110 | + List<GetPage> pickAtRoute(String route) { | ||
| 111 | + return skipWhile((value) => value.name != route).toList(); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + List<GetPage> pickAfterRoute(String route) { | ||
| 115 | + return skipWhile((value) => value.name != route).skip(1).toList(); | ||
| 116 | + } | ||
| 117 | +} | 
- 
Please register or login to post a comment