Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
89d1b9e4
Unverified
Commit
89d1b9e4
authored
Aug 18, 2021
by
chunhtai
Committed by
GitHub
Aug 18, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Makes PlatformInformationProvider aware of the browser default route … (#88122)
parent
7864e64d
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
147 additions
and
148 deletions
+147
-148
router.dart
packages/flutter/lib/src/widgets/router.dart
+72
-75
route_notification_messages_test.dart
...lutter/test/widgets/route_notification_messages_test.dart
+9
-0
router_test.dart
packages/flutter/test/widgets/router_test.dart
+66
-73
No files found.
packages/flutter/lib/src/widgets/router.dart
View file @
89d1b9e4
...
@@ -201,39 +201,36 @@ class RouteInformation {
...
@@ -201,39 +201,36 @@ class RouteInformation {
/// method.
/// method.
///
///
/// If the location in the new route information is different from the
/// If the location in the new route information is different from the
/// current location, this is considered to be a navigation event, the router
/// current location, this is considered to be a navigation event, the
/// sends the new route information to the [routeInformationProvider]'s
/// [PlatformRouteInformationProvider.routerReportsNewRouteInformation] method
/// [RouteInformationProvider.routerReportsNewRouteInformation] method with
/// calls [SystemNavigator.routeInformationUpdated] with `replace = false` to
/// `isNavigation` equals to true. That method as implemented in
/// notify the engine, and through that the browser, to create a history entry
/// [PlatformRouteInformationProvider] uses
/// with the new url. Otherwise,
/// [SystemNavigator.routeInformationUpdated] to notify the engine, and through
/// [PlatformRouteInformationProvider.routerReportsNewRouteInformation] calls
/// that the browser, to create a history entry with the new url if the
/// [SystemNavigator.routeInformationUpdated] with `replace = true` to update
/// `isNavigation` is true.
/// the current history entry with the latest [RouteInformation].
///
/// If the location is the same as the current location but different state,
/// the router still sends the new route information to the
/// [routeInformationProvider]'s
/// [RouteInformationProvider.routerReportsNewRouteInformation] but with
/// `isNavigation` equals to false. This causes
/// [PlatformRouteInformationProvider] replace current history entry instead
/// of creating a new one.
///
///
/// One can force the [Router] to report new route information as navigation
/// One can force the [Router] to report new route information as navigation
/// event to the [routeInformationProvider] (and thus the browser) even if the
/// event to the [routeInformationProvider] (and thus the browser) even if the
/// [RouteInformation.location] has not changed by calling the [Router.navigate]
/// [RouteInformation.location] has not changed by calling the [Router.navigate]
/// method with a callback that performs the state change. This allows one to
/// method with a callback that performs the state change. This causes [Router]
/// support the browser's back and forward buttons without changing the URL. For
/// to call the [RouteInformationProvider.routerReportsNewRouteInformation] with
/// example, the scroll position of a scroll view may be saved in the
/// [RouteInformationReportingType.navigate], and thus causes
/// [RouteInformation.state]. Using [Router.navigate] to update the scroll
/// [PlatformRouteInformationProvider] to push a new history entry regardlessly.
/// position causes the browser to create a new history entry with the
/// This allows one to support the browser's back and forward buttons without
/// changing the URL. For example, the scroll position of a scroll view may be
/// saved in the [RouteInformation.state]. Using [Router.navigate] to update the
/// scroll position causes the browser to create a new history entry with the
/// [RouteInformation.state] that stores this new scroll position. When the user
/// [RouteInformation.state] that stores this new scroll position. When the user
/// clicks the back button, the app will go back to the previous scroll position
/// clicks the back button, the app will go back to the previous scroll position
/// without changing the URL in the location bar.
/// without changing the URL in the location bar.
///
///
/// One can also force the [Router] to ignore a navigation event by making
/// One can also force the [Router] to ignore a navigation event by making
/// those changes during a callback passed to [Router.neglect]. The [Router]
/// those changes during a callback passed to [Router.neglect]. The [Router]
/// will not report the route information with `isNavigation` equals to false
/// calls the [RouteInformationProvider.routerReportsNewRouteInformation] with
/// even if it detects location change as the result of running the callback.
/// [RouteInformationReportingType.neglect], and thus causes
/// [PlatformRouteInformationProvider] to replace the current history entry
/// regardlessly even if it detects location change.
///
///
/// To opt out of URL updates entirely, pass null for [routeInformationProvider]
/// To opt out of URL updates entirely, pass null for [routeInformationProvider]
/// and [routeInformationParser]. This is not recommended in general, but may be
/// and [routeInformationParser]. This is not recommended in general, but may be
...
@@ -432,7 +429,7 @@ class Router<T> extends StatefulWidget {
...
@@ -432,7 +429,7 @@ class Router<T> extends StatefulWidget {
final
_RouterScope
scope
=
context
final
_RouterScope
scope
=
context
.
getElementForInheritedWidgetOfExactType
<
_RouterScope
>()!
.
getElementForInheritedWidgetOfExactType
<
_RouterScope
>()!
.
widget
as
_RouterScope
;
.
widget
as
_RouterScope
;
scope
.
routerState
.
_setStateWithExplicitReportStatus
(
_IntentionToReportRouteInformation
.
must
,
callback
);
scope
.
routerState
.
_setStateWithExplicitReportStatus
(
RouteInformationReportingType
.
navigate
,
callback
);
}
}
/// Forces the [Router] to run the [callback] without creating a new history
/// Forces the [Router] to run the [callback] without creating a new history
...
@@ -461,7 +458,7 @@ class Router<T> extends StatefulWidget {
...
@@ -461,7 +458,7 @@ class Router<T> extends StatefulWidget {
final
_RouterScope
scope
=
context
final
_RouterScope
scope
=
context
.
getElementForInheritedWidgetOfExactType
<
_RouterScope
>()!
.
getElementForInheritedWidgetOfExactType
<
_RouterScope
>()!
.
widget
as
_RouterScope
;
.
widget
as
_RouterScope
;
scope
.
routerState
.
_setStateWithExplicitReportStatus
(
_IntentionToReportRouteInformation
.
ignore
,
callback
);
scope
.
routerState
.
_setStateWithExplicitReportStatus
(
RouteInformationReportingType
.
neglect
,
callback
);
}
}
@override
@override
...
@@ -471,22 +468,33 @@ class Router<T> extends StatefulWidget {
...
@@ -471,22 +468,33 @@ class Router<T> extends StatefulWidget {
typedef
_AsyncPassthrough
<
Q
>
=
Future
<
Q
>
Function
(
Q
);
typedef
_AsyncPassthrough
<
Q
>
=
Future
<
Q
>
Function
(
Q
);
typedef
_DelegateRouteSetter
<
T
>
=
Future
<
void
>
Function
(
T
);
typedef
_DelegateRouteSetter
<
T
>
=
Future
<
void
>
Function
(
T
);
// Whether to report the route information in this build cycle.
/// The [Router]'s intention when it reports a new [RouteInformation] to the
enum
_IntentionToReportRouteInformation
{
/// [RouteInformationProvider].
// We haven't receive any signal on whether to report.
///
/// See also:
///
/// * [RouteInformationProvider.routerReportsNewRouteInformation]: which is
/// called by the router when it has a new route information to report.
enum
RouteInformationReportingType
{
/// Router does not have a specific intention.
///
/// The router generates a new route information every time it detects route
/// information may have change due to a rebuild. This is the default type if
/// neither [Router.neglect] nor [Router.navigate] was used during the
/// rebuild.
none
,
none
,
//
Report if route information changes.
//
/ The accompanying [RouteInformation] were generated during a
maybe
,
/// [Router.neglect] call.
// Report regardless of route information changes.
neglect
,
must
,
/// The accompanying [RouteInformation] were generated during a
//
Don't report regardless of route information changes
.
//
/ [Router.navigate] call
.
ignor
e
,
navigat
e
,
}
}
class
_RouterState
<
T
>
extends
State
<
Router
<
T
>>
with
RestorationMixin
{
class
_RouterState
<
T
>
extends
State
<
Router
<
T
>>
with
RestorationMixin
{
Object
?
_currentRouteInformationParserTransaction
;
Object
?
_currentRouteInformationParserTransaction
;
Object
?
_currentRouterDelegateTransaction
;
Object
?
_currentRouterDelegateTransaction
;
_IntentionToReportRouteInformation
_currentIntentionToReport
=
_IntentionToReportRouteInformation
.
none
;
RouteInformationReportingType
?
_currentIntentionToReport
;
final
_RestorableRouteInformation
_routeInformation
=
_RestorableRouteInformation
();
final
_RestorableRouteInformation
_routeInformation
=
_RestorableRouteInformation
();
@override
@override
...
@@ -515,7 +523,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
...
@@ -515,7 +523,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
void
_scheduleRouteInformationReportingTask
()
{
void
_scheduleRouteInformationReportingTask
()
{
if
(
_routeInformationReportingTaskScheduled
||
widget
.
routeInformationProvider
==
null
)
if
(
_routeInformationReportingTaskScheduled
||
widget
.
routeInformationProvider
==
null
)
return
;
return
;
assert
(
_currentIntentionToReport
!=
_IntentionToReportRouteInformation
.
none
);
assert
(
_currentIntentionToReport
!=
null
);
_routeInformationReportingTaskScheduled
=
true
;
_routeInformationReportingTaskScheduled
=
true
;
SchedulerBinding
.
instance
!.
addPostFrameCallback
(
_reportRouteInformation
);
SchedulerBinding
.
instance
!.
addPostFrameCallback
(
_reportRouteInformation
);
}
}
...
@@ -525,31 +533,11 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
...
@@ -525,31 +533,11 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
_routeInformationReportingTaskScheduled
=
false
;
_routeInformationReportingTaskScheduled
=
false
;
if
(
_routeInformation
.
value
!=
null
)
{
if
(
_routeInformation
.
value
!=
null
)
{
final
RouteInformation
oldRouteInformation
=
widget
.
routeInformationProvider
!.
value
;
final
RouteInformation
currentRouteInformation
=
_routeInformation
.
value
!;
final
RouteInformation
currentRouteInformation
=
_routeInformation
.
value
!;
switch
(
_currentIntentionToReport
)
{
assert
(
_currentIntentionToReport
!=
null
);
case
_IntentionToReportRouteInformation
.
none
:
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
,
type:
_currentIntentionToReport
!);
assert
(
false
,
'_reportRouteInformation must not be called with _IntentionToReportRouteInformation.none'
);
return
;
case
_IntentionToReportRouteInformation
.
ignore
:
if
(
oldRouteInformation
.
location
!=
currentRouteInformation
.
location
||
oldRouteInformation
.
state
!=
currentRouteInformation
.
state
)
{
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
,
isNavigation:
false
);
}
}
break
;
_currentIntentionToReport
=
RouteInformationReportingType
.
none
;
case
_IntentionToReportRouteInformation
.
maybe
:
if
(
oldRouteInformation
.
location
!=
currentRouteInformation
.
location
)
{
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
);
}
else
if
(
oldRouteInformation
.
state
!=
currentRouteInformation
.
state
)
{
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
,
isNavigation:
false
);
}
break
;
case
_IntentionToReportRouteInformation
.
must
:
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
);
break
;
}
}
_currentIntentionToReport
=
_IntentionToReportRouteInformation
.
none
;
}
}
RouteInformation
?
_retrieveNewRouteInformation
()
{
RouteInformation
?
_retrieveNewRouteInformation
()
{
...
@@ -560,13 +548,14 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
...
@@ -560,13 +548,14 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
}
}
void
_setStateWithExplicitReportStatus
(
void
_setStateWithExplicitReportStatus
(
_IntentionToReportRouteInformation
status
,
RouteInformationReportingType
status
,
VoidCallback
fn
,
VoidCallback
fn
,
)
{
)
{
assert
(
status
!=
null
);
assert
(
status
!=
null
);
assert
(
status
.
index
>=
_IntentionToReportRouteInformation
.
mus
t
.
index
);
assert
(
status
.
index
>=
RouteInformationReportingType
.
neglec
t
.
index
);
assert
(()
{
assert
(()
{
if
(
_currentIntentionToReport
.
index
>=
_IntentionToReportRouteInformation
.
must
.
index
&&
if
(
_currentIntentionToReport
!=
null
&&
_currentIntentionToReport
!=
RouteInformationReportingType
.
none
&&
_currentIntentionToReport
!=
status
)
{
_currentIntentionToReport
!=
status
)
{
FlutterError
.
reportError
(
FlutterError
.
reportError
(
const
FlutterErrorDetails
(
const
FlutterErrorDetails
(
...
@@ -587,9 +576,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
...
@@ -587,9 +576,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
void
_maybeNeedToReportRouteInformation
()
{
void
_maybeNeedToReportRouteInformation
()
{
_routeInformation
.
value
=
_retrieveNewRouteInformation
();
_routeInformation
.
value
=
_retrieveNewRouteInformation
();
_currentIntentionToReport
=
_currentIntentionToReport
!=
_IntentionToReportRouteInformation
.
none
_currentIntentionToReport
??=
RouteInformationReportingType
.
none
;
?
_currentIntentionToReport
:
_IntentionToReportRouteInformation
.
maybe
;
_scheduleRouteInformationReportingTask
();
_scheduleRouteInformationReportingTask
();
}
}
...
@@ -1325,19 +1312,21 @@ abstract class RouteInformationProvider extends ValueListenable<RouteInformation
...
@@ -1325,19 +1312,21 @@ abstract class RouteInformationProvider extends ValueListenable<RouteInformation
/// other side effects. For example, the [PlatformRouteInformationProvider]
/// other side effects. For example, the [PlatformRouteInformationProvider]
/// overrides this method to report the route information back to the engine.
/// overrides this method to report the route information back to the engine.
///
///
/// The [routeInformation] is the new route information after the navigation
/// The `routeInformation` is the new route information generated by the
/// event.
/// Router rebuild, and it can be the same or different from the
/// [value].
///
///
/// The [isNavigation] denotes whether the new route information is generated
/// The `type` denotes the [Router]'s intention when it reports this
/// as a result of a navigation event. This information can be useful in a
/// `routeInformation`. It is useful when deciding how to update the internal
/// web application, for example, the [PlatformRouteInformationProvider] uses
/// state of [RouteInformationProvider] subclass with the `routeInformation`.
/// this flag to decide whether to create a browser history entry that enables
/// For example, [PlatformRouteInformationProvider] uses this property to
/// browser backward and forward buttons.
/// decide whether to push or replace the browser history entry with the new
/// `routeInformation`.
///
///
/// For more information on how [Router] determines a navigation event, see
/// For more information on how [Router] determines a navigation event, see
/// the "URL updates for web applications" section in the [Router]
/// the "URL updates for web applications" section in the [Router]
/// documentation.
/// documentation.
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
bool
isNavigation
=
tru
e
})
{}
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
required
RouteInformationReportingType
typ
e
})
{}
}
}
/// The route information provider that propagates the platform route information changes.
/// The route information provider that propagates the platform route information changes.
...
@@ -1360,24 +1349,32 @@ class PlatformRouteInformationProvider extends RouteInformationProvider with Wid
...
@@ -1360,24 +1349,32 @@ class PlatformRouteInformationProvider extends RouteInformationProvider with Wid
})
:
_value
=
initialRouteInformation
;
})
:
_value
=
initialRouteInformation
;
@override
@override
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
bool
isNavigation
=
true
})
{
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
required
RouteInformationReportingType
type
})
{
final
bool
replace
=
type
==
RouteInformationReportingType
.
neglect
||
(
type
==
RouteInformationReportingType
.
none
&&
_valueInEngine
.
location
==
routeInformation
.
location
);
SystemNavigator
.
selectMultiEntryHistory
();
SystemNavigator
.
selectMultiEntryHistory
();
SystemNavigator
.
routeInformationUpdated
(
SystemNavigator
.
routeInformationUpdated
(
location:
routeInformation
.
location
!,
location:
routeInformation
.
location
!,
state:
routeInformation
.
state
,
state:
routeInformation
.
state
,
replace:
!
isNavigation
,
replace:
replace
,
);
);
_value
=
routeInformation
;
_value
=
routeInformation
;
_valueInEngine
=
routeInformation
;
}
}
@override
@override
RouteInformation
get
value
=>
_value
;
RouteInformation
get
value
=>
_value
;
RouteInformation
_value
;
RouteInformation
_value
;
RouteInformation
_valueInEngine
=
RouteInformation
(
location:
WidgetsBinding
.
instance
!.
window
.
defaultRouteName
);
void
_platformReportsNewRouteInformation
(
RouteInformation
routeInformation
)
{
void
_platformReportsNewRouteInformation
(
RouteInformation
routeInformation
)
{
if
(
_value
==
routeInformation
)
if
(
_value
==
routeInformation
)
return
;
return
;
_value
=
routeInformation
;
_value
=
routeInformation
;
_valueInEngine
=
routeInformation
;
notifyListeners
();
notifyListeners
();
}
}
...
...
packages/flutter/test/widgets/route_notification_messages_test.dart
View file @
89d1b9e4
...
@@ -286,6 +286,15 @@ void main() {
...
@@ -286,6 +286,15 @@ void main() {
routerDelegate:
delegate
,
routerDelegate:
delegate
,
));
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'initial'
,
'state'
:
null
,
'replace'
:
false
,
}),
]);
log
.
clear
();
// Triggers a router rebuild and verify the route information is reported
// Triggers a router rebuild and verify the route information is reported
// to the web engine.
// to the web engine.
...
...
packages/flutter/test/widgets/router_test.dart
View file @
89d1b9e4
...
@@ -477,14 +477,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -477,14 +477,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
testWidgets
(
'router does report URL change correctly'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'router does report URL change correctly'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
reportedRouteInformation
;
RouteInformation
?
reportedRouteInformation
;
bool
?
reportedIsNavigation
;
RouteInformationReportingType
?
reportedType
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
onRouterReport:
(
RouteInformation
information
,
RouteInformationReportingType
type
)
{
// Makes sure we only report once after manually cleaning up.
// Makes sure we only report once after manually cleaning up.
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reported
IsNavigation
,
isNull
);
expect
(
reported
Type
,
isNull
);
reportedRouteInformation
=
information
;
reportedRouteInformation
=
information
;
reported
IsNavigation
=
isNavigation
;
reported
Type
=
type
;
},
},
);
);
final
SimpleRouterDelegate
delegate
=
SimpleRouterDelegate
(
final
SimpleRouterDelegate
delegate
=
SimpleRouterDelegate
(
...
@@ -514,7 +514,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -514,7 +514,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
),
),
));
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reportedRouteInformation
!.
location
,
'initial'
);
expect
(
reportedType
,
RouteInformationReportingType
.
none
);
reportedRouteInformation
=
null
;
reportedType
=
null
;
delegate
.
routeInformation
=
const
RouteInformation
(
delegate
.
routeInformation
=
const
RouteInformation
(
location:
'update'
,
location:
'update'
,
);
);
...
@@ -522,11 +525,11 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -522,11 +525,11 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
expect
(
reported
IsNavigation
,
isTru
e
);
expect
(
reported
Type
,
RouteInformationReportingType
.
non
e
);
// The router should report as non navigation event if only state changes.
// The router should report as non navigation event if only state changes.
reportedRouteInformation
=
null
;
reportedRouteInformation
=
null
;
reported
IsNavigation
=
null
;
reported
Type
=
null
;
delegate
.
routeInformation
=
const
RouteInformation
(
delegate
.
routeInformation
=
const
RouteInformation
(
location:
'update'
,
location:
'update'
,
state:
'another state'
,
state:
'another state'
,
...
@@ -535,31 +538,31 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -535,31 +538,31 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
expect
(
reportedRouteInformation
!.
state
,
'another state'
);
expect
(
reportedRouteInformation
!.
state
,
'another state'
);
expect
(
reported
IsNavigation
,
isFals
e
);
expect
(
reported
Type
,
RouteInformationReportingType
.
non
e
);
reportedRouteInformation
=
null
;
reportedRouteInformation
=
null
;
reported
IsNavigation
=
null
;
reported
Type
=
null
;
bool
result
=
false
;
bool
result
=
false
;
result
=
await
outerDispatcher
.
invokeCallback
(
SynchronousFuture
<
bool
>(
false
));
result
=
await
outerDispatcher
.
invokeCallback
(
SynchronousFuture
<
bool
>(
false
));
expect
(
result
,
isTrue
);
expect
(
result
,
isTrue
);
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
find
.
text
(
'popped'
),
findsOneWidget
);
expect
(
find
.
text
(
'popped'
),
findsOneWidget
);
expect
(
reportedRouteInformation
!.
location
,
'popped'
);
expect
(
reportedRouteInformation
!.
location
,
'popped'
);
expect
(
reported
IsNavigation
,
isTru
e
);
expect
(
reported
Type
,
RouteInformationReportingType
.
non
e
);
});
});
testWidgets
(
'router can be forced to recognize or ignore navigating events'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'router can be forced to recognize or ignore navigating events'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
reportedRouteInformation
;
RouteInformation
?
reportedRouteInformation
;
bool
?
reportedIsNavigation
;
RouteInformationReportingType
?
reportedType
;
bool
isNavigating
=
false
;
bool
isNavigating
=
false
;
late
RouteInformation
nextRouteInformation
;
late
RouteInformation
nextRouteInformation
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
onRouterReport:
(
RouteInformation
information
,
RouteInformationReportingType
type
)
{
// Makes sure we only report once after manually cleaning up.
// Makes sure we only report once after manually cleaning up.
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reported
IsNavigation
,
isNull
);
expect
(
reported
Type
,
isNull
);
reportedRouteInformation
=
information
;
reportedRouteInformation
=
information
;
reported
IsNavigation
=
isNavigation
;
reported
Type
=
type
;
},
},
);
);
provider
.
value
=
const
RouteInformation
(
provider
.
value
=
const
RouteInformation
(
...
@@ -595,7 +598,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -595,7 +598,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
),
),
));
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reportedRouteInformation
!.
location
,
'initial'
);
expect
(
reportedType
,
RouteInformationReportingType
.
none
);
reportedType
=
null
;
reportedRouteInformation
=
null
;
nextRouteInformation
=
const
RouteInformation
(
nextRouteInformation
=
const
RouteInformation
(
location:
'update'
,
location:
'update'
,
...
@@ -604,9 +610,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -604,9 +610,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
reported
IsNavigation
,
isFalse
);
expect
(
reported
Type
,
RouteInformationReportingType
.
neglect
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
reported
IsNavigation
=
null
;
reported
Type
=
null
;
reportedRouteInformation
=
null
;
reportedRouteInformation
=
null
;
isNavigating
=
true
;
isNavigating
=
true
;
...
@@ -615,21 +621,22 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -615,21 +621,22 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
// report a route information because isNavigating = true.
// report a route information because isNavigating = true.
await
tester
.
tap
(
find
.
byType
(
ElevatedButton
));
await
tester
.
tap
(
find
.
byType
(
ElevatedButton
));
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
reported
IsNavigation
,
isTru
e
);
expect
(
reported
Type
,
RouteInformationReportingType
.
navigat
e
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
reported
IsNavigation
=
null
;
reported
Type
=
null
;
reportedRouteInformation
=
null
;
reportedRouteInformation
=
null
;
});
});
testWidgets
(
'router ignore navigating events updates RouteInformationProvider'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'router ignore navigating events updates RouteInformationProvider'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
updatedRouteInformation
;
RouteInformation
?
updatedRouteInformation
;
late
RouteInformation
nextRouteInformation
;
late
RouteInformation
nextRouteInformation
;
RouteInformationReportingType
?
reportingType
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
onRouterReport:
(
RouteInformation
information
,
RouteInformationReportingType
type
)
{
// This should never be a navigation event.
expect
(
reportingType
,
isNull
);
expect
(
isNavigation
,
false
);
expect
(
updatedRouteInformation
,
isNull
);
expect
(
updatedRouteInformation
,
isNull
);
updatedRouteInformation
=
information
;
updatedRouteInformation
=
information
;
reportingType
=
type
;
},
},
);
);
provider
.
value
=
const
RouteInformation
(
provider
.
value
=
const
RouteInformation
(
...
@@ -658,7 +665,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -658,7 +665,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
),
),
));
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
updatedRouteInformation
,
isNull
);
expect
(
updatedRouteInformation
!.
location
,
'initial'
);
expect
(
reportingType
,
RouteInformationReportingType
.
none
);
updatedRouteInformation
=
null
;
reportingType
=
null
;
nextRouteInformation
=
const
RouteInformation
(
nextRouteInformation
=
const
RouteInformation
(
location:
'update'
,
location:
'update'
,
...
@@ -668,17 +678,20 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -668,17 +678,20 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
updatedRouteInformation
!.
location
,
'update'
);
expect
(
updatedRouteInformation
!.
location
,
'update'
);
expect
(
reportingType
,
RouteInformationReportingType
.
neglect
);
});
});
testWidgets
(
'state change without location changes updates RouteInformationProvider'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'state change without location changes updates RouteInformationProvider'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
updatedRouteInformation
;
RouteInformation
?
updatedRouteInformation
;
late
RouteInformation
nextRouteInformation
;
late
RouteInformation
nextRouteInformation
;
RouteInformationReportingType
?
reportingType
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
onRouterReport:
(
RouteInformation
information
,
RouteInformationReportingType
type
)
{
// This should never be a navigation event.
// This should never be a navigation event.
expect
(
isNavigation
,
false
);
expect
(
reportingType
,
isNull
);
expect
(
updatedRouteInformation
,
isNull
);
expect
(
updatedRouteInformation
,
isNull
);
updatedRouteInformation
=
information
;
updatedRouteInformation
=
information
;
reportingType
=
type
;
},
},
);
);
provider
.
value
=
const
RouteInformation
(
provider
.
value
=
const
RouteInformation
(
...
@@ -705,7 +718,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -705,7 +718,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
),
),
));
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
updatedRouteInformation
,
isNull
);
expect
(
updatedRouteInformation
!.
location
,
'initial'
);
expect
(
reportingType
,
RouteInformationReportingType
.
none
);
updatedRouteInformation
=
null
;
reportingType
=
null
;
nextRouteInformation
=
const
RouteInformation
(
nextRouteInformation
=
const
RouteInformation
(
location:
'initial'
,
location:
'initial'
,
...
@@ -715,45 +731,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -715,45 +731,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
updatedRouteInformation
!.
location
,
'initial'
);
expect
(
updatedRouteInformation
!.
location
,
'initial'
);
expect
(
updatedRouteInformation
!.
state
,
'state2'
);
expect
(
updatedRouteInformation
!.
state
,
'state2'
);
});
expect
(
reportingType
,
RouteInformationReportingType
.
none
);
testWidgets
(
'router does not report when route information is up to date with route information provider'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
reportedRouteInformation
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
reportedRouteInformation
=
information
;
},
);
provider
.
value
=
const
RouteInformation
(
location:
'initial'
,
);
final
SimpleRouterDelegate
delegate
=
SimpleRouterDelegate
(
reportConfiguration:
true
);
delegate
.
builder
=
(
BuildContext
context
,
RouteInformation
?
routeInformation
)
{
return
Text
(
routeInformation
!.
location
!);
};
await
tester
.
pumpWidget
(
buildBoilerPlate
(
Router
<
RouteInformation
>(
routeInformationProvider:
provider
,
routeInformationParser:
SimpleRouteInformationParser
(),
routerDelegate:
delegate
,
),
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
reportedRouteInformation
,
isNull
);
// This will cause the router to rebuild.
provider
.
value
=
const
RouteInformation
(
location:
'update'
,
);
// This will schedule the route reporting.
delegate
.
notifyListeners
();
await
tester
.
pump
();
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
// The router should not report because the route name is already up to
// date.
expect
(
reportedRouteInformation
,
isNull
);
});
});
testWidgets
(
'PlatformRouteInformationProvider works'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'PlatformRouteInformationProvider works'
,
(
WidgetTester
tester
)
async
{
...
@@ -823,18 +801,33 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -823,18 +801,33 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
);
);
log
.
clear
();
log
.
clear
();
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'a'
,
state:
true
));
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'a'
,
state:
true
),
type:
RouteInformationReportingType
.
none
);
// Implicit reporting pushes new history entry if the location changes.
expect
(
log
,
<
Object
>[
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'a'
,
'state'
:
true
,
'replace'
:
false
}),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'a'
,
'state'
:
true
,
'replace'
:
false
}),
]);
]);
log
.
clear
();
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'a'
,
state:
false
),
type:
RouteInformationReportingType
.
none
);
// Since the location is the same, the provider sends replaces message.
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'a'
,
'state'
:
false
,
'replace'
:
true
}),
]);
log
.
clear
();
log
.
clear
();
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'b'
,
state:
false
),
isNavigation:
false
);
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'b'
,
state:
false
),
type:
RouteInformationReportingType
.
neglect
);
expect
(
log
,
<
Object
>[
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'b'
,
'state'
:
false
,
'replace'
:
true
}),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'b'
,
'state'
:
false
,
'replace'
:
true
}),
]);
]);
log
.
clear
();
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'b'
,
state:
false
),
type:
RouteInformationReportingType
.
navigate
);
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'b'
,
'state'
:
false
,
'replace'
:
false
}),
]);
});
});
testWidgets
(
'RootBackButtonDispatcher works'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'RootBackButtonDispatcher works'
,
(
WidgetTester
tester
)
async
{
...
@@ -1239,7 +1232,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -1239,7 +1232,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
testWidgets
(
'Router reports location if it is different from location given by OS'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Router reports location if it is different from location given by OS'
,
(
WidgetTester
tester
)
async
{
final
List
<
RouteInformation
>
reportedRouteInformation
=
<
RouteInformation
>[];
final
List
<
RouteInformation
>
reportedRouteInformation
=
<
RouteInformation
>[];
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
info
,
bool
isNavigation
)
=>
reportedRouteInformation
.
add
(
info
),
onRouterReport:
(
RouteInformation
info
,
RouteInformationReportingType
type
)
=>
reportedRouteInformation
.
add
(
info
),
)..
value
=
const
RouteInformation
(
location:
'/home'
);
)..
value
=
const
RouteInformation
(
location:
'/home'
);
await
tester
.
pumpWidget
(
buildBoilerPlate
(
await
tester
.
pumpWidget
(
buildBoilerPlate
(
...
@@ -1256,13 +1249,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
...
@@ -1256,13 +1249,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
));
));
expect
(
find
.
text
(
'Current route: /home'
),
findsOneWidget
);
expect
(
find
.
text
(
'Current route: /home'
),
findsOneWidget
);
expect
(
reportedRouteInformation
,
isEmpty
);
expect
(
reportedRouteInformation
.
single
.
location
,
'/home'
);
provider
.
value
=
const
RouteInformation
(
location:
'/doesNotExist'
);
provider
.
value
=
const
RouteInformation
(
location:
'/doesNotExist'
);
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
find
.
text
(
'Current route: /404'
),
findsOneWidget
);
expect
(
find
.
text
(
'Current route: /404'
),
findsOneWidget
);
expect
(
reportedRouteInformation
.
single
.
location
,
'/404'
);
expect
(
reportedRouteInformation
[
1
]
.
location
,
'/404'
);
});
});
}
}
...
@@ -1277,7 +1270,7 @@ Widget buildBoilerPlate(Widget child) {
...
@@ -1277,7 +1270,7 @@ Widget buildBoilerPlate(Widget child) {
typedef
SimpleRouterDelegateBuilder
=
Widget
Function
(
BuildContext
,
RouteInformation
?);
typedef
SimpleRouterDelegateBuilder
=
Widget
Function
(
BuildContext
,
RouteInformation
?);
typedef
SimpleRouterDelegatePopRoute
=
Future
<
bool
>
Function
();
typedef
SimpleRouterDelegatePopRoute
=
Future
<
bool
>
Function
();
typedef
SimpleNavigatorRouterDelegatePopPage
<
T
>
=
bool
Function
(
Route
<
T
>
route
,
T
result
);
typedef
SimpleNavigatorRouterDelegatePopPage
<
T
>
=
bool
Function
(
Route
<
T
>
route
,
T
result
);
typedef
RouterReportRouterInformation
=
void
Function
(
RouteInformation
,
bool
);
typedef
RouterReportRouterInformation
=
void
Function
(
RouteInformation
,
RouteInformationReportingType
);
class
SimpleRouteInformationParser
extends
RouteInformationParser
<
RouteInformation
>
{
class
SimpleRouteInformationParser
extends
RouteInformationParser
<
RouteInformation
>
{
SimpleRouteInformationParser
();
SimpleRouteInformationParser
();
...
@@ -1398,9 +1391,9 @@ class SimpleRouteInformationProvider extends RouteInformationProvider with Chang
...
@@ -1398,9 +1391,9 @@ class SimpleRouteInformationProvider extends RouteInformationProvider with Chang
}
}
@override
@override
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
bool
isNavigation
=
tru
e
})
{
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
required
RouteInformationReportingType
typ
e
})
{
_value
=
routeInformation
;
_value
=
routeInformation
;
onRouterReport
?.
call
(
routeInformation
,
isNavigation
);
onRouterReport
?.
call
(
routeInformation
,
type
);
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment