mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
veggieseasons: Migrate to null safety (#922)
This commit is contained in:
@@ -15,8 +15,8 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
shared_preferences: 5033afbb22d372e15aff8ff766df9021b845f273
|
||||||
|
|
||||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||||
|
|
||||||
COCOAPODS: 1.10.1
|
COCOAPODS: 1.11.0
|
||||||
|
|||||||
@@ -26,22 +26,22 @@ class AppState extends ChangeNotifier {
|
|||||||
return _veggies.where((v) => !v.seasons.contains(currentSeason)).toList();
|
return _veggies.where((v) => !v.seasons.contains(currentSeason)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Veggie getVeggie(int id) => _veggies.singleWhere((v) => v.id == id);
|
Veggie getVeggie(int? id) => _veggies.singleWhere((v) => v.id == id);
|
||||||
|
|
||||||
List<Veggie> searchVeggies(String terms) => _veggies
|
List<Veggie> searchVeggies(String? terms) => _veggies
|
||||||
.where((v) => v.name.toLowerCase().contains(terms.toLowerCase()))
|
.where((v) => v.name.toLowerCase().contains(terms!.toLowerCase()))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
void setFavorite(int id, bool isFavorite) {
|
void setFavorite(int? id, bool isFavorite) {
|
||||||
var veggie = getVeggie(id);
|
var veggie = getVeggie(id);
|
||||||
veggie.isFavorite = isFavorite;
|
veggie.isFavorite = isFavorite;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in tests to set the season independent of the current date.
|
/// Used in tests to set the season independent of the current date.
|
||||||
static Season debugCurrentSeason;
|
static Season? debugCurrentSeason;
|
||||||
|
|
||||||
static Season _getSeasonForDate(DateTime date) {
|
static Season? _getSeasonForDate(DateTime date) {
|
||||||
if (debugCurrentSeason != null) {
|
if (debugCurrentSeason != null) {
|
||||||
return debugCurrentSeason;
|
return debugCurrentSeason;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class Preferences extends ChangeNotifier {
|
|||||||
static const _preferredCategoriesKey = 'preferredCategories';
|
static const _preferredCategoriesKey = 'preferredCategories';
|
||||||
|
|
||||||
// Indicates whether a call to [_loadFromSharedPrefs] is in progress;
|
// Indicates whether a call to [_loadFromSharedPrefs] is in progress;
|
||||||
Future<void> _loading;
|
Future<void>? _loading;
|
||||||
|
|
||||||
int _desiredCalories = 2000;
|
int _desiredCalories = 2000;
|
||||||
|
|
||||||
@@ -79,9 +79,7 @@ class Preferences extends ChangeNotifier {
|
|||||||
if (names != null && names.isNotEmpty) {
|
if (names != null && names.isNotEmpty) {
|
||||||
for (final name in names.split(',')) {
|
for (final name in names.split(',')) {
|
||||||
final index = int.tryParse(name) ?? -1;
|
final index = int.tryParse(name) ?? -1;
|
||||||
if (VeggieCategory.values[index] != null) {
|
_preferredCategories.add(VeggieCategory.values[index]);
|
||||||
_preferredCategories.add(VeggieCategory.values[index]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
|
|
||||||
enum VeggieCategory {
|
enum VeggieCategory {
|
||||||
allium,
|
allium,
|
||||||
@@ -71,18 +70,18 @@ const Map<Season, String> seasonNames = {
|
|||||||
|
|
||||||
class Veggie {
|
class Veggie {
|
||||||
Veggie({
|
Veggie({
|
||||||
@required this.id,
|
required this.id,
|
||||||
@required this.name,
|
required this.name,
|
||||||
@required this.imageAssetPath,
|
required this.imageAssetPath,
|
||||||
@required this.category,
|
required this.category,
|
||||||
@required this.shortDescription,
|
required this.shortDescription,
|
||||||
@required this.accentColor,
|
required this.accentColor,
|
||||||
@required this.seasons,
|
required this.seasons,
|
||||||
@required this.vitaminAPercentage,
|
required this.vitaminAPercentage,
|
||||||
@required this.vitaminCPercentage,
|
required this.vitaminCPercentage,
|
||||||
@required this.servingSize,
|
required this.servingSize,
|
||||||
@required this.caloriesPerServing,
|
required this.caloriesPerServing,
|
||||||
@required this.trivia,
|
required this.trivia,
|
||||||
this.isFavorite = false,
|
this.isFavorite = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -127,5 +126,5 @@ class Veggie {
|
|||||||
/// A set of trivia questions and answers related to the veggie.
|
/// A set of trivia questions and answers related to the veggie.
|
||||||
final List<Trivia> trivia;
|
final List<Trivia> trivia;
|
||||||
|
|
||||||
String get categoryName => veggieCategoryNames[category];
|
String? get categoryName => veggieCategoryNames[category];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class VeggieApp extends StatefulWidget {
|
class VeggieApp extends StatefulWidget {
|
||||||
const VeggieApp({Key key}) : super(key: key);
|
const VeggieApp({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => _VeggieAppState();
|
State<StatefulWidget> createState() => _VeggieAppState();
|
||||||
@@ -39,7 +39,7 @@ class _VeggieAppState extends State<VeggieApp> with RestorationMixin {
|
|||||||
String get restorationId => 'wrapper';
|
String get restorationId => 'wrapper';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void restoreState(RestorationBucket oldBucket, bool initialRestore) {
|
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||||
registerForRestoration(_appState, 'state');
|
registerForRestoration(_appState, 'state');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ class _RestorableAppState extends RestorableListenable<AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AppState fromPrimitives(Object data) {
|
AppState fromPrimitives(Object? data) {
|
||||||
final appState = AppState();
|
final appState = AppState();
|
||||||
final favorites = (data as List<dynamic>).cast<int>();
|
final favorites = (data as List<dynamic>).cast<int>();
|
||||||
for (var id in favorites) {
|
for (var id in favorites) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import 'package:veggieseasons/widgets/close_button.dart';
|
|||||||
import 'package:veggieseasons/widgets/trivia.dart';
|
import 'package:veggieseasons/widgets/trivia.dart';
|
||||||
|
|
||||||
class ServingInfoChart extends StatelessWidget {
|
class ServingInfoChart extends StatelessWidget {
|
||||||
const ServingInfoChart(this.veggie, this.prefs, {Key key}) : super(key: key);
|
const ServingInfoChart(this.veggie, this.prefs, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
final Veggie veggie;
|
final Veggie veggie;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ class ServingInfoChart extends StatelessWidget {
|
|||||||
return FutureBuilder<int>(
|
return FutureBuilder<int>(
|
||||||
future: targetCalories,
|
future: targetCalories,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final target = snapshot?.data ?? 2000;
|
final target = snapshot.data ?? 2000;
|
||||||
final percent = standardPercentage * 2000 ~/ target;
|
final percent = standardPercentage * 2000 ~/ target;
|
||||||
|
|
||||||
return Text(
|
return Text(
|
||||||
@@ -141,7 +141,7 @@ class ServingInfoChart extends StatelessWidget {
|
|||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return Text(
|
return Text(
|
||||||
'Percent daily values based on a diet of '
|
'Percent daily values based on a diet of '
|
||||||
'${snapshot?.data ?? '2,000'} calories.',
|
'${snapshot.data ?? '2,000'} calories.',
|
||||||
style: Styles.detailsServingNoteText(themeData),
|
style: Styles.detailsServingNoteText(themeData),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -156,9 +156,9 @@ class ServingInfoChart extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InfoView extends StatelessWidget {
|
class InfoView extends StatelessWidget {
|
||||||
final int id;
|
final int? id;
|
||||||
|
|
||||||
const InfoView(this.id, {Key key}) : super(key: key);
|
const InfoView(this.id, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -179,9 +179,9 @@ class InfoView extends StatelessWidget {
|
|||||||
future: prefs.preferredCategories,
|
future: prefs.preferredCategories,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return Text(
|
return Text(
|
||||||
veggie.categoryName.toUpperCase(),
|
veggie.categoryName!.toUpperCase(),
|
||||||
style: (snapshot.hasData &&
|
style: (snapshot.hasData &&
|
||||||
snapshot.data.contains(veggie.category))
|
snapshot.data!.contains(veggie.category))
|
||||||
? Styles.detailsPreferredCategoryText(themeData)
|
? Styles.detailsPreferredCategoryText(themeData)
|
||||||
: themeData.textTheme.textStyle,
|
: themeData.textTheme.textStyle,
|
||||||
);
|
);
|
||||||
@@ -191,7 +191,7 @@ class InfoView extends StatelessWidget {
|
|||||||
for (Season season in veggie.seasons) ...[
|
for (Season season in veggie.seasons) ...[
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Padding(
|
Padding(
|
||||||
padding: Styles.seasonIconPadding[season],
|
padding: Styles.seasonIconPadding[season]!,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Styles.seasonIconData[season],
|
Styles.seasonIconData[season],
|
||||||
semanticLabel: seasonNames[season],
|
semanticLabel: seasonNames[season],
|
||||||
@@ -236,17 +236,18 @@ class InfoView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DetailsScreen extends StatefulWidget {
|
class DetailsScreen extends StatefulWidget {
|
||||||
final int id;
|
final int? id;
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
const DetailsScreen({this.id, this.restorationId, Key key}) : super(key: key);
|
const DetailsScreen({this.id, this.restorationId, Key? key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
static String show(NavigatorState navigator, int veggieId) {
|
static String show(NavigatorState navigator, int veggieId) {
|
||||||
return navigator.restorablePush<void>(_routeBuilder, arguments: veggieId);
|
return navigator.restorablePush<void>(_routeBuilder, arguments: veggieId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Route<void> _routeBuilder(BuildContext context, Object arguments) {
|
static Route<void> _routeBuilder(BuildContext context, Object? arguments) {
|
||||||
final veggieId = arguments as int;
|
final veggieId = arguments as int?;
|
||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
DetailsScreen(id: veggieId, restorationId: 'details'),
|
DetailsScreen(id: veggieId, restorationId: 'details'),
|
||||||
@@ -262,10 +263,10 @@ class _DetailsScreenState extends State<DetailsScreen> with RestorationMixin {
|
|||||||
final RestorableInt _selectedViewIndex = RestorableInt(0);
|
final RestorableInt _selectedViewIndex = RestorableInt(0);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get restorationId => widget.restorationId;
|
String? get restorationId => widget.restorationId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void restoreState(RestorationBucket oldBucket, bool initialRestore) {
|
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||||
registerForRestoration(_selectedViewIndex, 'tab');
|
registerForRestoration(_selectedViewIndex, 'tab');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import 'package:veggieseasons/data/veggie.dart';
|
|||||||
import 'package:veggieseasons/widgets/veggie_headline.dart';
|
import 'package:veggieseasons/widgets/veggie_headline.dart';
|
||||||
|
|
||||||
class FavoritesScreen extends StatelessWidget {
|
class FavoritesScreen extends StatelessWidget {
|
||||||
const FavoritesScreen({this.restorationId, Key key}) : super(key: key);
|
const FavoritesScreen({this.restorationId, Key? key}) : super(key: key);
|
||||||
|
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import 'package:veggieseasons/screens/search.dart';
|
|||||||
import 'package:veggieseasons/screens/settings.dart';
|
import 'package:veggieseasons/screens/settings.dart';
|
||||||
|
|
||||||
class HomeScreen extends StatelessWidget {
|
class HomeScreen extends StatelessWidget {
|
||||||
const HomeScreen({Key key, this.restorationId}) : super(key: key);
|
const HomeScreen({Key? key, this.restorationId}) : super(key: key);
|
||||||
|
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import 'package:veggieseasons/styles.dart';
|
|||||||
import 'package:veggieseasons/widgets/veggie_card.dart';
|
import 'package:veggieseasons/widgets/veggie_card.dart';
|
||||||
|
|
||||||
class ListScreen extends StatelessWidget {
|
class ListScreen extends StatelessWidget {
|
||||||
const ListScreen({this.restorationId, Key key}) : super(key: key);
|
const ListScreen({this.restorationId, Key? key}) : super(key: key);
|
||||||
|
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
Widget _generateVeggieRow(Veggie veggie, Preferences prefs,
|
Widget _generateVeggieRow(Veggie veggie, Preferences prefs,
|
||||||
{bool inSeason = true}) {
|
{bool inSeason = true}) {
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import 'package:veggieseasons/data/veggie.dart';
|
|||||||
import 'package:veggieseasons/widgets/veggie_headline.dart';
|
import 'package:veggieseasons/widgets/veggie_headline.dart';
|
||||||
|
|
||||||
class SearchScreen extends StatefulWidget {
|
class SearchScreen extends StatefulWidget {
|
||||||
const SearchScreen({this.restorationId, Key key}) : super(key: key);
|
const SearchScreen({this.restorationId, Key? key}) : super(key: key);
|
||||||
|
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_SearchScreenState createState() => _SearchScreenState();
|
_SearchScreenState createState() => _SearchScreenState();
|
||||||
@@ -22,13 +22,13 @@ class SearchScreen extends StatefulWidget {
|
|||||||
class _SearchScreenState extends State<SearchScreen> with RestorationMixin {
|
class _SearchScreenState extends State<SearchScreen> with RestorationMixin {
|
||||||
final controller = RestorableTextEditingController();
|
final controller = RestorableTextEditingController();
|
||||||
final focusNode = FocusNode();
|
final focusNode = FocusNode();
|
||||||
String terms;
|
String? terms;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get restorationId => widget.restorationId;
|
String? get restorationId => widget.restorationId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void restoreState(RestorationBucket oldBucket, bool initialRestore) {
|
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||||
registerForRestoration(controller, 'text');
|
registerForRestoration(controller, 'text');
|
||||||
controller.addListener(_onTextChanged);
|
controller.addListener(_onTextChanged);
|
||||||
terms = controller.value.text;
|
terms = controller.value.text;
|
||||||
|
|||||||
@@ -13,16 +13,16 @@ import 'package:veggieseasons/widgets/settings_group.dart';
|
|||||||
import 'package:veggieseasons/widgets/settings_item.dart';
|
import 'package:veggieseasons/widgets/settings_item.dart';
|
||||||
|
|
||||||
class VeggieCategorySettingsScreen extends StatelessWidget {
|
class VeggieCategorySettingsScreen extends StatelessWidget {
|
||||||
const VeggieCategorySettingsScreen({Key key, this.restorationId})
|
const VeggieCategorySettingsScreen({Key? key, this.restorationId})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
static String show(NavigatorState navigator) {
|
static String show(NavigatorState navigator) {
|
||||||
return navigator.restorablePush(_routeBuilder);
|
return navigator.restorablePush(_routeBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Route<void> _routeBuilder(BuildContext context, Object argument) {
|
static Route<void> _routeBuilder(BuildContext context, Object? argument) {
|
||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
const VeggieCategorySettingsScreen(restorationId: 'category'),
|
const VeggieCategorySettingsScreen(restorationId: 'category'),
|
||||||
@@ -56,7 +56,7 @@ class VeggieCategorySettingsScreen extends StatelessWidget {
|
|||||||
// otherwise.
|
// otherwise.
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
toggle = CupertinoSwitch(
|
toggle = CupertinoSwitch(
|
||||||
value: snapshot.data.contains(category),
|
value: snapshot.data!.contains(category),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
model.addPreferredCategory(category);
|
model.addPreferredCategory(category);
|
||||||
@@ -73,7 +73,7 @@ class VeggieCategorySettingsScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
items.add(SettingsItem(
|
items.add(SettingsItem(
|
||||||
label: veggieCategoryNames[category],
|
label: veggieCategoryNames[category]!,
|
||||||
content: toggle,
|
content: toggle,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -94,9 +94,9 @@ class VeggieCategorySettingsScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CalorieSettingsScreen extends StatelessWidget {
|
class CalorieSettingsScreen extends StatelessWidget {
|
||||||
const CalorieSettingsScreen({Key key, this.restorationId}) : super(key: key);
|
const CalorieSettingsScreen({Key? key, this.restorationId}) : super(key: key);
|
||||||
|
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
static const max = 1000;
|
static const max = 1000;
|
||||||
static const min = 2600;
|
static const min = 2600;
|
||||||
@@ -106,7 +106,7 @@ class CalorieSettingsScreen extends StatelessWidget {
|
|||||||
return navigator.restorablePush(_routeBuilder);
|
return navigator.restorablePush(_routeBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Route<void> _routeBuilder(BuildContext context, Object argument) {
|
static Route<void> _routeBuilder(BuildContext context, Object? argument) {
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
const CalorieSettingsScreen(restorationId: 'calorie'),
|
const CalorieSettingsScreen(restorationId: 'calorie'),
|
||||||
@@ -169,9 +169,9 @@ class CalorieSettingsScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SettingsScreen extends StatelessWidget {
|
class SettingsScreen extends StatelessWidget {
|
||||||
const SettingsScreen({this.restorationId, Key key}) : super(key: key);
|
const SettingsScreen({this.restorationId, Key? key}) : super(key: key);
|
||||||
|
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
SettingsItem _buildCaloriesItem(BuildContext context, Preferences prefs) {
|
SettingsItem _buildCaloriesItem(BuildContext context, Preferences prefs) {
|
||||||
return SettingsItem(
|
return SettingsItem(
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ abstract class Styles {
|
|||||||
|
|
||||||
static const appBackground = Color(0xffd0d0d0);
|
static const appBackground = Color(0xffd0d0d0);
|
||||||
|
|
||||||
static Color scaffoldBackground(Brightness brightness) =>
|
static Color? scaffoldBackground(Brightness brightness) =>
|
||||||
brightness == Brightness.light
|
brightness == Brightness.light
|
||||||
? CupertinoColors.lightBackgroundGray
|
? CupertinoColors.lightBackgroundGray
|
||||||
: null;
|
: null;
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ import 'package:veggieseasons/styles.dart';
|
|||||||
class FrostedBox extends StatelessWidget {
|
class FrostedBox extends StatelessWidget {
|
||||||
const FrostedBox({
|
const FrostedBox({
|
||||||
this.child,
|
this.child,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final Widget child;
|
final Widget? child;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -37,18 +37,15 @@ class ColorChangingIcon extends ImplicitlyAnimatedWidget {
|
|||||||
this.icon, {
|
this.icon, {
|
||||||
this.color = CupertinoColors.black,
|
this.color = CupertinoColors.black,
|
||||||
this.size,
|
this.size,
|
||||||
@required Duration duration,
|
required Duration duration,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : assert(icon != null),
|
}) : super(key: key, duration: duration);
|
||||||
assert(color != null),
|
|
||||||
assert(duration != null),
|
|
||||||
super(key: key, duration: duration);
|
|
||||||
|
|
||||||
final Color color;
|
final Color color;
|
||||||
|
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
|
|
||||||
final double size;
|
final double? size;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ColorChangingIconState createState() => _ColorChangingIconState();
|
_ColorChangingIconState createState() => _ColorChangingIconState();
|
||||||
@@ -56,7 +53,7 @@ class ColorChangingIcon extends ImplicitlyAnimatedWidget {
|
|||||||
|
|
||||||
class _ColorChangingIconState
|
class _ColorChangingIconState
|
||||||
extends AnimatedWidgetBaseState<ColorChangingIcon> {
|
extends AnimatedWidgetBaseState<ColorChangingIcon> {
|
||||||
ColorTween _colorTween;
|
ColorTween? _colorTween;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -73,14 +70,14 @@ class _ColorChangingIconState
|
|||||||
_colorTween = visitor(
|
_colorTween = visitor(
|
||||||
_colorTween,
|
_colorTween,
|
||||||
widget.color,
|
widget.color,
|
||||||
(dynamic value) => ColorTween(begin: value as Color),
|
(dynamic value) => ColorTween(begin: value as Color?),
|
||||||
) as ColorTween;
|
) as ColorTween?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple "close this modal" button that invokes a callback when pressed.
|
/// A simple "close this modal" button that invokes a callback when pressed.
|
||||||
class CloseButton extends StatefulWidget {
|
class CloseButton extends StatefulWidget {
|
||||||
const CloseButton(this.onPressed, {Key key}) : super(key: key);
|
const CloseButton(this.onPressed, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
final VoidCallback onPressed;
|
final VoidCallback onPressed;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import 'settings_item.dart';
|
|||||||
// See https://github.com/flutter/flutter/projects/29 for more info.
|
// See https://github.com/flutter/flutter/projects/29 for more info.
|
||||||
|
|
||||||
class SettingsGroupHeader extends StatelessWidget {
|
class SettingsGroupHeader extends StatelessWidget {
|
||||||
const SettingsGroupHeader(this.title, {Key key}) : super(key: key);
|
const SettingsGroupHeader(this.title, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ class SettingsGroupHeader extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SettingsGroupFooter extends StatelessWidget {
|
class SettingsGroupFooter extends StatelessWidget {
|
||||||
const SettingsGroupFooter(this.title, {Key key}) : super(key: key);
|
const SettingsGroupFooter(this.title, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
@@ -55,17 +55,16 @@ class SettingsGroupFooter extends StatelessWidget {
|
|||||||
|
|
||||||
class SettingsGroup extends StatelessWidget {
|
class SettingsGroup extends StatelessWidget {
|
||||||
SettingsGroup({
|
SettingsGroup({
|
||||||
@required this.items,
|
required this.items,
|
||||||
this.header,
|
this.header,
|
||||||
this.footer,
|
this.footer,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : assert(items != null),
|
}) : assert(items.isNotEmpty),
|
||||||
assert(items.isNotEmpty),
|
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
final List<SettingsItem> items;
|
final List<SettingsItem> items;
|
||||||
final Widget header;
|
final Widget? header;
|
||||||
final Widget footer;
|
final Widget? footer;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var brightness = CupertinoTheme.brightnessOf(context);
|
var brightness = CupertinoTheme.brightnessOf(context);
|
||||||
@@ -85,7 +84,7 @@ class SettingsGroup extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (header != null) header,
|
if (header != null) header!,
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: CupertinoColors.white,
|
color: CupertinoColors.white,
|
||||||
@@ -105,7 +104,7 @@ class SettingsGroup extends StatelessWidget {
|
|||||||
children: dividedItems,
|
children: dividedItems,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (footer != null) footer,
|
if (footer != null) footer!,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import 'package:veggieseasons/styles.dart';
|
|||||||
typedef SettingsItemCallback = FutureOr<void> Function();
|
typedef SettingsItemCallback = FutureOr<void> Function();
|
||||||
|
|
||||||
class SettingsNavigationIndicator extends StatelessWidget {
|
class SettingsNavigationIndicator extends StatelessWidget {
|
||||||
const SettingsNavigationIndicator({Key key}) : super(key: key);
|
const SettingsNavigationIndicator({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -30,12 +30,11 @@ class SettingsNavigationIndicator extends StatelessWidget {
|
|||||||
|
|
||||||
class SettingsIcon extends StatelessWidget {
|
class SettingsIcon extends StatelessWidget {
|
||||||
const SettingsIcon({
|
const SettingsIcon({
|
||||||
@required this.icon,
|
required this.icon,
|
||||||
this.foregroundColor = CupertinoColors.white,
|
this.foregroundColor = CupertinoColors.white,
|
||||||
this.backgroundColor = CupertinoColors.black,
|
this.backgroundColor = CupertinoColors.black,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : assert(icon != null),
|
}) : super(key: key);
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
final Color backgroundColor;
|
final Color backgroundColor;
|
||||||
final Color foregroundColor;
|
final Color foregroundColor;
|
||||||
@@ -61,20 +60,19 @@ class SettingsIcon extends StatelessWidget {
|
|||||||
|
|
||||||
class SettingsItem extends StatefulWidget {
|
class SettingsItem extends StatefulWidget {
|
||||||
const SettingsItem({
|
const SettingsItem({
|
||||||
@required this.label,
|
required this.label,
|
||||||
this.icon,
|
this.icon,
|
||||||
this.content,
|
this.content,
|
||||||
this.subtitle,
|
this.subtitle,
|
||||||
this.onPress,
|
this.onPress,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : assert(label != null),
|
}) : super(key: key);
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
final String label;
|
final String label;
|
||||||
final Widget icon;
|
final Widget? icon;
|
||||||
final Widget content;
|
final Widget? content;
|
||||||
final String subtitle;
|
final String? subtitle;
|
||||||
final SettingsItemCallback onPress;
|
final SettingsItemCallback? onPress;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => SettingsItemState();
|
State<StatefulWidget> createState() => SettingsItemState();
|
||||||
@@ -97,7 +95,7 @@ class SettingsItemState extends State<SettingsItem> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
pressed = true;
|
pressed = true;
|
||||||
});
|
});
|
||||||
await widget.onPress();
|
await widget.onPress!();
|
||||||
Future.delayed(
|
Future.delayed(
|
||||||
const Duration(milliseconds: 150),
|
const Duration(milliseconds: 150),
|
||||||
() {
|
() {
|
||||||
@@ -138,7 +136,7 @@ class SettingsItemState extends State<SettingsItem> {
|
|||||||
style: themeData.textTheme.textStyle),
|
style: themeData.textTheme.textStyle),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
widget.subtitle,
|
widget.subtitle!,
|
||||||
style: Styles.settingsItemSubtitleText(themeData),
|
style: Styles.settingsItemSubtitleText(themeData),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import 'package:veggieseasons/styles.dart';
|
|||||||
/// Presents a series of trivia questions about a particular widget, and tracks
|
/// Presents a series of trivia questions about a particular widget, and tracks
|
||||||
/// the user's score.
|
/// the user's score.
|
||||||
class TriviaView extends StatefulWidget {
|
class TriviaView extends StatefulWidget {
|
||||||
final int id;
|
final int? id;
|
||||||
final String restorationId;
|
final String? restorationId;
|
||||||
|
|
||||||
const TriviaView({this.id, this.restorationId, Key key}) : super(key: key);
|
const TriviaView({this.id, this.restorationId, Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_TriviaViewState createState() => _TriviaViewState();
|
_TriviaViewState createState() => _TriviaViewState();
|
||||||
@@ -26,10 +26,10 @@ enum PlayerStatus {
|
|||||||
|
|
||||||
class _TriviaViewState extends State<TriviaView> with RestorationMixin {
|
class _TriviaViewState extends State<TriviaView> with RestorationMixin {
|
||||||
/// Current app state. This is used to fetch veggie data.
|
/// Current app state. This is used to fetch veggie data.
|
||||||
AppState appState;
|
late AppState appState;
|
||||||
|
|
||||||
/// The veggie trivia about which to show.
|
/// The veggie trivia about which to show.
|
||||||
Veggie veggie;
|
late Veggie veggie;
|
||||||
|
|
||||||
/// Index of the current trivia question.
|
/// Index of the current trivia question.
|
||||||
RestorableInt triviaIndex = RestorableInt(0);
|
RestorableInt triviaIndex = RestorableInt(0);
|
||||||
@@ -45,10 +45,10 @@ class _TriviaViewState extends State<TriviaView> with RestorationMixin {
|
|||||||
_RestorablePlayerStatus(PlayerStatus.readyToAnswer);
|
_RestorablePlayerStatus(PlayerStatus.readyToAnswer);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get restorationId => widget.restorationId;
|
String? get restorationId => widget.restorationId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void restoreState(RestorationBucket oldBucket, bool initialRestore) {
|
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||||
registerForRestoration(triviaIndex, 'index');
|
registerForRestoration(triviaIndex, 'index');
|
||||||
registerForRestoration(score, 'score');
|
registerForRestoration(score, 'score');
|
||||||
registerForRestoration(status, 'status');
|
registerForRestoration(status, 'status');
|
||||||
@@ -234,7 +234,7 @@ class _RestorablePlayerStatus extends RestorableValue<PlayerStatus> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PlayerStatus fromPrimitives(Object data) {
|
PlayerStatus fromPrimitives(Object? data) {
|
||||||
return PlayerStatus.values[data as int];
|
return PlayerStatus.values[data as int];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ class _RestorablePlayerStatus extends RestorableValue<PlayerStatus> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateValue(PlayerStatus oldValue) {
|
void didUpdateValue(PlayerStatus? oldValue) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ class FrostyBackground extends StatelessWidget {
|
|||||||
this.color,
|
this.color,
|
||||||
this.intensity = 25,
|
this.intensity = 25,
|
||||||
this.child,
|
this.child,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final Color color;
|
final Color? color;
|
||||||
final double intensity;
|
final double intensity;
|
||||||
final Widget child;
|
final Widget? child;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -41,23 +41,17 @@ class FrostyBackground extends StatelessWidget {
|
|||||||
/// elevation and invoking an optional [onPressed] callback.
|
/// elevation and invoking an optional [onPressed] callback.
|
||||||
class PressableCard extends StatefulWidget {
|
class PressableCard extends StatefulWidget {
|
||||||
const PressableCard({
|
const PressableCard({
|
||||||
@required this.child,
|
required this.child,
|
||||||
this.borderRadius = const BorderRadius.all(Radius.circular(5)),
|
this.borderRadius = const BorderRadius.all(Radius.circular(5)),
|
||||||
this.upElevation = 2,
|
this.upElevation = 2,
|
||||||
this.downElevation = 0,
|
this.downElevation = 0,
|
||||||
this.shadowColor = CupertinoColors.black,
|
this.shadowColor = CupertinoColors.black,
|
||||||
this.duration = const Duration(milliseconds: 100),
|
this.duration = const Duration(milliseconds: 100),
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : assert(child != null),
|
}) : super(key: key);
|
||||||
assert(borderRadius != null),
|
|
||||||
assert(upElevation != null),
|
|
||||||
assert(downElevation != null),
|
|
||||||
assert(shadowColor != null),
|
|
||||||
assert(duration != null),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
final VoidCallback onPressed;
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
@@ -84,7 +78,7 @@ class _PressableCardState extends State<PressableCard> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() => cardIsDown = false);
|
setState(() => cardIsDown = false);
|
||||||
if (widget.onPressed != null) {
|
if (widget.onPressed != null) {
|
||||||
widget.onPressed();
|
widget.onPressed!();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onTapDown: (details) => setState(() => cardIsDown = true),
|
onTapDown: (details) => setState(() => cardIsDown = true),
|
||||||
@@ -107,7 +101,7 @@ class _PressableCardState extends State<PressableCard> {
|
|||||||
|
|
||||||
class VeggieCard extends StatelessWidget {
|
class VeggieCard extends StatelessWidget {
|
||||||
const VeggieCard(this.veggie, this.isInSeason, this.isPreferredCategory,
|
const VeggieCard(this.veggie, this.isInSeason, this.isPreferredCategory,
|
||||||
{Key key})
|
{Key? key})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
/// Veggie to be displayed by the card.
|
/// Veggie to be displayed by the card.
|
||||||
|
|||||||
@@ -8,17 +8,17 @@ import 'package:veggieseasons/screens/details.dart';
|
|||||||
import 'package:veggieseasons/styles.dart';
|
import 'package:veggieseasons/styles.dart';
|
||||||
|
|
||||||
class ZoomClipAssetImage extends StatelessWidget {
|
class ZoomClipAssetImage extends StatelessWidget {
|
||||||
const ZoomClipAssetImage(
|
const ZoomClipAssetImage({
|
||||||
{@required this.zoom,
|
required this.zoom,
|
||||||
this.height,
|
this.height,
|
||||||
this.width,
|
this.width,
|
||||||
@required this.imageAsset,
|
required this.imageAsset,
|
||||||
Key key})
|
Key? key,
|
||||||
: super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final double zoom;
|
final double zoom;
|
||||||
final double height;
|
final double? height;
|
||||||
final double width;
|
final double? width;
|
||||||
final String imageAsset;
|
final String imageAsset;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -30,8 +30,8 @@ class ZoomClipAssetImage extends StatelessWidget {
|
|||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
child: OverflowBox(
|
child: OverflowBox(
|
||||||
maxHeight: height * zoom,
|
maxHeight: height! * zoom,
|
||||||
maxWidth: width * zoom,
|
maxWidth: width! * zoom,
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
imageAsset,
|
imageAsset,
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.fill,
|
||||||
@@ -45,7 +45,7 @@ class ZoomClipAssetImage extends StatelessWidget {
|
|||||||
class VeggieHeadline extends StatelessWidget {
|
class VeggieHeadline extends StatelessWidget {
|
||||||
final Veggie veggie;
|
final Veggie veggie;
|
||||||
|
|
||||||
const VeggieHeadline(this.veggie, {Key key}) : super(key: key);
|
const VeggieHeadline(this.veggie, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
List<Widget> _buildSeasonDots(List<Season> seasons) {
|
List<Widget> _buildSeasonDots(List<Season> seasons) {
|
||||||
var widgets = <Widget>[];
|
var widgets = <Widget>[];
|
||||||
|
|||||||
@@ -19,4 +19,4 @@ SPEC CHECKSUMS:
|
|||||||
|
|
||||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||||
|
|
||||||
COCOAPODS: 1.10.1
|
COCOAPODS: 1.11.0
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ packages:
|
|||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.1"
|
version: "2.8.2"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -35,7 +35,7 @@ packages:
|
|||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.2.0"
|
||||||
charcode:
|
charcode:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -162,7 +162,7 @@ packages:
|
|||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.10"
|
version: "0.12.11"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -239,7 +239,7 @@ packages:
|
|||||||
name: provider
|
name: provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "6.0.1"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -328,7 +328,7 @@ packages:
|
|||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.2"
|
version: "0.4.3"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ description: An iOS app that shows the fruits and veggies currently in season.
|
|||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.5.0 <3.0.0"
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
@@ -13,7 +13,7 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
font_awesome_flutter: ^9.0.0
|
font_awesome_flutter: ^9.0.0
|
||||||
intl: ^0.17.0
|
intl: ^0.17.0
|
||||||
provider: ^5.0.0
|
provider: ^6.0.1
|
||||||
shared_preferences: ^2.0.5
|
shared_preferences: ^2.0.5
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user