Router replaces browser history entry if state changes (#83509)

diff --git a/packages/flutter/lib/src/services/system_navigator.dart b/packages/flutter/lib/src/services/system_navigator.dart
index 8a6b5b9..1c3d05d 100644
--- a/packages/flutter/lib/src/services/system_navigator.dart
+++ b/packages/flutter/lib/src/services/system_navigator.dart
@@ -67,20 +67,34 @@
 
   /// Notifies the platform for a route information change.
   ///
-  /// On web, creates a new browser history entry and update URL with the route
-  /// information. Whether the history holds one entry or multiple entries is
-  /// determined by [selectSingleEntryHistory] and [selectMultiEntryHistory].
+  /// On web, this method behaves differently based on the single-entry or
+  /// multiple-entries history mode. Use the [selectSingleEntryHistory] and
+  /// [selectMultiEntryHistory] to toggle between modes.
   ///
-  /// Currently, this is ignored on other platforms.
+  /// For single-entry mode, this method replaces the current URL and state in
+  /// the current history entry. The flag `replace` is ignored.
+  ///
+  /// For multiple-entries mode, this method creates a new history entry on top
+  /// of the current entry if the `replace` is false, thus the user will
+  /// be on a new history entry as if the user has visited a new page, and the
+  /// browser back button brings the user back to the previous entry. If
+  /// `replace` is true, this method only updates the URL and the state in the
+  /// current history entry without pushing a new one.
+  ///
+  /// This method is ignored on other platforms.
+  ///
+  /// The `replace` flag defaults to false.
   static Future<void> routeInformationUpdated({
     required String location,
     Object? state,
+    bool replace = false,
   }) {
     return SystemChannels.navigation.invokeMethod<void>(
       'routeInformationUpdated',
       <String, dynamic>{
         'location': location,
         'state': state,
+        'replace': replace,
       },
     );
   }
diff --git a/packages/flutter/lib/src/widgets/router.dart b/packages/flutter/lib/src/widgets/router.dart
index 8610aa2..a995eff 100644
--- a/packages/flutter/lib/src/widgets/router.dart
+++ b/packages/flutter/lib/src/widgets/router.dart
@@ -198,16 +198,28 @@
 /// retrieve the new route information from the [routerDelegate]'s
 /// [RouterDelegate.currentConfiguration] method and the
 /// [routeInformationParser]'s [RouteInformationParser.restoreRouteInformation]
-/// method. If the location in the new route information is different from the
-/// current location, the router sends the new route information to the
-/// [routeInformationProvider]'s
-/// [RouteInformationProvider.routerReportsNewRouteInformation] method. That
-/// method as implemented in [PlatformRouteInformationProvider] uses
-/// [SystemNavigator.routeInformationUpdated] to notify the engine, and through
-/// that the browser, of the new URL.
+/// method.
 ///
-/// One can force the [Router] to report new route information to the
-/// [routeInformationProvider] (and thus the browser) even if 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
+/// sends the new route information to the [routeInformationProvider]'s
+/// [RouteInformationProvider.routerReportsNewRouteInformation] method with
+/// `isNavigation` equals to true. That method as implemented in
+/// [PlatformRouteInformationProvider] uses
+/// [SystemNavigator.routeInformationUpdated] to notify the engine, and through
+/// that the browser, to create a history entry with the new url if the
+/// `isNavigation` is true.
+///
+/// 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
+/// event to the [routeInformationProvider] (and thus the browser) even if the
 /// [RouteInformation.location] has not changed by calling the [Router.navigate]
 /// method with a callback that performs the state change. This allows one to
 /// support the browser's back and forward buttons without changing the URL. For
@@ -218,10 +230,10 @@
 /// clicks the back button, the app will go back to the previous scroll position
 /// without changing the URL in the location bar.
 ///
-/// One can also force the [Router] to ignore application state changes by
-/// making those changes during a callback passed to [Router.neglect]. The
-/// [Router] will not report any route information even if it detects location
-/// change as a result of running the callback.
+/// One can also force the [Router] to ignore a navigation event by making
+/// those changes during a callback passed to [Router.neglect]. The [Router]
+/// will not report the route information with `isNavigation` equals to false
+/// even if it detects location change as the result of running the callback.
 ///
 /// To opt out of URL updates entirely, pass null for [routeInformationProvider]
 /// and [routeInformationParser]. This is not recommended in general, but may be
@@ -392,8 +404,8 @@
     return scope?.routerState.widget as Router<T>?;
   }
 
-  /// Forces the [Router] to run the [callback] and reports the route
-  /// information back to the engine.
+  /// Forces the [Router] to run the [callback] and create a new history
+  /// entry in the browser.
   ///
   /// The web application relies on the [Router] to report new route information
   /// in order to create browser history entry. The [Router] will only report
@@ -414,8 +426,8 @@
   ///
   ///  * [Router]: see the "URL updates for web applications" section for more
   ///    information about route information reporting.
-  ///  * [neglect]: which forces the [Router] to not report the route
-  ///    information even if location does change.
+  ///  * [neglect]: which forces the [Router] to not create a new history entry
+  ///    even if location does change.
   static void navigate(BuildContext context, VoidCallback callback) {
     final _RouterScope scope = context
       .getElementForInheritedWidgetOfExactType<_RouterScope>()!
@@ -423,24 +435,27 @@
     scope.routerState._setStateWithExplicitReportStatus(_IntentionToReportRouteInformation.must, callback);
   }
 
-  /// Forces the [Router] to run the [callback] without reporting the route
-  /// information back to the engine.
-  ///
-  /// Use this method if you don't want the [Router] to report the new route
-  /// information even if it detects changes as a result of running the
-  /// [callback].
+  /// Forces the [Router] to run the [callback] without creating a new history
+  /// entry in the browser.
   ///
   /// The web application relies on the [Router] to report new route information
   /// in order to create browser history entry. The [Router] will report them
-  /// automatically if it detects the [RouteInformation.location] changes. You
-  /// can use this method if you want to navigate to a new route without
-  /// creating the browser history entry.
+  /// automatically if it detects the [RouteInformation.location] changes.
+  ///
+  /// Creating a new route history entry makes users feel they have visited a
+  /// new page, and the browser back button brings them back to previous history
+  /// entry. Use this method if you don't want the [Router] to create a new
+  /// route information even if it detects changes as a result of running the
+  /// [callback].
+  ///
+  /// Using this method will still update the URL and state in current history
+  /// entry.
   ///
   /// See also:
   ///
   ///  * [Router]: see the "URL updates for web applications" section for more
   ///    information about route information reporting.
