Commit f9ea1ce8 authored by Hixie's avatar Hixie

NavigatorTransaction

To make it easier to avoid pushing twice in one frame, provide a
transaction mechanism for the navigator.
parent 97cca4d4
...@@ -60,7 +60,7 @@ class FeedFragmentState extends State<FeedFragment> { ...@@ -60,7 +60,7 @@ class FeedFragmentState extends State<FeedFragment> {
setState(() { setState(() {
_fitnessMode = value; _fitnessMode = value;
}); });
Navigator.of(context).pop(); Navigator.pop(context);
} }
void _showDrawer() { void _showDrawer() {
...@@ -91,8 +91,7 @@ class FeedFragmentState extends State<FeedFragment> { ...@@ -91,8 +91,7 @@ class FeedFragmentState extends State<FeedFragment> {
} }
void _handleShowSettings() { void _handleShowSettings() {
Navigator.of(context)..pop() Navigator.popAndPushNamed(context, '/settings');
..pushNamed('/settings');
} }
// TODO(jackson): We should be localizing // TODO(jackson): We should be localizing
...@@ -190,7 +189,7 @@ class FeedFragmentState extends State<FeedFragment> { ...@@ -190,7 +189,7 @@ class FeedFragmentState extends State<FeedFragment> {
void _handleActionButtonPressed() { void _handleActionButtonPressed() {
showDialog(context: context, child: new AddItemDialog()).then((routeName) { showDialog(context: context, child: new AddItemDialog()).then((routeName) {
if (routeName != null) if (routeName != null)
Navigator.of(context).pushNamed(routeName); Navigator.pushNamed(context, routeName);
}); });
} }
...@@ -249,13 +248,13 @@ class AddItemDialogState extends State<AddItemDialog> { ...@@ -249,13 +248,13 @@ class AddItemDialogState extends State<AddItemDialog> {
new FlatButton( new FlatButton(
child: new Text('CANCEL'), child: new Text('CANCEL'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.pop(context);
} }
), ),
new FlatButton( new FlatButton(
child: new Text('ADD'), child: new Text('ADD'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(_addItemRoute); Navigator.pop(context, _addItemRoute);
} }
), ),
] ]
......
...@@ -55,14 +55,15 @@ class MealFragmentState extends State<MealFragment> { ...@@ -55,14 +55,15 @@ class MealFragmentState extends State<MealFragment> {
void _handleSave() { void _handleSave() {
config.onCreated(new Meal(when: new DateTime.now(), description: _description)); config.onCreated(new Meal(when: new DateTime.now(), description: _description));
Navigator.of(context).pop(); Navigator.pop(context);
} }
Widget buildToolBar() { Widget buildToolBar() {
return new ToolBar( return new ToolBar(
left: new IconButton( left: new IconButton(
icon: "navigation/close", icon: "navigation/close",
onPressed: Navigator.of(context).pop), onPressed: () => Navigator.pop(context)
),
center: new Text('New Meal'), center: new Text('New Meal'),
right: <Widget>[ right: <Widget>[
// TODO(abarth): Should this be a FlatButton? // TODO(abarth): Should this be a FlatButton?
......
...@@ -77,14 +77,15 @@ class MeasurementFragmentState extends State<MeasurementFragment> { ...@@ -77,14 +77,15 @@ class MeasurementFragmentState extends State<MeasurementFragment> {
)); ));
} }
config.onCreated(new Measurement(when: _when, weight: parsedWeight)); config.onCreated(new Measurement(when: _when, weight: parsedWeight));
Navigator.of(context).pop(); Navigator.pop(context);
} }
Widget buildToolBar() { Widget buildToolBar() {
return new ToolBar( return new ToolBar(
left: new IconButton( left: new IconButton(
icon: "navigation/close", icon: "navigation/close",
onPressed: Navigator.of(context).pop), onPressed: () => Navigator.pop(context)
),
center: new Text('New Measurement'), center: new Text('New Measurement'),
right: <Widget>[ right: <Widget>[
// TODO(abarth): Should this be a FlatButton? // TODO(abarth): Should this be a FlatButton?
......
...@@ -28,7 +28,7 @@ class SettingsFragmentState extends State<SettingsFragment> { ...@@ -28,7 +28,7 @@ class SettingsFragmentState extends State<SettingsFragment> {
return new ToolBar( return new ToolBar(
left: new IconButton( left: new IconButton(
icon: "navigation/arrow_back", icon: "navigation/arrow_back",
onPressed: () => Navigator.of(context).pop() onPressed: () => Navigator.pop(context)
), ),
center: new Text('Settings') center: new Text('Settings')
); );
...@@ -47,7 +47,7 @@ class SettingsFragmentState extends State<SettingsFragment> { ...@@ -47,7 +47,7 @@ class SettingsFragmentState extends State<SettingsFragment> {
void _handleGoalWeightChanged(String goalWeight) { void _handleGoalWeightChanged(String goalWeight) {
// TODO(jackson): Looking for null characters to detect enter key is a hack // TODO(jackson): Looking for null characters to detect enter key is a hack
if (goalWeight.endsWith("\u{0}")) { if (goalWeight.endsWith("\u{0}")) {
Navigator.of(context).pop(double.parse(goalWeight.replaceAll("\u{0}", ""))); Navigator.pop(context, double.parse(goalWeight.replaceAll("\u{0}", "")));
} else { } else {
setState(() { setState(() {
try { try {
...@@ -74,13 +74,13 @@ class SettingsFragmentState extends State<SettingsFragment> { ...@@ -74,13 +74,13 @@ class SettingsFragmentState extends State<SettingsFragment> {
new FlatButton( new FlatButton(
child: new Text('CANCEL'), child: new Text('CANCEL'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.pop(context);
} }
), ),
new FlatButton( new FlatButton(
child: new Text('SAVE'), child: new Text('SAVE'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(_goalWeight); Navigator.pop(context, _goalWeight);
} }
), ),
] ]
......
...@@ -21,7 +21,7 @@ class GalleryPage extends StatelessComponent { ...@@ -21,7 +21,7 @@ class GalleryPage extends StatelessComponent {
for (WidgetDemo demo in demos) { for (WidgetDemo demo in demos) {
items.add(new DrawerItem( items.add(new DrawerItem(
onPressed: () { onPressed: () {
Navigator.of(context).pushNamed(demo.routeName); Navigator.pushNamed(context, demo.routeName);
}, },
child: new Text(demo.title) child: new Text(demo.title)
)); ));
......
...@@ -41,7 +41,7 @@ class StockHomeState extends State<StockHome> { ...@@ -41,7 +41,7 @@ class StockHomeState extends State<StockHome> {
} }
void _handleSearchEnd() { void _handleSearchEnd() {
Navigator.of(context).pop(); Navigator.pop(context);
} }
void _handleSearchQueryChanged(String query) { void _handleSearchQueryChanged(String query) {
...@@ -92,13 +92,13 @@ class StockHomeState extends State<StockHome> { ...@@ -92,13 +92,13 @@ class StockHomeState extends State<StockHome> {
new FlatButton( new FlatButton(
child: new Text('USE IT'), child: new Text('USE IT'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(false); Navigator.pop(context, false);
} }
), ),
new FlatButton( new FlatButton(
child: new Text('OH WELL'), child: new Text('OH WELL'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(false); Navigator.pop(context, false);
} }
), ),
] ]
...@@ -142,8 +142,7 @@ class StockHomeState extends State<StockHome> { ...@@ -142,8 +142,7 @@ class StockHomeState extends State<StockHome> {
} }
void _handleShowSettings() { void _handleShowSettings() {
Navigator.of(context)..pop() Navigator.popAndPushNamed(context, '/settings');
..pushNamed('/settings');
} }
Widget buildToolBar() { Widget buildToolBar() {
...@@ -207,7 +206,7 @@ class StockHomeState extends State<StockHome> { ...@@ -207,7 +206,7 @@ class StockHomeState extends State<StockHome> {
onOpen: (Stock stock, Key arrowKey) { onOpen: (Stock stock, Key arrowKey) {
Set<Key> mostValuableKeys = new Set<Key>(); Set<Key> mostValuableKeys = new Set<Key>();
mostValuableKeys.add(arrowKey); mostValuableKeys.add(arrowKey);
Navigator.of(context).pushNamed('/stock/${stock.symbol}', mostValuableKeys: mostValuableKeys); Navigator.pushNamed(context, '/stock/${stock.symbol}', mostValuableKeys: mostValuableKeys);
}, },
onShow: (Stock stock, Key arrowKey) { onShow: (Stock stock, Key arrowKey) {
scaffoldKey.currentState.showBottomSheet((BuildContext context) => new StockSymbolBottomSheet(stock: stock)); scaffoldKey.currentState.showBottomSheet((BuildContext context) => new StockSymbolBottomSheet(stock: stock));
......
...@@ -23,10 +23,9 @@ Future showStockMenu({BuildContext context, bool autorefresh, ValueChanged<bool> ...@@ -23,10 +23,9 @@ Future showStockMenu({BuildContext context, bool autorefresh, ValueChanged<bool>
new Checkbox( new Checkbox(
value: autorefresh, value: autorefresh,
onChanged: (bool value) { onChanged: (bool value) {
Navigator.of(context).setState(() { // TODO(ianh): https://github.com/flutter/flutter/issues/187
autorefresh = value; autorefresh = value;
}); Navigator.pop(context, _MenuItems.autorefreshCheckbox);
Navigator.of(context).pop(_MenuItems.autorefreshCheckbox);
} }
) )
] ]
...@@ -43,9 +42,8 @@ Future showStockMenu({BuildContext context, bool autorefresh, ValueChanged<bool> ...@@ -43,9 +42,8 @@ Future showStockMenu({BuildContext context, bool autorefresh, ValueChanged<bool>
] ]
)) { )) {
case _MenuItems.autorefresh: case _MenuItems.autorefresh:
Navigator.of(context).setState(() { // TODO(ianh): https://github.com/flutter/flutter/issues/187
autorefresh = !autorefresh; autorefresh = !autorefresh;
});
continue autorefreshNotify; continue autorefreshNotify;
autorefreshNotify: autorefreshNotify:
case _MenuItems.autorefreshCheckbox: case _MenuItems.autorefreshCheckbox:
...@@ -75,7 +73,7 @@ Future showStockMenu({BuildContext context, bool autorefresh, ValueChanged<bool> ...@@ -75,7 +73,7 @@ Future showStockMenu({BuildContext context, bool autorefresh, ValueChanged<bool>
new FlatButton( new FlatButton(
child: new Text('OH WELL'), child: new Text('OH WELL'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(false); Navigator.pop(context, false);
} }
), ),
] ]
......
...@@ -44,13 +44,13 @@ class StockSettingsState extends State<StockSettings> { ...@@ -44,13 +44,13 @@ class StockSettingsState extends State<StockSettings> {
new FlatButton( new FlatButton(
child: new Text('NO THANKS'), child: new Text('NO THANKS'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(false); Navigator.pop(context, false);
} }
), ),
new FlatButton( new FlatButton(
child: new Text('AGREE'), child: new Text('AGREE'),
onPressed: () { onPressed: () {
Navigator.of(context).pop(true); Navigator.pop(context, true);
} }
), ),
] ]
...@@ -72,7 +72,7 @@ class StockSettingsState extends State<StockSettings> { ...@@ -72,7 +72,7 @@ class StockSettingsState extends State<StockSettings> {
return new ToolBar( return new ToolBar(
left: new IconButton( left: new IconButton(
icon: 'navigation/arrow_back', icon: 'navigation/arrow_back',
onPressed: () => Navigator.of(context).pop() onPressed: () => Navigator.pop(context)
), ),
center: new Text('Settings') center: new Text('Settings')
); );
......
...@@ -58,7 +58,7 @@ class StockSymbolPage extends StatelessComponent { ...@@ -58,7 +58,7 @@ class StockSymbolPage extends StatelessComponent {
left: new IconButton( left: new IconButton(
icon: 'navigation/arrow_back', icon: 'navigation/arrow_back',
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.pop(context);
} }
), ),
center: new Text(stock.name) center: new Text(stock.name)
......
...@@ -15,11 +15,11 @@ class Home extends StatelessComponent { ...@@ -15,11 +15,11 @@ class Home extends StatelessComponent {
), ),
new RaisedButton( new RaisedButton(
child: new Text('GO SHOPPING'), child: new Text('GO SHOPPING'),
onPressed: () => Navigator.of(context).pushNamed('/shopping') onPressed: () => Navigator.pushNamed(context, '/shopping')
), ),
new RaisedButton( new RaisedButton(
child: new Text('START ADVENTURE'), child: new Text('START ADVENTURE'),
onPressed: () => Navigator.of(context).pushNamed('/adventure') onPressed: () => Navigator.pushNamed(context, '/adventure')
) )
], ],
padding: const EdgeDims.all(30.0) padding: const EdgeDims.all(30.0)
...@@ -41,11 +41,11 @@ class Shopping extends StatelessComponent { ...@@ -41,11 +41,11 @@ class Shopping extends StatelessComponent {
), ),
new RaisedButton( new RaisedButton(
child: new Text('RETURN HOME'), child: new Text('RETURN HOME'),
onPressed: () => Navigator.of(context).pop() onPressed: () => Navigator.pop(context)
), ),
new RaisedButton( new RaisedButton(
child: new Text('GO TO DUNGEON'), child: new Text('GO TO DUNGEON'),
onPressed: () => Navigator.of(context).pushNamed('/adventure') onPressed: () => Navigator.pushNamed(context, '/adventure')
) )
], ],
padding: const EdgeDims.all(30.0) padding: const EdgeDims.all(30.0)
...@@ -67,7 +67,7 @@ class Adventure extends StatelessComponent { ...@@ -67,7 +67,7 @@ class Adventure extends StatelessComponent {
), ),
new RaisedButton( new RaisedButton(
child: new Text('RUN!!!'), child: new Text('RUN!!!'),
onPressed: () => Navigator.of(context).pop() onPressed: () => Navigator.pop(context)
) )
], ],
padding: const EdgeDims.all(30.0) padding: const EdgeDims.all(30.0)
......
...@@ -119,7 +119,7 @@ class _ModalBottomSheetState extends State<_ModalBottomSheet> { ...@@ -119,7 +119,7 @@ class _ModalBottomSheetState extends State<_ModalBottomSheet> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new GestureDetector( return new GestureDetector(
onTap: () { Navigator.of(context).pop(); }, onTap: () => Navigator.pop(context),
child: new BuilderTransition( child: new BuilderTransition(
performance: config.route.performance, performance: config.route.performance,
variables: <AnimatedValue<double>>[_layout.childTop], variables: <AnimatedValue<double>>[_layout.childTop],
...@@ -130,7 +130,7 @@ class _ModalBottomSheetState extends State<_ModalBottomSheet> { ...@@ -130,7 +130,7 @@ class _ModalBottomSheetState extends State<_ModalBottomSheet> {
token: _layout.childTop.value, token: _layout.childTop.value,
child: new BottomSheet( child: new BottomSheet(
performance: config.route.performance, performance: config.route.performance,
onClosing: () { Navigator.of(context).pop(); }, onClosing: () => Navigator.pop(context),
childHeight: _layout.childTop.end, childHeight: _layout.childTop.end,
builder: config.route.builder builder: config.route.builder
) )
...@@ -167,7 +167,7 @@ Future showModalBottomSheet({ BuildContext context, WidgetBuilder builder }) { ...@@ -167,7 +167,7 @@ Future showModalBottomSheet({ BuildContext context, WidgetBuilder builder }) {
assert(context != null); assert(context != null);
assert(builder != null); assert(builder != null);
final Completer completer = new Completer(); final Completer completer = new Completer();
Navigator.of(context).push(new _ModalBottomSheetRoute( Navigator.push(context, new _ModalBottomSheetRoute(
completer: completer, completer: completer,
builder: builder builder: builder
)); ));
......
...@@ -40,11 +40,11 @@ class _DatePickerDialogState extends State<_DatePickerDialog> { ...@@ -40,11 +40,11 @@ class _DatePickerDialogState extends State<_DatePickerDialog> {
} }
void _handleCancel() { void _handleCancel() {
Navigator.of(context).pop(); Navigator.pop(context);
} }
void _handleOk() { void _handleOk() {
Navigator.of(context).pop(_selectedDate); Navigator.pop(context, _selectedDate);
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
......
...@@ -140,6 +140,6 @@ class _DialogRoute<T> extends PopupRoute<T> { ...@@ -140,6 +140,6 @@ class _DialogRoute<T> extends PopupRoute<T> {
Future showDialog({ BuildContext context, Widget child }) { Future showDialog({ BuildContext context, Widget child }) {
Completer completer = new Completer(); Completer completer = new Completer();
Navigator.of(context).push(new _DialogRoute(completer: completer, child: child)); Navigator.push(context, new _DialogRoute(completer: completer, child: child));
return completer.future; return completer.future;
} }
...@@ -71,7 +71,7 @@ class _DrawerRoute extends OverlayRoute { ...@@ -71,7 +71,7 @@ class _DrawerRoute extends OverlayRoute {
_state = _DrawerState.closed; _state = _DrawerState.closed;
switch (previousState) { switch (previousState) {
case _DrawerState.showing: case _DrawerState.showing:
Navigator.of(context).pop(); Navigator.pop(context);
break; break;
case _DrawerState.popped: case _DrawerState.popped:
finished(); finished();
...@@ -220,5 +220,5 @@ class _DrawerControllerState extends State<_DrawerController> { ...@@ -220,5 +220,5 @@ class _DrawerControllerState extends State<_DrawerController> {
} }
void showDrawer({ BuildContext context, Widget child, int elevation: 16 }) { void showDrawer({ BuildContext context, Widget child, int elevation: 16 }) {
Navigator.of(context).push(new _DrawerRoute(child: child, elevation: elevation)); Navigator.push(context, new _DrawerRoute(child: child, elevation: elevation));
} }
...@@ -93,9 +93,7 @@ class _DropDownMenu<T> extends StatusTransitionComponent { ...@@ -93,9 +93,7 @@ class _DropDownMenu<T> extends StatusTransitionComponent {
padding: _kMenuHorizontalPadding, padding: _kMenuHorizontalPadding,
child: route.items[itemIndex] child: route.items[itemIndex]
), ),
onTap: () { onTap: () => Navigator.pop(context, route.items[itemIndex].value)
Navigator.of(context).pop(route.items[itemIndex].value);
}
) )
)); ));
} }
...@@ -117,7 +115,7 @@ class _DropDownMenu<T> extends StatusTransitionComponent { ...@@ -117,7 +115,7 @@ class _DropDownMenu<T> extends StatusTransitionComponent {
reverseCurve: const Interval(0.0, 0.001) reverseCurve: const Interval(0.0, 0.001)
); );
final RenderBox renderBox = Navigator.of(context).context.findRenderObject(); final RenderBox renderBox = route.navigator.context.findRenderObject();
final Size navigatorSize = renderBox.size; final Size navigatorSize = renderBox.size;
final RelativeRect menuRect = new RelativeRect.fromSize(route.rect, navigatorSize); final RelativeRect menuRect = new RelativeRect.fromSize(route.rect, navigatorSize);
...@@ -216,7 +214,7 @@ class DropDownButton<T> extends StatelessComponent { ...@@ -216,7 +214,7 @@ class DropDownButton<T> extends StatelessComponent {
final RenderBox renderBox = indexedStackKey.currentContext.findRenderObject(); final RenderBox renderBox = indexedStackKey.currentContext.findRenderObject();
final Rect rect = renderBox.localToGlobal(Point.origin) & renderBox.size; final Rect rect = renderBox.localToGlobal(Point.origin) & renderBox.size;
final Completer completer = new Completer<T>(); final Completer completer = new Completer<T>();
Navigator.of(context).push(new _DropDownRoute<T>( Navigator.push(context, new _DropDownRoute<T>(
completer: completer, completer: completer,
items: items, items: items,
selectedIndex: selectedIndex, selectedIndex: selectedIndex,
......
...@@ -81,8 +81,10 @@ class _MaterialAppState extends State<MaterialApp> implements BindingObserver { ...@@ -81,8 +81,10 @@ class _MaterialAppState extends State<MaterialApp> implements BindingObserver {
assert(mounted); assert(mounted);
NavigatorState navigator = _navigator.currentState; NavigatorState navigator = _navigator.currentState;
assert(navigator != null); assert(navigator != null);
if (!navigator.pop()) navigator.openTransaction((NavigatorTransaction transaction) {
if (!transaction.pop())
activity.finishCurrentActivity(); activity.finishCurrentActivity();
});
return true; return true;
} }
......
...@@ -38,7 +38,7 @@ class _PopupMenu<T> extends StatelessComponent { ...@@ -38,7 +38,7 @@ class _PopupMenu<T> extends StatelessComponent {
performance: route.performance, performance: route.performance,
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(start, end)), opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(start, end)),
child: new InkWell( child: new InkWell(
onTap: () { Navigator.of(context).pop(route.items[i].value); }, onTap: () => Navigator.pop(context, route.items[i].value),
child: route.items[i] child: route.items[i]
)) ))
); );
...@@ -114,7 +114,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> { ...@@ -114,7 +114,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
Future showMenu({ BuildContext context, ModalPosition position, List<PopupMenuItem> items, int elevation: 8 }) { Future showMenu({ BuildContext context, ModalPosition position, List<PopupMenuItem> items, int elevation: 8 }) {
Completer completer = new Completer(); Completer completer = new Completer();
Navigator.of(context).push(new _PopupMenuRoute( Navigator.push(context, new _PopupMenuRoute(
completer: completer, completer: completer,
position: position, position: position,
items: items, items: items,
......
...@@ -36,11 +36,11 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { ...@@ -36,11 +36,11 @@ class _TimePickerDialogState extends State<_TimePickerDialog> {
} }
void _handleCancel() { void _handleCancel() {
Navigator.of(context).pop(); Navigator.pop(context);
} }
void _handleOk() { void _handleOk() {
Navigator.of(context).pop(_selectedTime); Navigator.pop(context, _selectedTime);
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
......
...@@ -11,7 +11,6 @@ import 'package:flutter/services.dart'; ...@@ -11,7 +11,6 @@ import 'package:flutter/services.dart';
import 'basic.dart'; import 'basic.dart';
import 'binding.dart'; import 'binding.dart';
import 'framework.dart'; import 'framework.dart';
import 'navigator.dart';
import 'overlay.dart'; import 'overlay.dart';
typedef bool DragTargetWillAccept<T>(T data); typedef bool DragTargetWillAccept<T>(T data);
...@@ -165,7 +164,7 @@ class _DraggableState<T> extends State<DraggableBase<T>> implements GestureArena ...@@ -165,7 +164,7 @@ class _DraggableState<T> extends State<DraggableBase<T>> implements GestureArena
new _DragAvatar<T>( new _DragAvatar<T>(
pointer: pointer, pointer: pointer,
router: router, router: router,
overlay: Navigator.of(context).overlay, overlay: Overlay.of(context),
data: config.data, data: config.data,
initialPosition: position, initialPosition: position,
dragStartPoint: dragStartPoint, dragStartPoint: dragStartPoint,
......
...@@ -23,7 +23,7 @@ class ModalBarrier extends StatelessComponent { ...@@ -23,7 +23,7 @@ class ModalBarrier extends StatelessComponent {
return new Listener( return new Listener(
onPointerDown: (_) { onPointerDown: (_) {
if (dismissable) if (dismissable)
Navigator.of(context).pop(); Navigator.pop(context);
}, },
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: new ConstrainedBox( child: new ConstrainedBox(
......
...@@ -14,13 +14,13 @@ abstract class Route<T> { ...@@ -14,13 +14,13 @@ abstract class Route<T> {
/// Called when the route is inserted into the navigator. /// Called when the route is inserted into the navigator.
/// ///
/// Use this to populate overlayEntries and add them to the overlay. /// Use this to populate overlayEntries and add them to the overlay
/// (The reason the Route is responsible for doing this, rather than the /// (accessible as navigator.overlay). (The reason the Route is responsible
/// Navigator, is that the Route will be responsible for _removing_ the /// for doing this, rather than the Navigator, is that the Route will be
/// entries and this way it's symmetric. /// responsible for _removing_ the entries and this way it's symmetric.)
/// ///
/// The overlay argument will be null if this is the first route inserted. /// The overlay argument will be null if this is the first route inserted.
void install(OverlayState overlay, OverlayEntry insertionPoint) { } void install(OverlayEntry insertionPoint) { }
/// Called after install() when the route is pushed onto the navigator. /// Called after install() when the route is pushed onto the navigator.
void didPush() { } void didPush() { }
...@@ -81,6 +81,7 @@ class NamedRouteSettings { ...@@ -81,6 +81,7 @@ class NamedRouteSettings {
} }
typedef Route RouteFactory(NamedRouteSettings settings); typedef Route RouteFactory(NamedRouteSettings settings);
typedef void NavigatorTransactionCallback(NavigatorTransaction transaction);
class NavigatorObserver { class NavigatorObserver {
/// The navigator that the observer is observing, if any. /// The navigator that the observer is observing, if any.
...@@ -108,7 +109,37 @@ class Navigator extends StatefulComponent { ...@@ -108,7 +109,37 @@ class Navigator extends StatefulComponent {
static const String defaultRouteName = '/'; static const String defaultRouteName = '/';
static NavigatorState of(BuildContext context) => context.ancestorStateOfType(NavigatorState); static void pushNamed(BuildContext context, String routeName, { Set<Key> mostValuableKeys }) {
openTransaction(context, (NavigatorTransaction transaction) {
transaction.pushNamed(routeName, mostValuableKeys: mostValuableKeys);
});
}
static void push(BuildContext context, Route route, { Set<Key> mostValuableKeys }) {
openTransaction(context, (NavigatorTransaction transaction) {
transaction.push(route, mostValuableKeys: mostValuableKeys);
});
}
static bool pop(BuildContext context, [ dynamic result ]) {
bool returnValue;
openTransaction(context, (NavigatorTransaction transaction) {
returnValue = transaction.pop(result);
});
return returnValue;
}
static void popAndPushNamed(BuildContext context, String routeName, { Set<Key> mostValuableKeys }) {
openTransaction(context, (NavigatorTransaction transaction) {
transaction.pop();
transaction.pushNamed(routeName, mostValuableKeys: mostValuableKeys);
});
}
static void openTransaction(BuildContext context, NavigatorTransactionCallback callback) {
NavigatorState navigator = context.ancestorStateOfType(NavigatorState);
navigator.openTransaction(callback);
}
NavigatorState createState() => new NavigatorState(); NavigatorState createState() => new NavigatorState();
} }
...@@ -121,7 +152,7 @@ class NavigatorState extends State<Navigator> { ...@@ -121,7 +152,7 @@ class NavigatorState extends State<Navigator> {
super.initState(); super.initState();
assert(config.observer == null || config.observer.navigator == null); assert(config.observer == null || config.observer.navigator == null);
config.observer?._navigator = this; config.observer?._navigator = this;
push(config.onGenerateRoute(new NamedRouteSettings( _push(config.onGenerateRoute(new NamedRouteSettings(
name: config.initialRoute ?? Navigator.defaultRouteName name: config.initialRoute ?? Navigator.defaultRouteName
))); )));
} }
...@@ -146,9 +177,10 @@ class NavigatorState extends State<Navigator> { ...@@ -146,9 +177,10 @@ class NavigatorState extends State<Navigator> {
assert(() { _debugLocked = false; return true; }); assert(() { _debugLocked = false; return true; });
} }
// Used by Routes and NavigatorObservers
OverlayState get overlay => _overlayKey.currentState; OverlayState get overlay => _overlayKey.currentState;
OverlayEntry get _currentOverlay { OverlayEntry get _currentOverlayEntry {
for (Route route in _history.reversed) { for (Route route in _history.reversed) {
if (route.overlayEntries.isNotEmpty) if (route.overlayEntries.isNotEmpty)
return route.overlayEntries.last; return route.overlayEntries.last;
...@@ -158,17 +190,17 @@ class NavigatorState extends State<Navigator> { ...@@ -158,17 +190,17 @@ class NavigatorState extends State<Navigator> {
bool _debugLocked = false; // used to prevent re-entrant calls to push, pop, and friends bool _debugLocked = false; // used to prevent re-entrant calls to push, pop, and friends
void pushNamed(String name, { Set<Key> mostValuableKeys }) { void _pushNamed(String name, { Set<Key> mostValuableKeys }) {
assert(!_debugLocked); assert(!_debugLocked);
assert(name != null); assert(name != null);
NamedRouteSettings settings = new NamedRouteSettings( NamedRouteSettings settings = new NamedRouteSettings(
name: name, name: name,
mostValuableKeys: mostValuableKeys mostValuableKeys: mostValuableKeys
); );
push(config.onGenerateRoute(settings) ?? config.onUnknownRoute(settings)); _push(config.onGenerateRoute(settings) ?? config.onUnknownRoute(settings));
} }
void push(Route route, { Set<Key> mostValuableKeys }) { void _push(Route route, { Set<Key> mostValuableKeys }) {
assert(!_debugLocked); assert(!_debugLocked);
assert(() { _debugLocked = true; return true; }); assert(() { _debugLocked = true; return true; });
assert(route != null); assert(route != null);
...@@ -176,7 +208,7 @@ class NavigatorState extends State<Navigator> { ...@@ -176,7 +208,7 @@ class NavigatorState extends State<Navigator> {
setState(() { setState(() {
Route oldRoute = _history.isNotEmpty ? _history.last : null; Route oldRoute = _history.isNotEmpty ? _history.last : null;
route._navigator = this; route._navigator = this;
route.install(overlay, _currentOverlay); route.install(_currentOverlayEntry);
_history.add(route); _history.add(route);
route.didPush(); route.didPush();
if (oldRoute != null) if (oldRoute != null)
...@@ -186,18 +218,7 @@ class NavigatorState extends State<Navigator> { ...@@ -186,18 +218,7 @@ class NavigatorState extends State<Navigator> {
assert(() { _debugLocked = false; return true; }); assert(() { _debugLocked = false; return true; });
} }
/// Replaces one given route with another, but does not call didPush/didPop. void _replace({ Route oldRoute, Route newRoute }) {
/// Instead, this calls install() on the new route, then didReplace() on the
/// new route passing the old route, then dispose() on the old route.
///
/// The old route must have overlays, otherwise we won't know where to insert
/// the overlays of the new route. The old route must not be currently visible
/// (i.e. a later route have overlays that are currently opaque), otherwise
/// the replacement would have a jarring effect.
///
/// It is safe to call this redundantly (replacing a route with itself). Such
/// calls are ignored.
void replace({ Route oldRoute, Route newRoute }) {
assert(!_debugLocked); assert(!_debugLocked);
assert(oldRoute != null); assert(oldRoute != null);
assert(newRoute != null); assert(newRoute != null);
...@@ -213,7 +234,7 @@ class NavigatorState extends State<Navigator> { ...@@ -213,7 +234,7 @@ class NavigatorState extends State<Navigator> {
int index = _history.indexOf(oldRoute); int index = _history.indexOf(oldRoute);
assert(index >= 0); assert(index >= 0);
newRoute._navigator = this; newRoute._navigator = this;
newRoute.install(overlay, oldRoute.overlayEntries.last); newRoute.install(oldRoute.overlayEntries.last);
_history[index] = newRoute; _history[index] = newRoute;
newRoute.didReplace(oldRoute); newRoute.didReplace(oldRoute);
if (index > 0) if (index > 0)
...@@ -224,24 +245,14 @@ class NavigatorState extends State<Navigator> { ...@@ -224,24 +245,14 @@ class NavigatorState extends State<Navigator> {
assert(() { _debugLocked = false; return true; }); assert(() { _debugLocked = false; return true; });
} }
/// Like replace(), but affects the route before the given anchorRoute rather void _replaceRouteBefore({ Route anchorRoute, Route newRoute }) {
/// than the anchorRoute itself.
///
/// If newRoute is already the route before anchorRoute, then the call is
/// ignored.
///
/// The conditions described for [replace()] apply; for instance, the route
/// before anchorRoute must have overlays.
void replaceRouteBefore({ Route anchorRoute, Route newRoute }) {
assert(anchorRoute != null); assert(anchorRoute != null);
assert(anchorRoute._navigator == this); assert(anchorRoute._navigator == this);
assert(_history.indexOf(anchorRoute) > 0); assert(_history.indexOf(anchorRoute) > 0);
replace(oldRoute: _history[_history.indexOf(anchorRoute)-1], newRoute: newRoute); _replace(oldRoute: _history[_history.indexOf(anchorRoute)-1], newRoute: newRoute);
} }
/// Removes the route prior to the given anchorRoute without notifying void _removeRouteBefore(Route anchorRoute) {
/// neighbouring routes or the navigator observer, if any.
void removeRouteBefore(Route anchorRoute) {
assert(!_debugLocked); assert(!_debugLocked);
assert(() { _debugLocked = true; return true; }); assert(() { _debugLocked = true; return true; });
assert(anchorRoute._navigator == this); assert(anchorRoute._navigator == this);
...@@ -258,16 +269,7 @@ class NavigatorState extends State<Navigator> { ...@@ -258,16 +269,7 @@ class NavigatorState extends State<Navigator> {
assert(() { _debugLocked = false; return true; }); assert(() { _debugLocked = false; return true; });
} }
/// Removes the current route, notifying the observer (if any), and the bool _pop([dynamic result]) {
/// previous routes (using [Route.didPopNext]).
///
/// The type of the result argument, if provided, must match the type argument
/// of the class of the current route. (In practice, this is usually
/// "dynamic".)
///
/// Returns true if a route was popped; returns false if there are no further
/// previous routes.
bool pop([dynamic result]) {
assert(!_debugLocked); assert(!_debugLocked);
assert(() { _debugLocked = true; return true; }); assert(() { _debugLocked = true; return true; });
Route route = _history.last; Route route = _history.last;
...@@ -292,20 +294,123 @@ class NavigatorState extends State<Navigator> { ...@@ -292,20 +294,123 @@ class NavigatorState extends State<Navigator> {
return true; return true;
} }
/// Calls pop() repeatedly until the given route is the current route. void _popUntil(Route targetRoute) {
/// If it is already the current route, nothing happens.
void popUntil(Route targetRoute) {
assert(_history.contains(targetRoute)); assert(_history.contains(targetRoute));
while (!targetRoute.isCurrent) while (!targetRoute.isCurrent)
pop(); _pop();
}
bool _hadTransaction = true;
bool openTransaction(NavigatorTransactionCallback callback) {
assert(callback != null);
if (_hadTransaction)
return false;
_hadTransaction = true;
NavigatorTransaction transaction = new NavigatorTransaction._(this);
setState(() {
callback(transaction);
});
assert(() { transaction._debugClose(); return true; });
return true;
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(!_debugLocked); assert(!_debugLocked);
assert(_history.isNotEmpty); assert(_history.isNotEmpty);
_hadTransaction = false;
return new Overlay( return new Overlay(
key: _overlayKey, key: _overlayKey,
initialEntries: _history.first.overlayEntries initialEntries: _history.first.overlayEntries
); );
} }
} }
class NavigatorTransaction {
NavigatorTransaction._(this._navigator) {
assert(_navigator != null);
}
NavigatorState _navigator;
bool _debugOpen = true;
/// Invokes the Navigator's onGenerateRoute callback to create a route with
/// the given name, then calls [push()] with that route.
void pushNamed(String name, { Set<Key> mostValuableKeys }) {
assert(_debugOpen);
_navigator._pushNamed(name, mostValuableKeys: mostValuableKeys);
}
/// Adds the given route to the Navigator's history, and transitions to it.
/// The route will have didPush() called on it; the previous route, if any,
/// will have didPushNext() called on it; and the Navigator observer, if any,
/// will have didPush() called on it.
void push(Route route, { Set<Key> mostValuableKeys }) {
assert(_debugOpen);
_navigator._push(route, mostValuableKeys: mostValuableKeys);
}
/// Replaces one given route with another, but does not call didPush/didPop.
/// Instead, this calls install() on the new route, then didReplace() on the
/// new route passing the old route, then dispose() on the old route. The
/// navigator is not informed of the replacement.
///
/// The old route must have overlay entries, otherwise we won't know where to
/// insert the entries of the new route. The old route must not be currently
/// visible (i.e. a later route have overlay entries that are currently
/// opaque), otherwise the replacement would have a jarring effect.
///
/// It is safe to call this redundantly (replacing a route with itself). Such
/// calls are ignored.
void replace({ Route oldRoute, Route newRoute }) {
assert(_debugOpen);
_navigator._replace(oldRoute: oldRoute, newRoute: newRoute);
}
/// Like replace(), but affects the route before the given anchorRoute rather
/// than the anchorRoute itself.
///
/// If newRoute is already the route before anchorRoute, then the call is
/// ignored.
///
/// The conditions described for [replace()] apply; for instance, the route
/// before anchorRoute must have overlay entries.
void replaceRouteBefore({ Route anchorRoute, Route newRoute }) {
assert(_debugOpen);
_navigator._replaceRouteBefore(anchorRoute: anchorRoute, newRoute: newRoute);
}
/// Removes the route prior to the given anchorRoute without notifying
/// neighbouring routes or the navigator observer, if any.
void removeRouteBefore(Route anchorRoute) {
assert(_debugOpen);
_navigator._removeRouteBefore(anchorRoute);
}
/// Tries to removes the current route, calling its didPop() method. If that
/// method returns false, then nothing else happens. Otherwise, the observer
/// (if any) is notified using its didPop() method, and the previous route is
/// notified using [Route.didPopNext].
///
/// The type of the result argument, if provided, must match the type argument
/// of the class of the current route. (In practice, this is usually
/// "dynamic".)
///
/// Returns true if a route was popped; returns false if there are no further
/// previous routes.
bool pop([dynamic result]) {
assert(_debugOpen);
return _navigator._pop(result);
}
/// Calls pop() repeatedly until the given route is the current route.
/// If it is already the current route, nothing happens.
void popUntil(Route targetRoute) {
assert(_debugOpen);
_navigator._popUntil(targetRoute);
}
void _debugClose() {
assert(_debugOpen);
_debugOpen = false;
}
}
\ No newline at end of file
...@@ -44,6 +44,8 @@ class Overlay extends StatefulComponent { ...@@ -44,6 +44,8 @@ class Overlay extends StatefulComponent {
final List<OverlayEntry> initialEntries; final List<OverlayEntry> initialEntries;
static OverlayState of(BuildContext context) => context.ancestorStateOfType(OverlayState);
OverlayState createState() => new OverlayState(); OverlayState createState() => new OverlayState();
} }
......
...@@ -23,11 +23,11 @@ abstract class OverlayRoute<T> extends Route<T> { ...@@ -23,11 +23,11 @@ abstract class OverlayRoute<T> extends Route<T> {
List<OverlayEntry> get overlayEntries => _overlayEntries; List<OverlayEntry> get overlayEntries => _overlayEntries;
final List<OverlayEntry> _overlayEntries = <OverlayEntry>[]; final List<OverlayEntry> _overlayEntries = <OverlayEntry>[];
void install(OverlayState overlay, OverlayEntry insertionPoint) { void install(OverlayEntry insertionPoint) {
assert(_overlayEntries.isEmpty); assert(_overlayEntries.isEmpty);
for (WidgetBuilder builder in builders) for (WidgetBuilder builder in builders)
_overlayEntries.add(new OverlayEntry(builder: builder)); _overlayEntries.add(new OverlayEntry(builder: builder));
overlay?.insertAll(_overlayEntries, above: insertionPoint); navigator.overlay?.insertAll(_overlayEntries, above: insertionPoint);
} }
// Subclasses shouldn't call this if they want to delay the finished() call. // Subclasses shouldn't call this if they want to delay the finished() call.
...@@ -108,9 +108,9 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> { ...@@ -108,9 +108,9 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
} }
} }
void install(OverlayState overlay, OverlayEntry insertionPoint) { void install(OverlayEntry insertionPoint) {
_performance = createPerformance(); _performance = createPerformance();
super.install(overlay, insertionPoint); super.install(insertionPoint);
} }
void didPush() { void didPush() {
......
...@@ -29,7 +29,7 @@ void main() { ...@@ -29,7 +29,7 @@ void main() {
expect(tester.findText('drawer'), isNotNull); expect(tester.findText('drawer'), isNotNull);
tester.pump(new Duration(seconds: 1)); // animation done tester.pump(new Duration(seconds: 1)); // animation done
expect(tester.findText('drawer'), isNotNull); expect(tester.findText('drawer'), isNotNull);
Navigator.of(context).pop(); Navigator.pop(context);
tester.pump(); // drawer should be starting to animate away tester.pump(); // drawer should be starting to animate away
expect(tester.findText('drawer'), isNotNull); expect(tester.findText('drawer'), isNotNull);
tester.pump(new Duration(seconds: 1)); // animation done tester.pump(new Duration(seconds: 1)); // animation done
......
...@@ -15,13 +15,13 @@ final Map<String, RouteBuilder> routes = <String, RouteBuilder>{ ...@@ -15,13 +15,13 @@ final Map<String, RouteBuilder> routes = <String, RouteBuilder>{
new Container(height: 100.0, width: 100.0), new Container(height: 100.0, width: 100.0),
new Card(child: new Hero(tag: 'a', child: new Container(height: 100.0, width: 100.0, key: firstKey))), new Card(child: new Hero(tag: 'a', child: new Container(height: 100.0, width: 100.0, key: firstKey))),
new Container(height: 100.0, width: 100.0), new Container(height: 100.0, width: 100.0),
new FlatButton(child: new Text('button'), onPressed: () => Navigator.of(args.context).pushNamed('/two')), new FlatButton(child: new Text('button'), onPressed: () => Navigator.pushNamed(args.context, '/two')),
]), ]),
'/two': (RouteArguments args) => new Block([ '/two': (RouteArguments args) => new Block([
new Container(height: 150.0, width: 150.0), new Container(height: 150.0, width: 150.0),
new Card(child: new Hero(tag: 'a', child: new Container(height: 150.0, width: 150.0, key: secondKey))), new Card(child: new Hero(tag: 'a', child: new Container(height: 150.0, width: 150.0, key: secondKey))),
new Container(height: 150.0, width: 150.0), new Container(height: 150.0, width: 150.0),
new FlatButton(child: new Text('button'), onPressed: () => Navigator.of(args.context).pop()), new FlatButton(child: new Text('button'), onPressed: () => Navigator.pop(args.context)),
]), ]),
}; };
......
...@@ -10,7 +10,7 @@ class FirstComponent extends StatelessComponent { ...@@ -10,7 +10,7 @@ class FirstComponent extends StatelessComponent {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new GestureDetector( return new GestureDetector(
onTap: () { onTap: () {
Navigator.of(context).pushNamed('/second'); Navigator.pushNamed(context, '/second');
}, },
child: new Container( child: new Container(
decoration: new BoxDecoration( decoration: new BoxDecoration(
...@@ -29,7 +29,7 @@ class SecondComponent extends StatefulComponent { ...@@ -29,7 +29,7 @@ class SecondComponent extends StatefulComponent {
class SecondComponentState extends State<SecondComponent> { class SecondComponentState extends State<SecondComponent> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new GestureDetector( return new GestureDetector(
onTap: Navigator.of(context).pop, onTap: () => Navigator.pop(context),
child: new Container( child: new Container(
decoration: new BoxDecoration( decoration: new BoxDecoration(
backgroundColor: new Color(0xFFFF00FF) backgroundColor: new Color(0xFFFF00FF)
......
...@@ -16,10 +16,11 @@ class TestOverlayRoute extends OverlayRoute { ...@@ -16,10 +16,11 @@ class TestOverlayRoute extends OverlayRoute {
void main() { void main() {
test('Check onstage/offstage handling around transitions', () { test('Check onstage/offstage handling around transitions', () {
testWidgets((WidgetTester tester) { testWidgets((WidgetTester tester) {
GlobalKey containerKey = new GlobalKey(); GlobalKey containerKey1 = new GlobalKey();
GlobalKey containerKey2 = new GlobalKey();
final Map<String, RouteBuilder> routes = <String, RouteBuilder>{ final Map<String, RouteBuilder> routes = <String, RouteBuilder>{
'/': (_) => new Container(key: containerKey, child: new Text('Home')), '/': (_) => new Container(key: containerKey1, child: new Text('Home')),
'/settings': (_) => new Container(child: new Text('Settings')), '/settings': (_) => new Container(key: containerKey2, child: new Text('Settings')),
}; };
tester.pumpWidget(new MaterialApp(routes: routes)); tester.pumpWidget(new MaterialApp(routes: routes));
...@@ -28,9 +29,7 @@ void main() { ...@@ -28,9 +29,7 @@ void main() {
expect(tester.findText('Settings'), isNull); expect(tester.findText('Settings'), isNull);
expect(tester.findText('Overlay'), isNull); expect(tester.findText('Overlay'), isNull);
NavigatorState navigator = Navigator.of(containerKey.currentContext); Navigator.pushNamed(containerKey1.currentContext, '/settings');
navigator.pushNamed('/settings');
tester.pump(); tester.pump();
...@@ -50,7 +49,7 @@ void main() { ...@@ -50,7 +49,7 @@ void main() {
expect(tester.findText('Settings'), isOnStage); expect(tester.findText('Settings'), isOnStage);
expect(tester.findText('Overlay'), isNull); expect(tester.findText('Overlay'), isNull);
navigator.push(new TestOverlayRoute()); Navigator.push(containerKey2.currentContext, new TestOverlayRoute());
tester.pump(); tester.pump();
...@@ -64,7 +63,7 @@ void main() { ...@@ -64,7 +63,7 @@ void main() {
expect(tester.findText('Settings'), isOnStage); expect(tester.findText('Settings'), isOnStage);
expect(tester.findText('Overlay'), isOnStage); expect(tester.findText('Overlay'), isOnStage);
navigator.pop(); Navigator.pop(containerKey2.currentContext);
tester.pump(); tester.pump();
expect(tester.findText('Home'), isNull); expect(tester.findText('Home'), isNull);
...@@ -77,7 +76,7 @@ void main() { ...@@ -77,7 +76,7 @@ void main() {
expect(tester.findText('Settings'), isOnStage); expect(tester.findText('Settings'), isOnStage);
expect(tester.findText('Overlay'), isNull); expect(tester.findText('Overlay'), isNull);
navigator.pop(); Navigator.pop(containerKey2.currentContext);
tester.pump(); tester.pump();
expect(tester.findText('Home'), isOnStage); expect(tester.findText('Home'), isOnStage);
......
...@@ -74,7 +74,9 @@ void main() { ...@@ -74,7 +74,9 @@ void main() {
expect(tester.findText('16'), isNull); expect(tester.findText('16'), isNull);
expect(tester.findText('100'), isNull); expect(tester.findText('100'), isNull);
navigatorKey.currentState.pushNamed('/second'); navigatorKey.currentState.openTransaction(
(NavigatorTransaction transaction) => transaction.pushNamed('/second')
);
tester.pump(); // navigating always takes two frames tester.pump(); // navigating always takes two frames
tester.pump(new Duration(seconds: 1)); tester.pump(new Duration(seconds: 1));
...@@ -89,7 +91,9 @@ void main() { ...@@ -89,7 +91,9 @@ void main() {
expect(tester.findText('10'), isNull); expect(tester.findText('10'), isNull);
expect(tester.findText('100'), isNull); expect(tester.findText('100'), isNull);
navigatorKey.currentState.pop(); navigatorKey.currentState.openTransaction(
(NavigatorTransaction transaction) => transaction.pop()
);
tester.pump(); // navigating always takes two frames tester.pump(); // navigating always takes two frames
tester.pump(new Duration(seconds: 1)); tester.pump(new Duration(seconds: 1));
......
...@@ -22,14 +22,14 @@ class TestRoute extends Route<String> { ...@@ -22,14 +22,14 @@ class TestRoute extends Route<String> {
results.add('$name: $s'); results.add('$name: $s');
} }
void install(OverlayState overlay, OverlayEntry insertionPoint) { void install(OverlayEntry insertionPoint) {
log('install'); log('install');
OverlayEntry entry = new OverlayEntry( OverlayEntry entry = new OverlayEntry(
builder: (BuildContext context) => new Container(), builder: (BuildContext context) => new Container(),
opaque: true opaque: true
); );
_entries.add(entry); _entries.add(entry);
overlay?.insert(entry, above: insertionPoint); navigator.overlay?.insert(entry, above: insertionPoint);
routes.add(this); routes.add(this);
} }
...@@ -73,11 +73,11 @@ class TestRoute extends Route<String> { ...@@ -73,11 +73,11 @@ class TestRoute extends Route<String> {
void runNavigatorTest( void runNavigatorTest(
WidgetTester tester, WidgetTester tester,
NavigatorState host, NavigatorState host,
void test(NavigatorState transaction), NavigatorTransactionCallback test,
List<String> expectations List<String> expectations
) { ) {
expect(host, isNotNull); expect(host, isNotNull);
test(host); host.openTransaction(test);
expect(results, equals(expectations)); expect(results, equals(expectations));
results.clear(); results.clear();
tester.pump(); tester.pump();
...@@ -95,7 +95,7 @@ void main() { ...@@ -95,7 +95,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
}, },
[ [
'initial: install', 'initial: install',
...@@ -106,7 +106,7 @@ void main() { ...@@ -106,7 +106,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.push(second = new TestRoute('second')); transaction.push(second = new TestRoute('second'));
}, },
[ [
...@@ -118,7 +118,7 @@ void main() { ...@@ -118,7 +118,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.push(new TestRoute('third')); transaction.push(new TestRoute('third'));
}, },
[ [
...@@ -130,7 +130,7 @@ void main() { ...@@ -130,7 +130,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.replace(oldRoute: second, newRoute: new TestRoute('two')); transaction.replace(oldRoute: second, newRoute: new TestRoute('two'));
}, },
[ [
...@@ -143,7 +143,7 @@ void main() { ...@@ -143,7 +143,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.pop('hello'); transaction.pop('hello');
}, },
[ [
...@@ -155,7 +155,7 @@ void main() { ...@@ -155,7 +155,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.pop('good bye'); transaction.pop('good bye');
}, },
[ [
...@@ -182,7 +182,7 @@ void main() { ...@@ -182,7 +182,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
}, },
[ [
'first: install', 'first: install',
...@@ -193,7 +193,7 @@ void main() { ...@@ -193,7 +193,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.push(second = new TestRoute('second')); transaction.push(second = new TestRoute('second'));
}, },
[ [
...@@ -205,7 +205,7 @@ void main() { ...@@ -205,7 +205,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.push(new TestRoute('third')); transaction.push(new TestRoute('third'));
}, },
[ [
...@@ -217,7 +217,7 @@ void main() { ...@@ -217,7 +217,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.removeRouteBefore(second); transaction.removeRouteBefore(second);
}, },
[ [
...@@ -227,7 +227,7 @@ void main() { ...@@ -227,7 +227,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.pop('good bye'); transaction.pop('good bye');
}, },
[ [
...@@ -239,7 +239,7 @@ void main() { ...@@ -239,7 +239,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.push(new TestRoute('three')); transaction.push(new TestRoute('three'));
}, },
[ [
...@@ -252,7 +252,7 @@ void main() { ...@@ -252,7 +252,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.push(four = new TestRoute('four')); transaction.push(four = new TestRoute('four'));
}, },
[ [
...@@ -264,7 +264,7 @@ void main() { ...@@ -264,7 +264,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.removeRouteBefore(four); transaction.removeRouteBefore(four);
}, },
[ [
...@@ -274,7 +274,7 @@ void main() { ...@@ -274,7 +274,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.pop('the end'); transaction.pop('the end');
}, },
[ [
...@@ -301,7 +301,7 @@ void main() { ...@@ -301,7 +301,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
}, },
[ [
'A: install', 'A: install',
...@@ -311,7 +311,7 @@ void main() { ...@@ -311,7 +311,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.push(new TestRoute('B')); transaction.push(new TestRoute('B'));
}, },
[ [
...@@ -324,7 +324,7 @@ void main() { ...@@ -324,7 +324,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.push(routeC = new TestRoute('C')); transaction.push(routeC = new TestRoute('C'));
}, },
[ [
...@@ -337,7 +337,7 @@ void main() { ...@@ -337,7 +337,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.replaceRouteBefore(anchorRoute: routeC, newRoute: routeB = new TestRoute('b')); transaction.replaceRouteBefore(anchorRoute: routeC, newRoute: routeB = new TestRoute('b'));
}, },
[ [
...@@ -350,7 +350,7 @@ void main() { ...@@ -350,7 +350,7 @@ void main() {
runNavigatorTest( runNavigatorTest(
tester, tester,
host, host,
(NavigatorState transaction) { (NavigatorTransaction transaction) {
transaction.popUntil(routeB); transaction.popUntil(routeB);
}, },
[ [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment