diff --git a/veggieseasons/lib/main.dart b/veggieseasons/lib/main.dart index bd334ee3a69..75b3aa1a170 100644 --- a/veggieseasons/lib/main.dart +++ b/veggieseasons/lib/main.dart @@ -17,10 +17,41 @@ void main() { ]); runApp( - MultiProvider( + RootRestorationScope( + restorationId: 'root', + child: VeggieApp(), + ), + ); +} + +class VeggieApp extends StatefulWidget { + @override + State createState() => _VeggieAppState(); +} + +class _VeggieAppState extends State with RestorationMixin { + final _RestorableAppState _appState = _RestorableAppState(); + + @override + String get restorationId => 'wrapper'; + + @override + void restoreState(RestorationBucket oldBucket, bool initialRestore) { + registerForRestoration(_appState, 'state'); + } + + @override + void dispose() { + super.dispose(); + _appState.dispose(); + } + + @override + Widget build(BuildContext context) { + return MultiProvider( providers: [ - ChangeNotifierProvider( - create: (_) => AppState(), + ChangeNotifierProvider.value( + value: _appState.value, ), ChangeNotifierProvider( create: (_) => Preferences()..load(), @@ -28,8 +59,31 @@ void main() { ], child: CupertinoApp( debugShowCheckedModeBanner: false, - home: HomeScreen(), + home: HomeScreen(restorationId: 'home'), + restorationScopeId: 'app', ), - ), - ); + ); + } +} + +class _RestorableAppState extends RestorableListenable { + @override + AppState createDefaultValue() { + return AppState(); + } + + @override + AppState fromPrimitives(Object data) { + final appState = AppState(); + final favorites = (data as List).cast(); + for (var id in favorites) { + appState.setFavorite(id, true); + } + return appState; + } + + @override + Object toPrimitives() { + return value.favoriteVeggies.map((veggie) => veggie.id).toList(); + } } diff --git a/veggieseasons/lib/screens/details.dart b/veggieseasons/lib/screens/details.dart index 1bcca04b76b..92bf47f87d4 100644 --- a/veggieseasons/lib/screens/details.dart +++ b/veggieseasons/lib/screens/details.dart @@ -238,15 +238,42 @@ class InfoView extends StatelessWidget { class DetailsScreen extends StatefulWidget { final int id; + final String restorationId; - DetailsScreen(this.id); + DetailsScreen({this.id, this.restorationId}); + + static String show(NavigatorState navigator, int veggieId) { + return navigator.restorablePush(_routeBuilder, arguments: veggieId); + } + + static Route _routeBuilder(BuildContext context, Object arguments) { + final veggieId = arguments as int; + return CupertinoPageRoute( + builder: (context) => DetailsScreen(id: veggieId, restorationId: 'details'), + fullscreenDialog: true, + ); + } @override _DetailsScreenState createState() => _DetailsScreenState(); } -class _DetailsScreenState extends State { - int _selectedViewIndex = 0; +class _DetailsScreenState extends State with RestorationMixin { + final RestorableInt _selectedViewIndex = RestorableInt(0); + + @override + String get restorationId => widget.restorationId; + + @override + void restoreState(RestorationBucket oldBucket, bool initialRestore) { + registerForRestoration(_selectedViewIndex, 'tab'); + } + + @override + void dispose() { + super.dispose(); + _selectedViewIndex.dispose(); + } Widget _buildHeader(BuildContext context, AppState model) { final veggie = model.getVeggie(widget.id); @@ -282,33 +309,37 @@ class _DetailsScreenState extends State { Widget build(BuildContext context) { final appState = Provider.of(context); - return CupertinoPageScaffold( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: ListView( - children: [ - _buildHeader(context, appState), - SizedBox(height: 20), - CupertinoSegmentedControl( - children: { - 0: Text('Facts & Info'), - 1: Text('Trivia'), - }, - groupValue: _selectedViewIndex, - onValueChanged: (value) { - setState(() => _selectedViewIndex = value); - }, - ), - _selectedViewIndex == 0 - ? InfoView(widget.id) - : TriviaView(widget.id), - ], + return UnmanagedRestorationScope( + bucket: bucket, + child: CupertinoPageScaffold( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: ListView( + restorationId: 'list', + children: [ + _buildHeader(context, appState), + SizedBox(height: 20), + CupertinoSegmentedControl( + children: { + 0: Text('Facts & Info'), + 1: Text('Trivia'), + }, + groupValue: _selectedViewIndex.value, + onValueChanged: (value) { + setState(() => _selectedViewIndex.value = value); + }, + ), + _selectedViewIndex.value == 0 + ? InfoView(widget.id) + : TriviaView(id: widget.id, restorationId: 'trivia'), + ], + ), ), - ), - ], + ], + ), ), ); } diff --git a/veggieseasons/lib/screens/favorites.dart b/veggieseasons/lib/screens/favorites.dart index f565c6be93f..05446673e2d 100644 --- a/veggieseasons/lib/screens/favorites.dart +++ b/veggieseasons/lib/screens/favorites.dart @@ -11,9 +11,14 @@ import 'package:veggieseasons/styles.dart'; import 'package:veggieseasons/widgets/veggie_headline.dart'; class FavoritesScreen extends StatelessWidget { + FavoritesScreen({this.restorationId, Key key}) : super(key: key); + + final String restorationId; + @override Widget build(BuildContext context) { return CupertinoTabView( + restorationScopeId: restorationId, builder: (context) { final model = Provider.of(context); @@ -32,6 +37,7 @@ class FavoritesScreen extends StatelessWidget { ), ) : ListView( + restorationId: 'list', children: [ SizedBox(height: 24), for (Veggie veggie in model.favoriteVeggies) diff --git a/veggieseasons/lib/screens/home.dart b/veggieseasons/lib/screens/home.dart index cb01910c814..45fb96bd08c 100644 --- a/veggieseasons/lib/screens/home.dart +++ b/veggieseasons/lib/screens/home.dart @@ -10,38 +10,46 @@ import 'package:veggieseasons/screens/search.dart'; import 'package:veggieseasons/screens/settings.dart'; class HomeScreen extends StatelessWidget { + HomeScreen({Key key, this.restorationId}) : super(key: key); + + final String restorationId; + @override Widget build(BuildContext context) { - return CupertinoTabScaffold( - tabBar: CupertinoTabBar(items: [ - BottomNavigationBarItem( - icon: Icon(CupertinoIcons.home), - label: 'Home', - ), - BottomNavigationBarItem( - icon: Icon(CupertinoIcons.book), - label: 'My Garden', - ), - BottomNavigationBarItem( - icon: Icon(CupertinoIcons.search), - label: 'Search', - ), - BottomNavigationBarItem( - icon: Icon(CupertinoIcons.settings), - label: 'Settings', - ), - ]), - tabBuilder: (context, index) { - if (index == 0) { - return ListScreen(); - } else if (index == 1) { - return FavoritesScreen(); - } else if (index == 2) { - return SearchScreen(); - } else { - return SettingsScreen(); - } - }, + return RestorationScope( + restorationId: restorationId, + child: CupertinoTabScaffold( + restorationId: 'scaffold', + tabBar: CupertinoTabBar(items: [ + BottomNavigationBarItem( + icon: Icon(CupertinoIcons.home), + label: 'Home', + ), + BottomNavigationBarItem( + icon: Icon(CupertinoIcons.book), + label: 'My Garden', + ), + BottomNavigationBarItem( + icon: Icon(CupertinoIcons.search), + label: 'Search', + ), + BottomNavigationBarItem( + icon: Icon(CupertinoIcons.settings), + label: 'Settings', + ), + ]), + tabBuilder: (context, index) { + if (index == 0) { + return ListScreen(restorationId: 'list'); + } else if (index == 1) { + return FavoritesScreen(restorationId: 'favorites'); + } else if (index == 2) { + return SearchScreen(restorationId: 'search'); + } else { + return SettingsScreen(restorationId: 'settings'); + } + }, + ), ); } } diff --git a/veggieseasons/lib/screens/list.dart b/veggieseasons/lib/screens/list.dart index 288ee175819..8b49ce941ba 100644 --- a/veggieseasons/lib/screens/list.dart +++ b/veggieseasons/lib/screens/list.dart @@ -13,6 +13,10 @@ import 'package:veggieseasons/styles.dart'; import 'package:veggieseasons/widgets/veggie_card.dart'; class ListScreen extends StatelessWidget { + ListScreen({this.restorationId, Key key}) : super(key: key); + + final String restorationId; + Widget _generateVeggieRow(Veggie veggie, Preferences prefs, {bool inSeason = true}) { return Padding( @@ -29,6 +33,7 @@ class ListScreen extends StatelessWidget { @override Widget build(BuildContext context) { return CupertinoTabView( + restorationScopeId: restorationId, builder: (context) { var dateString = DateFormat('MMMM y').format(DateTime.now()); @@ -38,6 +43,7 @@ class ListScreen extends StatelessWidget { return SafeArea( bottom: false, child: ListView.builder( + restorationId: 'list', itemCount: appState.allVeggies.length + 2, itemBuilder: (context, index) { if (index == 0) { diff --git a/veggieseasons/lib/screens/search.dart b/veggieseasons/lib/screens/search.dart index 986cfca304b..760959c0992 100644 --- a/veggieseasons/lib/screens/search.dart +++ b/veggieseasons/lib/screens/search.dart @@ -12,36 +12,45 @@ import 'package:veggieseasons/widgets/search_bar.dart'; import 'package:veggieseasons/widgets/veggie_headline.dart'; class SearchScreen extends StatefulWidget { + SearchScreen({this.restorationId, Key key}) : super(key: key); + + final String restorationId; + @override _SearchScreenState createState() => _SearchScreenState(); } -class _SearchScreenState extends State { - final controller = TextEditingController(); +class _SearchScreenState extends State with RestorationMixin { + final controller = RestorableTextEditingController(); final focusNode = FocusNode(); - String terms = ''; + String terms; + + @override + String get restorationId => widget.restorationId; @override - void initState() { - super.initState(); + void restoreState(RestorationBucket oldBucket, bool initialRestore) { + registerForRestoration(controller, 'text'); controller.addListener(_onTextChanged); + terms = controller.value.text; } @override void dispose() { focusNode.dispose(); + controller.dispose(); super.dispose(); } void _onTextChanged() { - setState(() => terms = controller.text); + setState(() => terms = controller.value.text); } Widget _createSearchBox() { return Padding( padding: const EdgeInsets.all(8), child: SearchBar( - controller: controller, + controller: controller.value, focusNode: focusNode, ), ); @@ -61,6 +70,7 @@ class _SearchScreenState extends State { } return ListView.builder( + restorationId: 'list', itemCount: veggies.length, itemBuilder: (context, i) { return Padding( @@ -75,20 +85,24 @@ class _SearchScreenState extends State { Widget build(BuildContext context) { final model = Provider.of(context); - return CupertinoTabView( - builder: (context) { - return SafeArea( - bottom: false, - child: Column( - children: [ - _createSearchBox(), - Expanded( - child: _buildSearchResults(model.searchVeggies(terms)), - ), - ], - ), - ); - }, + return UnmanagedRestorationScope( + bucket: bucket, + child: CupertinoTabView( + restorationScopeId: 'tabview', + builder: (context) { + return SafeArea( + bottom: false, + child: Column( + children: [ + _createSearchBox(), + Expanded( + child: _buildSearchResults(model.searchVeggies(terms)), + ), + ], + ), + ); + }, + ), ); } } diff --git a/veggieseasons/lib/screens/settings.dart b/veggieseasons/lib/screens/settings.dart index 912840f03ba..6accd80d6a9 100644 --- a/veggieseasons/lib/screens/settings.dart +++ b/veggieseasons/lib/screens/settings.dart @@ -13,119 +13,161 @@ import 'package:veggieseasons/widgets/settings_group.dart'; import 'package:veggieseasons/widgets/settings_item.dart'; class VeggieCategorySettingsScreen extends StatelessWidget { + VeggieCategorySettingsScreen({Key key, this.restorationId}) : super(key: key); + + final String restorationId; + + static String show(NavigatorState navigator) { + return navigator.restorablePush(_routeBuilder); + } + + static Route _routeBuilder(BuildContext context, Object argument) { + return CupertinoPageRoute( + builder: (context) => VeggieCategorySettingsScreen(restorationId: 'category'), + title: 'Preferred Categories', + ); + } + @override Widget build(BuildContext context) { final model = Provider.of(context); final currentPrefs = model.preferredCategories; var brightness = CupertinoTheme.brightnessOf(context); - return CupertinoPageScaffold( - navigationBar: CupertinoNavigationBar( - middle: Text('Preferred Categories'), - previousPageTitle: 'Settings', - ), - backgroundColor: Styles.scaffoldBackground(brightness), - child: FutureBuilder>( - future: currentPrefs, - builder: (context, snapshot) { - final items = []; - - for (final category in VeggieCategory.values) { - CupertinoSwitch toggle; - - // It's possible that category data hasn't loaded from shared prefs - // yet, so display it if possible and fall back to disabled switches - // otherwise. - if (snapshot.hasData) { - toggle = CupertinoSwitch( - value: snapshot.data.contains(category), - onChanged: (value) { - if (value) { - model.addPreferredCategory(category); - } else { - model.removePreferredCategory(category); - } - }, - ); - } else { - toggle = CupertinoSwitch( - value: false, - onChanged: null, - ); - } + return RestorationScope( + restorationId: restorationId, + child: CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar( + middle: Text('Preferred Categories'), + previousPageTitle: 'Settings', + ), + backgroundColor: Styles.scaffoldBackground(brightness), + child: FutureBuilder>( + future: currentPrefs, + builder: (context, snapshot) { + final items = []; - items.add(SettingsItem( - label: veggieCategoryNames[category], - content: toggle, - )); - } + for (final category in VeggieCategory.values) { + CupertinoSwitch toggle; - return ListView( - children: [ - SettingsGroup( - items: items, - ), - ], - ); - }, + // It's possible that category data hasn't loaded from shared prefs + // yet, so display it if possible and fall back to disabled switches + // otherwise. + if (snapshot.hasData) { + toggle = CupertinoSwitch( + value: snapshot.data.contains(category), + onChanged: (value) { + if (value) { + model.addPreferredCategory(category); + } else { + model.removePreferredCategory(category); + } + }, + ); + } else { + toggle = CupertinoSwitch( + value: false, + onChanged: null, + ); + } + + items.add(SettingsItem( + label: veggieCategoryNames[category], + content: toggle, + )); + } + + return ListView( + restorationId: 'list', + children: [ + SettingsGroup( + items: items, + ), + ], + ); + }, + ), ), ); } } class CalorieSettingsScreen extends StatelessWidget { + CalorieSettingsScreen({Key key, this.restorationId}) : super(key: key); + + final String restorationId; + static const max = 1000; static const min = 2600; static const step = 200; + static String show(NavigatorState navigator) { + return navigator.restorablePush(_routeBuilder); + } + + static Route _routeBuilder(BuildContext context, Object argument) { + return CupertinoPageRoute( + builder: (context) => CalorieSettingsScreen(restorationId: 'calorie'), + title: 'Calorie Target', + ); + } + @override Widget build(BuildContext context) { final model = Provider.of(context); var brightness = CupertinoTheme.brightnessOf(context); - return CupertinoPageScaffold( - navigationBar: CupertinoNavigationBar( - previousPageTitle: 'Settings', - ), - backgroundColor: Styles.scaffoldBackground(brightness), - child: ListView( - children: [ - FutureBuilder( - future: model.desiredCalories, - builder: (context, snapshot) { - final steps = []; - - for (var cals = max; cals < min; cals += step) { - steps.add( - SettingsItem( - label: cals.toString(), - icon: SettingsIcon( - icon: Styles.checkIcon, - foregroundColor: snapshot.hasData && snapshot.data == cals - ? CupertinoColors.activeBlue - : Styles.transparentColor, - backgroundColor: Styles.transparentColor, + return RestorationScope( + restorationId: restorationId, + child: CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar( + previousPageTitle: 'Settings', + ), + backgroundColor: Styles.scaffoldBackground(brightness), + child: ListView( + restorationId: 'list', + children: [ + FutureBuilder( + future: model.desiredCalories, + builder: (context, snapshot) { + final steps = []; + + for (var cals = max; cals < min; cals += step) { + steps.add( + SettingsItem( + label: cals.toString(), + icon: SettingsIcon( + icon: Styles.checkIcon, + foregroundColor: snapshot.hasData && snapshot.data == cals + ? CupertinoColors.activeBlue + : Styles.transparentColor, + backgroundColor: Styles.transparentColor, + ), + onPress: snapshot.hasData + ? () => model.setDesiredCalories(cals) + : null, ), - onPress: snapshot.hasData - ? () => model.setDesiredCalories(cals) - : null, - ), - ); - } + ); + } - return SettingsGroup( - items: steps, - header: SettingsGroupHeader('Available calorie levels'), - footer: SettingsGroupFooter('These are used for serving ' - 'calculations'), - ); - }, - ), - ], + return SettingsGroup( + items: steps, + header: SettingsGroupHeader('Available calorie levels'), + footer: SettingsGroupFooter('These are used for serving ' + 'calculations'), + ); + }, + ), + ], + ), ), ); } } class SettingsScreen extends StatelessWidget { + SettingsScreen({this.restorationId, Key key}) : super(key: key); + + final String restorationId; + SettingsItem _buildCaloriesItem(BuildContext context, Preferences prefs) { return SettingsItem( label: 'Calorie Target', @@ -149,12 +191,7 @@ class SettingsScreen extends StatelessWidget { }, ), onPress: () { - Navigator.of(context).push( - CupertinoPageRoute( - builder: (context) => CalorieSettingsScreen(), - title: 'Calorie Target', - ), - ); + CalorieSettingsScreen.show(Navigator.of(context)); }, ); } @@ -169,12 +206,7 @@ class SettingsScreen extends StatelessWidget { ), content: SettingsNavigationIndicator(), onPress: () { - Navigator.of(context).push( - CupertinoPageRoute( - builder: (context) => VeggieCategorySettingsScreen(), - title: 'Preferred Categories', - ), - ); + VeggieCategorySettingsScreen.show(Navigator.of(context)); }, ); } @@ -183,30 +215,34 @@ class SettingsScreen extends StatelessWidget { Widget build(BuildContext context) { final prefs = Provider.of(context); - return CupertinoPageScaffold( - child: Container( - color: Styles.scaffoldBackground(CupertinoTheme.brightnessOf(context)), - child: CustomScrollView( - slivers: [ - CupertinoSliverNavigationBar( - largeTitle: Text('Settings'), - ), - SliverSafeArea( - top: false, - sliver: SliverList( - delegate: SliverChildListDelegate( - [ - SettingsGroup( - items: [ - _buildCaloriesItem(context, prefs), - _buildCategoriesItem(context, prefs), - ], - ), - ], + return RestorationScope( + restorationId: restorationId, + child: CupertinoPageScaffold( + child: Container( + color: Styles.scaffoldBackground(CupertinoTheme.brightnessOf(context)), + child: CustomScrollView( + restorationId: 'list', + slivers: [ + CupertinoSliverNavigationBar( + largeTitle: Text('Settings'), + ), + SliverSafeArea( + top: false, + sliver: SliverList( + delegate: SliverChildListDelegate( + [ + SettingsGroup( + items: [ + _buildCaloriesItem(context, prefs), + _buildCategoriesItem(context, prefs), + ], + ), + ], + ), ), ), - ), - ], + ], + ), ), ), ); diff --git a/veggieseasons/lib/widgets/trivia.dart b/veggieseasons/lib/widgets/trivia.dart index 11dcde679af..a7a49b274f2 100644 --- a/veggieseasons/lib/widgets/trivia.dart +++ b/veggieseasons/lib/widgets/trivia.dart @@ -9,8 +9,9 @@ import 'package:veggieseasons/styles.dart'; /// the user's score. class TriviaView extends StatefulWidget { final int id; + final String restorationId; - const TriviaView(this.id); + const TriviaView({this.id, this.restorationId}); @override _TriviaViewState createState() => _TriviaViewState(); @@ -23,7 +24,7 @@ enum PlayerStatus { wasIncorrect, } -class _TriviaViewState extends State { +class _TriviaViewState extends State with RestorationMixin { /// Current app state. This is used to fetch veggie data. AppState appState; @@ -31,16 +32,26 @@ class _TriviaViewState extends State { Veggie veggie; /// Index of the current trivia question. - int triviaIndex = 0; + RestorableInt triviaIndex = RestorableInt(0); /// User's score on the current veggie. - int score = 0; + RestorableInt score = RestorableInt(0); /// Trivia question currently being displayed. - Trivia get currentTrivia => veggie.trivia[triviaIndex]; + Trivia get currentTrivia => veggie.trivia[triviaIndex.value]; /// The current state of the game. - PlayerStatus status = PlayerStatus.readyToAnswer; + _RestorablePlayerStatus status = _RestorablePlayerStatus(PlayerStatus.readyToAnswer); + + @override + String get restorationId => widget.restorationId; + + @override + void restoreState(RestorationBucket oldBucket, bool initialRestore) { + registerForRestoration(triviaIndex, 'index'); + registerForRestoration(score, 'score'); + registerForRestoration(status, 'status'); + } // Called at init and again if any dependencies (read: InheritedWidgets) on // on which this object relies are changed. @@ -72,11 +83,19 @@ class _TriviaViewState extends State { } } + @override + void dispose() { + triviaIndex.dispose(); + score.dispose(); + status.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { - if (triviaIndex >= veggie.trivia.length) { + if (triviaIndex.value >= veggie.trivia.length) { return _buildFinishedView(); - } else if (status == PlayerStatus.readyToAnswer) { + } else if (status.value == PlayerStatus.readyToAnswer) { return _buildQuestionView(); } else { return _buildResultView(); @@ -85,19 +104,19 @@ class _TriviaViewState extends State { void _resetGame() { setState(() { - triviaIndex = 0; - score = 0; - status = PlayerStatus.readyToAnswer; + triviaIndex.value = 0; + score.value = 0; + status.value = PlayerStatus.readyToAnswer; }); } void _processAnswer(int answerIndex) { setState(() { if (answerIndex == currentTrivia.correctAnswerIndex) { - status = PlayerStatus.wasCorrect; - score++; + status.value = PlayerStatus.wasCorrect; + score.value++; } else { - status = PlayerStatus.wasIncorrect; + status.value = PlayerStatus.wasIncorrect; } }); } @@ -193,7 +212,7 @@ class _TriviaViewState extends State { child: Column( children: [ Text( - status == PlayerStatus.wasCorrect + status.value == PlayerStatus.wasCorrect ? 'That\'s right!' : 'Sorry, that wasn\'t the right answer.', style: CupertinoTheme.of(context).textTheme.textStyle, @@ -202,8 +221,8 @@ class _TriviaViewState extends State { CupertinoButton( child: Text('Next Question'), onPressed: () => setState(() { - triviaIndex++; - status = PlayerStatus.readyToAnswer; + triviaIndex.value++; + status.value = PlayerStatus.readyToAnswer; }), ), ], @@ -211,3 +230,29 @@ class _TriviaViewState extends State { ); } } + +class _RestorablePlayerStatus extends RestorableValue { + _RestorablePlayerStatus(this._defaultValue); + + final PlayerStatus _defaultValue; + + @override + PlayerStatus createDefaultValue() { + return _defaultValue; + } + + @override + PlayerStatus fromPrimitives(Object data) { + return PlayerStatus.values[data as int]; + } + + @override + Object toPrimitives() { + return value.index; + } + + @override + void didUpdateValue(PlayerStatus oldValue) { + notifyListeners(); + } +} diff --git a/veggieseasons/lib/widgets/veggie_card.dart b/veggieseasons/lib/widgets/veggie_card.dart index f04f69edc2f..c1d5e495643 100644 --- a/veggieseasons/lib/widgets/veggie_card.dart +++ b/veggieseasons/lib/widgets/veggie_card.dart @@ -142,12 +142,7 @@ class VeggieCard extends StatelessWidget { @override Widget build(BuildContext context) { return PressableCard( - onPressed: () { - Navigator.of(context).push(CupertinoPageRoute( - builder: (context) => DetailsScreen(veggie.id), - fullscreenDialog: true, - )); - }, + onPressed: () => DetailsScreen.show(Navigator.of(context), veggie.id), child: Stack( children: [ Semantics( diff --git a/veggieseasons/lib/widgets/veggie_headline.dart b/veggieseasons/lib/widgets/veggie_headline.dart index 9d6bd93de50..4b1ebb480dc 100644 --- a/veggieseasons/lib/widgets/veggie_headline.dart +++ b/veggieseasons/lib/widgets/veggie_headline.dart @@ -70,10 +70,7 @@ class VeggieHeadline extends StatelessWidget { final themeData = CupertinoTheme.of(context); return GestureDetector( - onTap: () => Navigator.of(context).push(CupertinoPageRoute( - builder: (context) => DetailsScreen(veggie.id), - fullscreenDialog: true, - )), + onTap: () => DetailsScreen.show(Navigator.of(context), veggie.id), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/veggieseasons/pubspec.lock b/veggieseasons/pubspec.lock index ac91a1aa1b5..4f4961bdd2d 100644 --- a/veggieseasons/pubspec.lock +++ b/veggieseasons/pubspec.lock @@ -135,6 +135,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.16.1" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3-nullsafety.1" matcher: dependency: transitive description: @@ -148,7 +155,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.3" + version: "1.3.0-nullsafety.4" nested: dependency: transitive description: @@ -272,7 +279,7 @@ packages: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.1" + version: "1.10.0-nullsafety.2" stream_channel: dependency: transitive description: @@ -337,5 +344,5 @@ packages: source: hosted version: "2.2.1" sdks: - dart: ">=2.10.0-110 <2.11.0" + dart: ">=2.10.0-110 <=2.11.0-207.0.dev" flutter: ">=1.16.0 <2.0.0"