-  ///  * [navigate]: which forces the [Router] to report the route information
+  ///  * [navigate]: which forces the [Router] to create a new history entry
   ///    even if location does not change.
   static void neglect(BuildContext context, VoidCallback callback) {
     final _RouterScope scope = context
@@ -497,8 +512,6 @@
 
   bool _routeInformationReportingTaskScheduled = false;
 
-  String? _lastSeenLocation;
-
   void _scheduleRouteInformationReportingTask() {
     if (_routeInformationReportingTaskScheduled || widget.routeInformationProvider == null)
       return;
@@ -512,23 +525,29 @@
     _routeInformationReportingTaskScheduled = false;
 
     if (_routeInformation.value != null) {
-      final RouteInformation routeInformation = _routeInformation.value!;
+      final RouteInformation oldRouteInformation = widget.routeInformationProvider!.value;
+      final RouteInformation currentRouteInformation = _routeInformation.value!;
       switch (_currentIntentionToReport) {
         case _IntentionToReportRouteInformation.none:
           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;
         case _IntentionToReportRouteInformation.maybe:
-          if (_lastSeenLocation != routeInformation.location) {
-            widget.routeInformationProvider!.routerReportsNewRouteInformation(routeInformation);
+          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(routeInformation);
+          widget.routeInformationProvider!.routerReportsNewRouteInformation(currentRouteInformation);
           break;
       }
-      _lastSeenLocation = routeInformation.location;
     }
     _currentIntentionToReport = _IntentionToReportRouteInformation.none;
   }
@@ -621,7 +640,6 @@
   void _processRouteInformation(RouteInformation information, ValueGetter<_DelegateRouteSetter<T>> delegateRouteSetter) {
     _currentRouteInformationParserTransaction = Object();
     _currentRouterDelegateTransaction = Object();
-    _lastSeenLocation = information.location;
     widget.routeInformationParser!
       .parseRouteInformation(information)
       .then<T>(_verifyRouteInformationParserStillCurrent(_currentRouteInformationParserTransaction, widget))
@@ -1301,8 +1319,7 @@
 ///    from the [Router] back to the engine by overriding the
 ///    [routerReportsNewRouteInformation].
 abstract class RouteInformationProvider extends ValueListenable<RouteInformation> {
-  /// A callback called when the [Router] widget detects any navigation event
-  /// due to state changes.
+  /// A callback called when the [Router] widget reports new route information
   ///
   /// The subclasses can override this method to update theirs values or trigger
   /// other side effects. For example, the [PlatformRouteInformationProvider]
@@ -1310,7 +1327,17 @@
   ///
   /// The [routeInformation] is the new route information after the navigation
   /// event.
-  void routerReportsNewRouteInformation(RouteInformation routeInformation) {}
+  ///
+  /// The [isNavigation] denotes whether the new route information is generated
+  /// as a result of a navigation event. This information can be useful in a
+  /// web application, for example, the [PlatformRouteInformationProvider] uses
+  /// this flag to decide whether to create a browser history entry that enables
+  /// browser backward and forward buttons.
+  ///
+  /// For more information on how [Router] determines a navigation event, see
+  /// the "URL updates for web applications" section in the [Router]
+  /// documentation.
+  void routerReportsNewRouteInformation(RouteInformation routeInformation, {bool isNavigation = true}) {}
 }
 
 /// The route information provider that propagates the platform route information changes.
@@ -1333,11 +1360,12 @@
   }) : _value = initialRouteInformation;
 
   @override
-  void routerReportsNewRouteInformation(RouteInformation routeInformation) {
+  void routerReportsNewRouteInformation(RouteInformation routeInformation, {bool isNavigation = true}) {
     SystemNavigator.selectMultiEntryHistory();
     SystemNavigator.routeInformationUpdated(
       location: routeInformation.location!,
       state: routeInformation.state,
+      replace: !isNavigation,
     );
     _value = routeInformation;
   }
diff --git a/packages/flutter/test/services/system_navigator_test.dart b/packages/flutter/test/services/system_navigator_test.dart
index 122c1ca..47bb60e 100644
--- a/packages/flutter/test/services/system_navigator_test.dart
+++ b/packages/flutter/test/services/system_navigator_test.dart
@@ -43,11 +43,15 @@
     ]);
 
     await verify(() => SystemNavigator.routeInformationUpdated(location: 'a'), <Object>[
-      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'location': 'a', 'state': null }),
+      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'location': 'a', 'state': null, 'replace': false }),
     ]);
 
     await verify(() => SystemNavigator.routeInformationUpdated(location: 'a', state: true), <Object>[
-      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'location': 'a', 'state': true }),
+      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'location': 'a', 'state': true, 'replace': false }),
+    ]);
+
+    await verify(() => SystemNavigator.routeInformationUpdated(location: 'a', state: true, replace: true), <Object>[
+      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'location': 'a', 'state': true, 'replace': true }),
     ]);
 
     await verify(() => SystemNavigator.routeUpdated(routeName: 'a', previousRouteName: 'b'), <Object>[
diff --git a/packages/flutter/test/widgets/route_notification_messages_test.dart b/packages/flutter/test/widgets/route_notification_messages_test.dart
index 891189d..a94c145 100644
--- a/packages/flutter/test/widgets/route_notification_messages_test.dart
+++ b/packages/flutter/test/widgets/route_notification_messages_test.dart
@@ -69,6 +69,7 @@
         arguments: <String, dynamic>{
           'location': '/',
           'state': null,
+          'replace': false,
         },
       ),
     ]);
