blob: 1af969c5376551fe64f8eb0387b75b5ca8425b2c [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'builder.dart';
import 'configuration.dart';
import 'match.dart';
import 'matching.dart';
import 'typedefs.dart';
/// GoRouter implementation of [RouterDelegate].
class GoRouterDelegate extends RouterDelegate<RouteMatchList>
with PopNavigatorRouterDelegateMixin<RouteMatchList>, ChangeNotifier {
/// Constructor for GoRouter's implementation of the RouterDelegate base
/// class.
GoRouterDelegate({
required RouteConfiguration configuration,
required GoRouterBuilderWithNav builderWithNav,
required GoRouterPageBuilder? errorPageBuilder,
required GoRouterWidgetBuilder? errorBuilder,
required List<NavigatorObserver> observers,
required this.routerNeglect,
String? restorationScopeId,
}) : builder = RouteBuilder(
configuration: configuration,
builderWithNav: builderWithNav,
errorPageBuilder: errorPageBuilder,
errorBuilder: errorBuilder,
restorationScopeId: restorationScopeId,
observers: observers,
);
/// Builds the top-level Navigator given a configuration and location.
@visibleForTesting
final RouteBuilder builder;
/// Set to true to disable creating history entries on the web.
final bool routerNeglect;
final GlobalKey<NavigatorState> _key = GlobalKey<NavigatorState>();
RouteMatchList _matches = RouteMatchList.empty();
/// Push the given location onto the page stack
void push(RouteMatch match) {
_matches.push(match);
notifyListeners();
}
/// Returns `true` if there is more than 1 page on the stack.
bool canPop() {
return _matches.canPop();
}
/// Pop the top page off the GoRouter's page stack.
void pop() {
_matches.pop();
notifyListeners();
}
/// Replaces the top-most page of the page stack with the given one.
///
/// See also:
/// * [push] which pushes the given location onto the page stack.
void replace(RouteMatch match) {
_matches.matches.last = match;
notifyListeners();
}
/// For internal use; visible for testing only.
@visibleForTesting
RouteMatchList get matches => _matches;
/// For use by the Router architecture as part of the RouterDelegate.
@override
GlobalKey<NavigatorState> get navigatorKey => _key;
/// For use by the Router architecture as part of the RouterDelegate.
@override
RouteMatchList get currentConfiguration => _matches;
/// For use by the Router architecture as part of the RouterDelegate.
@override
Widget build(BuildContext context) => builder.build(
context,
_matches,
pop,
navigatorKey,
routerNeglect,
);
/// For use by the Router architecture as part of the RouterDelegate.
@override
Future<void> setNewRoutePath(RouteMatchList configuration) {
_matches = configuration;
// Use [SynchronousFuture] so that the initial url is processed
// synchronously and remove unwanted initial animations on deep-linking
return SynchronousFuture<void>(null);
}
}