Toggle navigation
Toggle navigation
This project
Loading...
Sign in
flutter_package
/
fluttertpc_get
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Ahmed Fwela
2021-05-31 00:21:42 +0200
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
c5a06ca0ad8f8b790aa5910ad3b1bed50a4fbf3e
c5a06ca0
1 parent
c3b673fb
WIP
successfully decoupled the logical routes from the visual routes
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
252 additions
and
73 deletions
example_nav2/lib/app/models/demo_product.dart
example_nav2/lib/app/modules/home/views/dashboard_view.dart
example_nav2/lib/app/modules/home/views/home_view.dart
example_nav2/lib/app/modules/product_details/bindings/product_details_binding.dart
example_nav2/lib/app/modules/product_details/controllers/product_details_controller.dart
example_nav2/lib/app/modules/product_details/views/product_details_view.dart
example_nav2/lib/app/modules/products/controllers/products_controller.dart
example_nav2/lib/app/modules/products/views/products_view.dart
example_nav2/lib/app/modules/profile/views/profile_view.dart
example_nav2/lib/app/routes/app_pages.dart
example_nav2/lib/app/routes/app_routes.dart
lib/get_instance/src/extension_instance.dart
lib/get_navigation/src/nav2/get_router_delegate.dart
lib/get_navigation/src/nav2/router_outlet.dart
example_nav2/lib/app/models/demo_product.dart
0 → 100644
View file @
c5a06ca
class
DemoProduct
{
final
String
name
;
final
String
id
;
DemoProduct
({
required
this
.
name
,
required
this
.
id
,
});
}
...
...
example_nav2/lib/app/modules/home/views/dashboard_view.dart
0 → 100644
View file @
c5a06ca
import
'package:example_nav2/app/modules/home/controllers/home_controller.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
class
DashboardView
extends
GetView
<
HomeController
>
{
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
body:
Center
(
child:
Text
(
'DashboardView is working'
,
style:
TextStyle
(
fontSize:
20
),
),
),
);
}
}
...
...
example_nav2/lib/app/modules/home/views/home_view.dart
View file @
c5a06ca
import
'package:example_nav2/app/modules/home/views/dashboard_view.dart'
;
import
'package:example_nav2/app/routes/app_pages.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get_navigation/src/nav2/get_router_delegate.dart'
;
import
'package:get/get_navigation/src/nav2/router_outlet.dart'
;
import
'../controllers/home_controller.dart'
;
class
HomeView
extends
GetView
<
HomeController
>
{
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'HomeView'
),
centerTitle:
true
,
),
body:
Center
(
child:
Text
(
'HomeView is working'
,
style:
TextStyle
(
fontSize:
20
),
),
),
return
GetRouterOutlet
.
builder
(
builder:
(
context
,
delegate
,
currentRoute
)
{
final
title
=
currentRoute
?.
title
;
final
currentName
=
currentRoute
?.
name
;
var
currentIndex
=
0
;
if
(
currentName
?.
startsWith
(
Routes
.
PRODUCTS
)
==
true
)
currentIndex
=
2
;
if
(
currentName
?.
startsWith
(
Routes
.
PROFILE
)
==
true
)
currentIndex
=
1
;
return
Scaffold
(
appBar:
title
==
null
?
null
:
AppBar
(
title:
Text
(
title
),
centerTitle:
true
,
),
body:
GetRouterOutlet
(
emptyStackPage:
(
delegate
)
=>
DashboardView
(),
pickPages:
(
currentNavStack
)
{
// will take any route after home
final
res
=
currentNavStack
.
pickAfterRoute
(
Routes
.
HOME
);
print
(
'''RouterOutlet rebuild:
currentStack:
$currentNavStack
pickedStack:
$res
'''
);
return
res
;
},
),
bottomNavigationBar:
BottomNavigationBar
(
currentIndex:
currentIndex
,
onTap:
(
value
)
{
final
getDelegate
=
Get
.
getDelegate
();
if
(
getDelegate
==
null
)
return
;
switch
(
value
)
{
case
0
:
getDelegate
.
offUntil
(
Routes
.
HOME
);
break
;
case
1
:
getDelegate
.
toNamed
(
Routes
.
PROFILE
);
break
;
case
2
:
getDelegate
.
toNamed
(
Routes
.
PRODUCTS
);
break
;
default
:
}
},
items:
[
// Routes.Home + [Empty]
BottomNavigationBarItem
(
icon:
Icon
(
Icons
.
home
),
label:
'Home'
,
),
// Routes.Home + Routes.Profile
BottomNavigationBarItem
(
icon:
Icon
(
Icons
.
account_box_rounded
),
label:
'Profile'
,
),
// Routes.Home + Routes.Products
BottomNavigationBarItem
(
icon:
Icon
(
Icons
.
account_box_rounded
),
label:
'Products'
,
),
],
),
);
},
);
}
}
...
...
example_nav2/lib/app/modules/product_details/bindings/product_details_binding.dart
View file @
c5a06ca
...
...
@@ -5,8 +5,10 @@ import '../controllers/product_details_controller.dart';
class
ProductDetailsBinding
extends
Bindings
{
@override
void
dependencies
()
{
Get
.
lazyPut
<
ProductDetailsController
>(
()
=>
ProductDetailsController
(),
Get
.
create
<
ProductDetailsController
>(
()
=>
ProductDetailsController
(
Get
.
parameters
[
'productId'
]
??
''
,
),
);
}
}
...
...
example_nav2/lib/app/modules/product_details/controllers/product_details_controller.dart
View file @
c5a06ca
import
'package:get/get.dart'
;
class
ProductDetailsController
extends
GetxController
{}
class
ProductDetailsController
extends
GetxController
{
final
String
productId
;
ProductDetailsController
(
this
.
productId
);
}
...
...
example_nav2/lib/app/modules/product_details/views/product_details_view.dart
View file @
c5a06ca
...
...
@@ -4,18 +4,20 @@ import 'package:get/get.dart';
import
'../controllers/product_details_controller.dart'
;
class
ProductDetailsView
extends
Get
View
<
ProductDetailsController
>
{
class
ProductDetailsView
extends
Get
Widget
<
ProductDetailsController
>
{
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'ProductDetailsView'
),
centerTitle:
true
,
),
body:
Center
(
child:
Text
(
'ProductDetailsView is working'
,
style:
TextStyle
(
fontSize:
20
),
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
Text
(
'ProductDetailsView is working'
,
style:
TextStyle
(
fontSize:
20
),
),
Text
(
'ProductId:
${controller.productId}
'
)
],
),
),
);
...
...
example_nav2/lib/app/modules/products/controllers/products_controller.dart
View file @
c5a06ca
import
'package:example_nav2/app/models/demo_product.dart'
;
import
'package:get/get.dart'
;
class
ProductsController
extends
GetxController
{
//TODO: Implement ProductsController
final
products
=
<
DemoProduct
>[].
obs
;
final
count
=
0
.
obs
;
@override
void
onInit
()
{
super
.
onInit
();
void
loadDemoProductsFromSomeWhere
()
{
products
.
add
(
DemoProduct
(
name:
'Product added on:
${DateTime.now().toString()}
'
,
id:
DateTime
.
now
().
millisecondsSinceEpoch
.
toString
(),
),
);
}
@override
void
onReady
()
{
super
.
onReady
();
loadDemoProductsFromSomeWhere
();
}
@override
void
onClose
()
{}
void
increment
()
=>
count
.
value
++;
}
...
...
example_nav2/lib/app/modules/products/views/products_view.dart
View file @
c5a06ca
import
'package:example_nav2/app/routes/app_pages.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
...
...
@@ -8,14 +9,29 @@ class ProductsView extends GetView<ProductsController> {
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'ProductsView'
),
centerTitle:
true
,
floatingActionButton:
FloatingActionButton
.
extended
(
onPressed:
controller
.
loadDemoProductsFromSomeWhere
,
label:
Text
(
'Add'
),
),
body:
Center
(
child:
Text
(
'ProductsView is working'
,
style:
TextStyle
(
fontSize:
20
),
body:
Obx
(
()
=>
RefreshIndicator
(
onRefresh:
()
async
{
controller
.
products
.
clear
();
controller
.
loadDemoProductsFromSomeWhere
();
},
child:
ListView
.
builder
(
itemCount:
controller
.
products
.
length
,
itemBuilder:
(
context
,
index
)
{
final
item
=
controller
.
products
[
index
];
return
ListTile
(
onTap:
()
{
Get
.
getDelegate
()?.
toNamed
(
Routes
.
PRODUCT_DETAILS
(
item
.
id
));
},
title:
Text
(
item
.
name
),
subtitle:
Text
(
item
.
id
),
);
},
),
),
),
);
...
...
example_nav2/lib/app/modules/profile/views/profile_view.dart
View file @
c5a06ca
...
...
@@ -8,10 +8,6 @@ class ProfileView extends GetView<ProfileController> {
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'ProfileView'
),
centerTitle:
true
,
),
body:
Center
(
child:
Text
(
'ProfileView is working'
,
...
...
example_nav2/lib/app/routes/app_pages.dart
View file @
c5a06ca
import
'package:get/get.dart'
;
import
'package:get/get_navigation/src/nav2/router_outlet.dart'
;
import
'../modules/home/bindings/home_binding.dart'
;
import
'../modules/home/views/home_view.dart'
;
import
'../modules/product_details/bindings/product_details_binding.dart'
;
...
...
@@ -22,24 +22,34 @@ class AppPages {
GetPage
(
name:
_Paths
.
HOME
,
page:
()
=>
HomeView
(),
binding:
HomeBinding
(),
//TODO: don't group bindings in one place, and instead make each page use its own binding
bindings:
[
HomeBinding
(),
//These must use [Get.lazyPut] or [Get.create] because their view is created long after they are declared
ProfileBinding
(),
ProductsBinding
(),
ProductDetailsBinding
(),
],
title:
null
,
middlewares:
[
RouterOutletContainerMiddleWare
(
_Paths
.
HOME
),
],
children:
[
GetPage
(
name:
_Paths
.
PROFILE
,
page:
()
=>
ProfileView
(),
binding:
ProfileBinding
()
,
title:
'Profile'
,
),
],
),
GetPage
(
name:
_Paths
.
PRODUCTS
,
page:
()
=>
ProductsView
(),
binding:
ProductsBinding
(),
children:
[
GetPage
(
name:
_Paths
.
PRODUCT_DETAILS
,
page:
()
=>
ProductDetailsView
(),
binding:
ProductDetailsBinding
(),
name:
_Paths
.
PRODUCTS
,
page:
()
=>
ProductsView
(),
title:
'Products'
,
children:
[
GetPage
(
name:
_Paths
.
PRODUCT_DETAILS
,
page:
()
=>
ProductDetailsView
(),
),
],
),
],
),
...
...
example_nav2/lib/app/routes/app_routes.dart
View file @
c5a06ca
...
...
@@ -5,12 +5,12 @@ abstract class Routes {
Routes
.
_
();
static
const
HOME
=
_Paths
.
HOME
;
static
const
PROFILE
=
_Paths
.
PROFILE
;
static
const
PROFILE
=
_Paths
.
HOME
+
_Paths
.
PROFILE
;
static
const
SETTINGS
=
_Paths
.
SETTINGS
;
static
const
PRODUCTS
=
_Paths
.
PRODUCTS
;
static
PRODUCT_DETAILS
(
String
productId
)
=>
'
${_Paths.PRODUCTS}
/
$productId
'
;
static
const
PRODUCTS
=
_Paths
.
HOME
+
_Paths
.
PRODUCTS
;
static
String
PRODUCT_DETAILS
(
String
productId
)
=>
'
$PRODUCTS
/
$productId
'
;
}
abstract
class
_Paths
{
...
...
lib/get_instance/src/extension_instance.dart
View file @
c5a06ca
import
'package:flutter/widgets.dart'
;
import
'package:get/get_navigation/src/nav2/get_router_delegate.dart'
;
import
'../../get_core/src/get_interface.dart'
;
import
'../../route_manager.dart'
;
import
'get_instance.dart'
;
extension
Inst
on
GetInterface
{
...
...
@@ -127,4 +129,6 @@ extension Inst on GetInterface {
/// Casts the stored router delegate to a desired type
TDelegate
?
delegate
<
TDelegate
extends
RouterDelegate
<
TPage
>,
TPage
>()
=>
routerDelegate
as
TDelegate
?;
GetDelegate
?
getDelegate
()
=>
delegate
<
GetDelegate
,
GetPage
>();
}
...
...
lib/get_navigation/src/nav2/get_router_delegate.dart
View file @
c5a06ca
import
'dart:async'
;
import
'package:flutter/material.dart'
;
import
'package:get/get_navigation/src/nav2/router_outlet.dart'
;
import
'../../../get.dart'
;
import
'../../../get_state_manager/src/simple/list_notifier.dart'
;
...
...
@@ -8,7 +9,7 @@ class GetDelegate extends RouterDelegate<GetPage>
with
ListenableMixin
,
ListNotifierMixin
{
final
List
<
GetPage
>
routes
=
<
GetPage
>[];
final
GetPage
?
notFoundRoute
;
GetPage
?
notFoundRoute
;
final
List
<
NavigatorObserver
>?
dipNavObservers
;
final
TransitionDelegate
<
dynamic
>?
transitionDelegate
;
...
...
@@ -19,15 +20,27 @@ class GetDelegate extends RouterDelegate<GetPage>
GetDelegate
(
{
this
.
notFoundRoute
,
this
.
dipNavObservers
,
this
.
transitionDelegate
});
List
<
GetPage
>
getVisiblePages
()
{
return
routes
.
where
((
r
)
{
final
mware
=
(
r
.
middlewares
??
[]).
whereType
<
RouterOutletContainerMiddleWare
>();
if
(
mware
.
length
==
0
)
return
true
;
return
r
.
name
==
mware
.
first
.
stayAt
;
}).
toList
();
}
/// Called by the [Router] at startup with the structure that the
/// [RouteInformationParser] obtained from parsing the initial route.
@override
Widget
build
(
BuildContext
context
)
{
final
pages
=
getVisiblePages
();
return
Navigator
(
key:
navigatorKey
,
onPopPage:
_onPopPage
,
pages:
routes
.
toList
(),
observers:
[
GetObserver
()],
pages:
pages
,
observers:
[
GetObserver
(),
],
transitionDelegate:
transitionDelegate
??
const
DefaultTransitionDelegate
<
dynamic
>(),
);
...
...
@@ -73,13 +86,12 @@ class GetDelegate extends RouterDelegate<GetPage>
}
GetPage
_notFound
()
{
return
notFoundRoute
??
GetPage
(
name:
'/404'
,
page:
()
=>
Scaffold
(
body:
Text
(
'not found'
),
),
);
return
notFoundRoute
??=
GetPage
(
name:
'/404'
,
page:
()
=>
Scaffold
(
body:
Text
(
'not found'
),
),
);
}
Future
<
T
?>
pushRoute
<
T
>(
...
...
lib/get_navigation/src/nav2/router_outlet.dart
View file @
c5a06ca
import
'dart:js'
;
import
'package:flutter/material.dart'
;
import
'package:get/get_navigation/src/nav2/get_router_delegate.dart'
;
import
'../../../get.dart'
;
class
RouterOutlet
<
TDelegate
extends
RouterDelegate
<
T
>,
T
extends
Object
>
...
...
@@ -23,13 +22,13 @@ class RouterOutlet<TDelegate extends RouterDelegate<T>, T extends Object>
TDelegate
?
delegate
,
required
List
<
T
>
Function
(
TDelegate
routerDelegate
)
currentNavStack
,
required
List
<
T
>
Function
(
List
<
T
>
currentNavStack
)
pickPages
,
required
Widget
Function
(
T
?
page
)
pageBuilder
,
required
Widget
Function
(
T
Delegate
,
T
?
page
)
pageBuilder
,
})
:
this
.
builder
(
builder:
(
context
,
rDelegate
,
currentConfig
)
{
final
currentStack
=
currentNavStack
(
rDelegate
);
final
picked
=
pickPages
(
currentStack
);
if
(
picked
.
length
==
0
)
return
pageBuilder
(
null
);
return
pageBuilder
(
picked
.
last
);
if
(
picked
.
length
==
0
)
return
pageBuilder
(
rDelegate
,
null
);
return
pageBuilder
(
rDelegate
,
picked
.
last
);
},
delegate:
delegate
,
);
...
...
@@ -66,3 +65,53 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
return
widget
.
builder
(
context
,
delegate
,
currentRoute
);
}
}
class
GetRouterOutlet
extends
RouterOutlet
<
GetDelegate
,
GetPage
>
{
GetRouterOutlet
.
builder
({
required
Widget
Function
(
BuildContext
context
,
GetDelegate
delegate
,
GetPage
?
currentRoute
,
)
builder
,
GetDelegate
?
routerDelegate
,
})
:
super
.
builder
(
builder:
builder
,
delegate:
routerDelegate
,
);
GetRouterOutlet
({
Widget
Function
(
GetDelegate
delegate
)?
emptyStackPage
,
required
List
<
GetPage
>
Function
(
List
<
GetPage
>
currentNavStack
)
pickPages
,
})
:
super
(
pageBuilder:
(
rDelegate
,
page
)
=>
(
page
?.
page
()
??
emptyStackPage
?.
call
(
rDelegate
)
??
rDelegate
.
notFoundRoute
?.
page
())
??
SizedBox
.
shrink
(),
currentNavStack:
(
routerDelegate
)
=>
routerDelegate
.
routes
,
pickPages:
pickPages
,
delegate:
Get
.
routerDelegate
as
GetDelegate
,
);
}
class
RouterOutletContainerMiddleWare
extends
GetMiddleware
{
final
String
stayAt
;
RouterOutletContainerMiddleWare
(
this
.
stayAt
);
@override
RouteSettings
?
redirect
(
String
?
route
)
{
print
(
'RouterOutletContainerMiddleWare: Redirect called (
$route
)'
);
return
null
;
}
}
extension
PagesListExt
on
List
<
GetPage
>
{
List
<
GetPage
>
pickAtRoute
(
String
route
)
{
return
skipWhile
((
value
)
=>
value
.
name
!=
route
).
toList
();
}
List
<
GetPage
>
pickAfterRoute
(
String
route
)
{
return
skipWhile
((
value
)
=>
value
.
name
!=
route
).
skip
(
1
).
toList
();
}
}
...
...
Please
register
or
login
to post a comment