@@ -86,6 +87,7 @@
         arguments: <String, dynamic>{
           'location': '/A',
           'state': null,
+          'replace': false,
         },
       ),
     );
@@ -103,6 +105,7 @@
         arguments: <String, dynamic>{
           'location': '/',
           'state': null,
+          'replace': false,
         },
       ),
     );
@@ -174,6 +177,7 @@
         arguments: <String, dynamic>{
           'location': '/',
           'state': null,
+          'replace': false,
         },
       ),
     ]);
@@ -191,6 +195,7 @@
         arguments: <String, dynamic>{
           'location': '/A',
           'state': null,
+          'replace': false,
         },
       ),
     );
@@ -208,6 +213,7 @@
         arguments: <String, dynamic>{
           'location': '/B',
           'state': null,
+          'replace': false,
         },
       ),
     );
@@ -243,6 +249,7 @@
         arguments: <String, dynamic>{
           'location': '/home',
           'state': null,
+          'replace': false,
         },
       ),
     ]);
@@ -294,6 +301,7 @@
       isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{
         'location': 'update',
         'state': 'state',
+        'replace': false,
       }),
     ]);
   });
diff --git a/packages/flutter/test/widgets/router_test.dart b/packages/flutter/test/widgets/router_test.dart
index dee2ab9..d69973c 100644
--- a/packages/flutter/test/widgets/router_test.dart
+++ b/packages/flutter/test/widgets/router_test.dart
@@ -477,11 +477,14 @@
 
   testWidgets('router does report URL change correctly', (WidgetTester tester) async {
     RouteInformation? reportedRouteInformation;
+    bool? reportedIsNavigation;
     final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
-      onRouterReport: (RouteInformation information) {
+      onRouterReport: (RouteInformation information, bool isNavigation) {
         // Makes sure we only report once after manually cleaning up.
         expect(reportedRouteInformation, isNull);
+        expect(reportedIsNavigation, isNull);
         reportedRouteInformation = information;
+        reportedIsNavigation = isNavigation;
       },
     );
     final SimpleRouterDelegate delegate = SimpleRouterDelegate(
@@ -519,35 +522,44 @@
     expect(find.text('initial'), findsNothing);
     expect(find.text('update'), findsOneWidget);
     expect(reportedRouteInformation!.location, 'update');
+    expect(reportedIsNavigation, isTrue);
 
-    // The router should not report if only state changes.
+    // The router should report as non navigation event if only state changes.
     reportedRouteInformation = null;
+    reportedIsNavigation = null;
     delegate.routeInformation = const RouteInformation(
       location: 'update',
       state: 'another state',
     );
     await tester.pump();
     expect(find.text('update'), findsOneWidget);
-    expect(reportedRouteInformation, isNull);
+    expect(reportedRouteInformation!.location, 'update');
+    expect(reportedRouteInformation!.state, 'another state');
+    expect(reportedIsNavigation, isFalse);
 
     reportedRouteInformation = null;
+    reportedIsNavigation = null;
     bool result = false;
     result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
     expect(result, isTrue);
     await tester.pump();
     expect(find.text('popped'), findsOneWidget);
     expect(reportedRouteInformation!.location, 'popped');
+    expect(reportedIsNavigation, isTrue);
   });
 
   testWidgets('router can be forced to recognize or ignore navigating events', (WidgetTester tester) async {
     RouteInformation? reportedRouteInformation;
+    bool? reportedIsNavigation;
     bool isNavigating = false;
     late RouteInformation nextRouteInformation;
     final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
-      onRouterReport: (RouteInformation information) {
+      onRouterReport: (RouteInformation information, bool isNavigation) {
         // Makes sure we only report once after manually cleaning up.
         expect(reportedRouteInformation, isNull);
+        expect(reportedIsNavigation, isNull);
         reportedRouteInformation = information;
+        reportedIsNavigation = isNavigation;
       },
     );
     provider.value = const RouteInformation(
@@ -592,7 +604,10 @@
     await tester.pump();
     expect(find.text('initial'), findsNothing);
     expect(find.text('update'), findsOneWidget);
-    expect(reportedRouteInformation, isNull);
+    expect(reportedIsNavigation, isFalse);
+    expect(reportedRouteInformation!.location, 'update');
+    reportedIsNavigation = null;
+    reportedRouteInformation = null;
 
     isNavigating = true;
     // This should not trigger any real navigating event because the
@@ -600,13 +615,112 @@
     // report a route information because isNavigating = true.
     await tester.tap(find.byType(ElevatedButton));
     await tester.pump();
+    expect(reportedIsNavigation, isTrue);
     expect(reportedRouteInformation!.location, 'update');
+    reportedIsNavigation = null;
+    reportedRouteInformation = null;
+  });
+
+  testWidgets('router ignore navigating events updates RouteInformationProvider', (WidgetTester tester) async {
+    RouteInformation? updatedRouteInformation;
+    late RouteInformation nextRouteInformation;
+    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
+      onRouterReport: (RouteInformation information, bool isNavigation) {
+        // This should never be a navigation event.
+        expect(isNavigation, false);
+        expect(updatedRouteInformation, isNull);
+        updatedRouteInformation = information;
+      },
+    );
+    provider.value = const RouteInformation(
+      location: 'initial',
+    );
+    final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
+    delegate.builder = (BuildContext context, RouteInformation? information) {
+      return ElevatedButton(
+        child: Text(information!.location!),
+        onPressed: () {
+          Router.neglect(context, () {
+            if (delegate.routeInformation != nextRouteInformation)
+              delegate.routeInformation = nextRouteInformation;
+          });
+        },
+      );
+    };
+    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
+
+    await tester.pumpWidget(buildBoilerPlate(
+      Router<RouteInformation>(
+        backButtonDispatcher: outerDispatcher,
+        routeInformationProvider: provider,
+        routeInformationParser: SimpleRouteInformationParser(),
+        routerDelegate: delegate,
+      ),
+    ));
+    expect(find.text('initial'), findsOneWidget);
+    expect(updatedRouteInformation, isNull);
+
+    nextRouteInformation = const RouteInformation(
+      location: 'update',
+    );
+    await tester.tap(find.byType(ElevatedButton));
+    await tester.pump();
+    expect(find.text('initial'), findsNothing);
+    expect(find.text('update'), findsOneWidget);
+    expect(updatedRouteInformation!.location, 'update');
+  });
+
+  testWidgets('state change without location changes updates RouteInformationProvider', (WidgetTester tester) async {
+    RouteInformation? updatedRouteInformation;
+    late RouteInformation nextRouteInformation;
+    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
+      onRouterReport: (RouteInformation information, bool isNavigation) {
+        // This should never be a navigation event.
+        expect(isNavigation, false);
+        expect(updatedRouteInformation, isNull);
+        updatedRouteInformation = information;
+      },
+    );
+    provider.value = const RouteInformation(
+      location: 'initial',
+      state: 'state1',
+    );
+    final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
+    delegate.builder = (BuildContext context, RouteInformation? information) {
+      return ElevatedButton(
+        child: Text(information!.location!),
+        onPressed: () {
+          delegate.routeInformation = nextRouteInformation;
+        },
+      );
+    };
+    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
+
+    await tester.pumpWidget(buildBoilerPlate(
+      Router<RouteInformation>(
+        backButtonDispatcher: outerDispatcher,
+        routeInformationProvider: provider,
+        routeInformationParser: SimpleRouteInformationParser(),
+        routerDelegate: delegate,
+      ),
+    ));
+    expect(find.text('initial'), findsOneWidget);
+    expect(updatedRouteInformation, isNull);
+
+    nextRouteInformation = const RouteInformation(
+      location: 'initial',
+      state: 'state2',
+    );
+    await tester.tap(find.byType(ElevatedButton));
+    await tester.pump();
+    expect(updatedRouteInformation!.location, 'initial');
+    expect(updatedRouteInformation!.state, 'state2');
   });
 
   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) {
+      onRouterReport: (RouteInformation information, bool isNavigation) {
         reportedRouteInformation = information;
       },
     );
@@ -691,6 +805,38 @@
     expect(find.text('newTestRouteName'), findsOneWidget);
   });
 
+  testWidgets('PlatformRouteInformationProvider updates route information', (WidgetTester tester) async {
+    final List<MethodCall> log = <MethodCall>[];
+    TestDefaultBinaryMessengerBinding
+      .instance!
+      .defaultBinaryMessenger
+      .setMockMethodCallHandler(
+        SystemChannels.navigation,
+        (MethodCall methodCall) async {
+          log.add(methodCall);
+        }
+      );
+    final RouteInformationProvider provider = PlatformRouteInformationProvider(
+      initialRouteInformation: const RouteInformation(
+        location: 'initial',
+      ),
+    );
+
+    log.clear();
+    provider.routerReportsNewRouteInformation(const RouteInformation(location: 'a', state: true));
+    expect(log, <Object>[
+      isMethodCall('selectMultiEntryHistory', arguments: null),
+      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'location': 'a', 'state': true, 'replace': false }),
+    ]);
+
+    log.clear();
+    provider.routerReportsNewRouteInformation(const RouteInformation(location: 'b', state: false), isNavigation: false);
+    expect(log, <Object>[
+      isMethodCall('selectMultiEntryHistory', arguments: null),
+      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'location': 'b', 'state': false, 'replace': true }),
+    ]);
+  });
+
   testWidgets('RootBackButtonDispatcher works', (WidgetTester tester) async {
     final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
     final RouteInformationProvider provider = PlatformRouteInformationProvider(
@@ -1093,7 +1239,7 @@
   testWidgets('Router reports location if it is different from location given by OS', (WidgetTester tester) async {
     final List<RouteInformation> reportedRouteInformation = <RouteInformation>[];
     final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
-      onRouterReport: reportedRouteInformation.add,
+      onRouterReport: (RouteInformation info, bool isNavigation) => reportedRouteInformation.add(info),
     )..value = const RouteInformation(location: '/home');
 
     await tester.pumpWidget(buildBoilerPlate(
@@ -1131,7 +1277,7 @@
 typedef SimpleRouterDelegateBuilder = Widget Function(BuildContext, RouteInformation?);
 typedef SimpleRouterDelegatePopRoute = Future<bool> Function();
 typedef SimpleNavigatorRouterDelegatePopPage<T> = bool Function(Route<T> route, T result);
-typedef RouterReportRouterInformation = void Function(RouteInformation);
+typedef RouterReportRouterInformation = void Function(RouteInformation, bool);
 
 class SimpleRouteInformationParser extends RouteInformationParser<RouteInformation> {
   SimpleRouteInformationParser();
@@ -1252,8 +1398,9 @@
   }
 
   @override
-  void routerReportsNewRouteInformation(RouteInformation routeInformation) {
-    onRouterReport?.call(routeInformation);
+  void routerReportsNewRouteInformation(RouteInformation routeInformation, {bool isNavigation = true}) {
+    _value = routeInformation;
+    onRouterReport?.call(routeInformation, isNavigation);
   }
 }