mirror of
https://github.com/flutter/samples.git
synced 2026-03-21 20:08:16 +00:00
Flutter 3.29 beta (#2571)
This commit is contained in:
@@ -28,9 +28,10 @@ class AppState extends ChangeNotifier {
|
||||
|
||||
Veggie getVeggie(int? id) => _veggies.singleWhere((v) => v.id == id);
|
||||
|
||||
List<Veggie> searchVeggies(String? terms) => _veggies
|
||||
.where((v) => v.name.toLowerCase().contains(terms!.toLowerCase()))
|
||||
.toList();
|
||||
List<Veggie> searchVeggies(String? terms) =>
|
||||
_veggies
|
||||
.where((v) => v.name.toLowerCase().contains(terms!.toLowerCase()))
|
||||
.toList();
|
||||
|
||||
void setFavorite(int? id, bool isFavorite) {
|
||||
var veggie = getVeggie(id);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -66,8 +66,10 @@ class Preferences extends ChangeNotifier {
|
||||
|
||||
// Store preferred categories as a comma-separated string containing their
|
||||
// indices.
|
||||
await prefs.setString(_preferredCategoriesKey,
|
||||
_preferredCategories.map((c) => c.index.toString()).join(','));
|
||||
await prefs.setString(
|
||||
_preferredCategoriesKey,
|
||||
_preferredCategories.map((c) => c.index.toString()).join(','),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _loadFromSharedPrefs() async {
|
||||
|
||||
@@ -25,12 +25,7 @@ enum VeggieCategory {
|
||||
vegetable,
|
||||
}
|
||||
|
||||
enum Season {
|
||||
winter,
|
||||
spring,
|
||||
summer,
|
||||
autumn,
|
||||
}
|
||||
enum Season { winter, spring, summer, autumn }
|
||||
|
||||
class Trivia {
|
||||
final String question;
|
||||
|
||||
@@ -30,12 +30,7 @@ void main() {
|
||||
]);
|
||||
setupWindow();
|
||||
|
||||
runApp(
|
||||
const RootRestorationScope(
|
||||
restorationId: 'root',
|
||||
child: VeggieApp(),
|
||||
),
|
||||
);
|
||||
runApp(const RootRestorationScope(restorationId: 'root', child: VeggieApp()));
|
||||
}
|
||||
|
||||
const double windowWidth = 480;
|
||||
@@ -47,11 +42,13 @@ void setupWindow() {
|
||||
setWindowMinSize(const Size(windowWidth, windowHeight));
|
||||
setWindowMaxSize(const Size(windowWidth, windowHeight));
|
||||
getCurrentScreen().then((screen) {
|
||||
setWindowFrame(Rect.fromCenter(
|
||||
center: screen!.frame.center,
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
));
|
||||
setWindowFrame(
|
||||
Rect.fromCenter(
|
||||
center: screen!.frame.center,
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -87,12 +84,8 @@ class _VeggieAppState extends State<VeggieApp> with RestorationMixin {
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider.value(
|
||||
value: _appState.value,
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => Preferences()..load(),
|
||||
),
|
||||
ChangeNotifierProvider.value(value: _appState.value),
|
||||
ChangeNotifierProvider(create: (_) => Preferences()..load()),
|
||||
],
|
||||
child: CupertinoApp.router(
|
||||
theme: Styles.veggieThemeData,
|
||||
@@ -142,9 +135,7 @@ class _VeggieAppState extends State<VeggieApp> with RestorationMixin {
|
||||
child: const ListScreen(restorationId: 'list'),
|
||||
);
|
||||
},
|
||||
routes: [
|
||||
_buildDetailsRoute(),
|
||||
],
|
||||
routes: [_buildDetailsRoute()],
|
||||
),
|
||||
GoRoute(
|
||||
path: '/favorites',
|
||||
@@ -155,9 +146,7 @@ class _VeggieAppState extends State<VeggieApp> with RestorationMixin {
|
||||
child: const FavoritesScreen(restorationId: 'favorites'),
|
||||
);
|
||||
},
|
||||
routes: [
|
||||
_buildDetailsRoute(),
|
||||
],
|
||||
routes: [_buildDetailsRoute()],
|
||||
),
|
||||
GoRoute(
|
||||
path: '/search',
|
||||
@@ -168,9 +157,7 @@ class _VeggieAppState extends State<VeggieApp> with RestorationMixin {
|
||||
child: const SearchScreen(restorationId: 'search'),
|
||||
);
|
||||
},
|
||||
routes: [
|
||||
_buildDetailsRoute(),
|
||||
],
|
||||
routes: [_buildDetailsRoute()],
|
||||
),
|
||||
GoRoute(
|
||||
path: '/settings',
|
||||
@@ -187,7 +174,8 @@ class _VeggieAppState extends State<VeggieApp> with RestorationMixin {
|
||||
path: 'categories',
|
||||
pageBuilder: (context, state) {
|
||||
return VeggieCategorySettingsScreen.pageBuilder(
|
||||
context);
|
||||
context,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
@@ -217,10 +205,7 @@ class _VeggieAppState extends State<VeggieApp> with RestorationMixin {
|
||||
final veggieId = int.parse(state.pathParameters['id']!);
|
||||
return CupertinoPage(
|
||||
restorationId: 'route.details',
|
||||
child: DetailsScreen(
|
||||
id: veggieId,
|
||||
restorationId: 'details',
|
||||
),
|
||||
child: DetailsScreen(id: veggieId, restorationId: 'details'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -62,10 +62,7 @@ class ServingInfoChart extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text(
|
||||
'Calories',
|
||||
style: Styles.detailsServingLabelText(themeData),
|
||||
),
|
||||
Text('Calories', style: Styles.detailsServingLabelText(themeData)),
|
||||
const Spacer(),
|
||||
Text(
|
||||
'${veggie.caloriesPerServing} kCal',
|
||||
@@ -78,30 +75,18 @@ class ServingInfoChart extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text(
|
||||
'Vitamin A',
|
||||
style: Styles.detailsServingLabelText(themeData),
|
||||
),
|
||||
Text('Vitamin A', style: Styles.detailsServingLabelText(themeData)),
|
||||
const Spacer(),
|
||||
_buildVitaminText(
|
||||
veggie.vitaminAPercentage,
|
||||
prefs.desiredCalories,
|
||||
),
|
||||
_buildVitaminText(veggie.vitaminAPercentage, prefs.desiredCalories),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text(
|
||||
'Vitamin C',
|
||||
style: Styles.detailsServingLabelText(themeData),
|
||||
),
|
||||
Text('Vitamin C', style: Styles.detailsServingLabelText(themeData)),
|
||||
const Spacer(),
|
||||
_buildVitaminText(
|
||||
veggie.vitaminCPercentage,
|
||||
prefs.desiredCalories,
|
||||
),
|
||||
_buildVitaminText(veggie.vitaminCPercentage, prefs.desiredCalories),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
@@ -139,20 +124,14 @@ class InfoView extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
veggie.name,
|
||||
style: Styles.detailsTitleText(themeData),
|
||||
),
|
||||
Text(veggie.name, style: Styles.detailsTitleText(themeData)),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
veggie.shortDescription,
|
||||
style: CupertinoTheme.of(context).textTheme.textStyle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Seasons',
|
||||
style: Styles.detailsServingLabelText(themeData),
|
||||
),
|
||||
Text('Seasons', style: Styles.detailsServingLabelText(themeData)),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
@@ -164,17 +143,19 @@ class InfoView extends StatelessWidget {
|
||||
children: [
|
||||
Icon(
|
||||
Styles.seasonIconData[season],
|
||||
color: veggie.seasons.contains(season)
|
||||
? Styles.seasonColors[season]
|
||||
: const Color.fromRGBO(128, 128, 128, 1),
|
||||
color:
|
||||
veggie.seasons.contains(season)
|
||||
? Styles.seasonColors[season]
|
||||
: const Color.fromRGBO(128, 128, 128, 1),
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
season.name.characters.first.toUpperCase() +
|
||||
season.name.characters.skip(1).string,
|
||||
style: Styles.minorText(CupertinoTheme.of(context))
|
||||
.copyWith(fontSize: 11),
|
||||
style: Styles.minorText(
|
||||
CupertinoTheme.of(context),
|
||||
).copyWith(fontSize: 11),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -227,37 +208,37 @@ class DetailsScreen extends StatelessWidget {
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ShareButton(
|
||||
() {
|
||||
showCupertinoModalPopup<void>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return CupertinoActionSheet(
|
||||
title: Text('Share ${veggie.name}'),
|
||||
message: Text(veggie.shortDescription),
|
||||
actions: [
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
ShareButton(() {
|
||||
showCupertinoModalPopup<void>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return CupertinoActionSheet(
|
||||
title: Text('Share ${veggie.name}'),
|
||||
message: Text(veggie.shortDescription),
|
||||
actions: [
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
const SizedBox(width: 8),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final appState = Provider.of<AppState>(context);
|
||||
final veggie = appState.getVeggie(id);
|
||||
|
||||
return FavoriteButton(
|
||||
() => appState.setFavorite(id, !veggie.isFavorite),
|
||||
veggie.isFavorite,
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Builder(builder: (context) {
|
||||
final appState = Provider.of<AppState>(context);
|
||||
final veggie = appState.getVeggie(id);
|
||||
|
||||
return FavoriteButton(
|
||||
() => appState.setFavorite(id, !veggie.isFavorite),
|
||||
veggie.isFavorite,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -25,25 +25,26 @@ class FavoritesScreen extends StatelessWidget {
|
||||
middle: Text('My Garden'),
|
||||
),
|
||||
child: Center(
|
||||
child: model.favoriteVeggies.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Text(
|
||||
'You haven\'t added any favorite veggies to your garden yet.',
|
||||
style: CupertinoTheme.of(context).textTheme.textStyle,
|
||||
child:
|
||||
model.favoriteVeggies.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Text(
|
||||
'You haven\'t added any favorite veggies to your garden yet.',
|
||||
style: CupertinoTheme.of(context).textTheme.textStyle,
|
||||
),
|
||||
)
|
||||
: ListView(
|
||||
restorationId: 'list',
|
||||
children: [
|
||||
const SizedBox(height: 24),
|
||||
for (Veggie veggie in model.favoriteVeggies)
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 24),
|
||||
child: VeggieHeadline(veggie),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: ListView(
|
||||
restorationId: 'list',
|
||||
children: [
|
||||
const SizedBox(height: 24),
|
||||
for (Veggie veggie in model.favoriteVeggies)
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 24),
|
||||
child: VeggieHeadline(veggie),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -16,16 +16,20 @@ class ListScreen extends StatelessWidget {
|
||||
|
||||
final String? restorationId;
|
||||
|
||||
Widget _generateVeggieCard(Veggie veggie, Preferences prefs,
|
||||
{bool inSeason = true}) {
|
||||
Widget _generateVeggieCard(
|
||||
Veggie veggie,
|
||||
Preferences prefs, {
|
||||
bool inSeason = true,
|
||||
}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 24),
|
||||
child: FutureBuilder<Set<VeggieCategory>>(
|
||||
future: prefs.preferredCategories,
|
||||
builder: (context, snapshot) {
|
||||
final data = snapshot.data ?? <VeggieCategory>{};
|
||||
return VeggieCard(veggie, inSeason, data.contains(veggie.category));
|
||||
}),
|
||||
future: prefs.preferredCategories,
|
||||
builder: (context, snapshot) {
|
||||
final data = snapshot.data ?? <VeggieCategory>{};
|
||||
return VeggieCard(veggie, inSeason, data.contains(veggie.category));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,7 +43,8 @@ class ListScreen extends StatelessWidget {
|
||||
final themeData = CupertinoTheme.of(context);
|
||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle(
|
||||
statusBarBrightness: MediaQuery.platformBrightnessOf(context)),
|
||||
statusBarBrightness: MediaQuery.platformBrightnessOf(context),
|
||||
),
|
||||
child: SafeArea(
|
||||
bottom: false,
|
||||
child: ListView.builder(
|
||||
@@ -49,8 +54,10 @@ class ListScreen extends StatelessWidget {
|
||||
if (index == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 24, 16, 16),
|
||||
child: Text('In season today',
|
||||
style: Styles.headlineText(themeData)),
|
||||
child: Text(
|
||||
'In season today',
|
||||
style: Styles.headlineText(themeData),
|
||||
),
|
||||
);
|
||||
} else if (index <= appState.availableVeggies.length) {
|
||||
return _generateVeggieCard(
|
||||
@@ -60,15 +67,19 @@ class ListScreen extends StatelessWidget {
|
||||
} else if (index <= appState.availableVeggies.length + 1) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 24, 16, 16),
|
||||
child: Text('Not in season',
|
||||
style: Styles.headlineText(themeData)),
|
||||
child: Text(
|
||||
'Not in season',
|
||||
style: Styles.headlineText(themeData),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
var relativeIndex =
|
||||
index - (appState.availableVeggies.length + 2);
|
||||
return _generateVeggieCard(
|
||||
appState.unavailableVeggies[relativeIndex], prefs,
|
||||
inSeason: false);
|
||||
appState.unavailableVeggies[relativeIndex],
|
||||
prefs,
|
||||
inSeason: false,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
@@ -58,10 +58,7 @@ class VeggieCategorySettingsScreen extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
} else {
|
||||
toggle = const CupertinoSwitch(
|
||||
value: false,
|
||||
onChanged: null,
|
||||
);
|
||||
toggle = const CupertinoSwitch(value: false, onChanged: null);
|
||||
}
|
||||
|
||||
tiles.add(
|
||||
@@ -136,9 +133,10 @@ class CalorieSettingsScreen extends StatelessWidget {
|
||||
: Styles.transparentColor,
|
||||
backgroundColor: Styles.transparentColor,
|
||||
),
|
||||
onTap: snapshot.hasData
|
||||
? () => model.setDesiredCalories(cals)
|
||||
: null,
|
||||
onTap:
|
||||
snapshot.hasData
|
||||
? () => model.setDesiredCalories(cals)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -147,12 +145,14 @@ class CalorieSettingsScreen extends StatelessWidget {
|
||||
header: Text(
|
||||
'Available calorie levels'.toUpperCase(),
|
||||
style: Styles.settingsGroupHeaderText(
|
||||
CupertinoTheme.of(context)),
|
||||
CupertinoTheme.of(context),
|
||||
),
|
||||
),
|
||||
footer: Text(
|
||||
'These are used for serving calculations',
|
||||
style: Styles.settingsGroupFooterText(
|
||||
CupertinoTheme.of(context)),
|
||||
CupertinoTheme.of(context),
|
||||
),
|
||||
),
|
||||
children: tiles,
|
||||
);
|
||||
@@ -176,7 +176,9 @@ class SettingsScreen extends StatefulWidget {
|
||||
|
||||
class _SettingsScreenState extends State<SettingsScreen> {
|
||||
CupertinoListTile _buildCaloriesTile(
|
||||
BuildContext context, Preferences prefs) {
|
||||
BuildContext context,
|
||||
Preferences prefs,
|
||||
) {
|
||||
return CupertinoListTile.notched(
|
||||
leading: const SettingsIcon(
|
||||
backgroundColor: CupertinoColors.systemBlue,
|
||||
@@ -198,7 +200,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
}
|
||||
|
||||
CupertinoListTile _buildCategoriesTile(
|
||||
BuildContext context, Preferences prefs) {
|
||||
BuildContext context,
|
||||
Preferences prefs,
|
||||
) {
|
||||
return CupertinoListTile.notched(
|
||||
leading: const SettingsIcon(
|
||||
backgroundColor: CupertinoColors.systemOrange,
|
||||
@@ -211,7 +215,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
}
|
||||
|
||||
CupertinoListTile _buildRestoreDefaultsTile(
|
||||
BuildContext context, Preferences prefs) {
|
||||
BuildContext context,
|
||||
Preferences prefs,
|
||||
) {
|
||||
return CupertinoListTile.notched(
|
||||
leading: const SettingsIcon(
|
||||
backgroundColor: CupertinoColors.systemRed,
|
||||
@@ -221,28 +227,29 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
onTap: () {
|
||||
showCupertinoDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => CupertinoAlertDialog(
|
||||
title: const Text('Are you sure?'),
|
||||
content: const Text(
|
||||
'Are you sure you want to reset the current settings?',
|
||||
),
|
||||
actions: [
|
||||
CupertinoDialogAction(
|
||||
isDestructiveAction: true,
|
||||
child: const Text('Yes'),
|
||||
onPressed: () async {
|
||||
await prefs.restoreDefaults();
|
||||
if (!context.mounted) return;
|
||||
context.pop();
|
||||
},
|
||||
builder:
|
||||
(context) => CupertinoAlertDialog(
|
||||
title: const Text('Are you sure?'),
|
||||
content: const Text(
|
||||
'Are you sure you want to reset the current settings?',
|
||||
),
|
||||
actions: [
|
||||
CupertinoDialogAction(
|
||||
isDestructiveAction: true,
|
||||
child: const Text('Yes'),
|
||||
onPressed: () async {
|
||||
await prefs.restoreDefaults();
|
||||
if (!context.mounted) return;
|
||||
context.pop();
|
||||
},
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
isDefaultAction: true,
|
||||
child: const Text('No'),
|
||||
onPressed: () => context.pop(),
|
||||
),
|
||||
],
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
isDefaultAction: true,
|
||||
child: const Text('No'),
|
||||
onPressed: () => context.pop(),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -253,29 +260,24 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
final prefs = Provider.of<Preferences>(context);
|
||||
|
||||
return CupertinoPageScaffold(
|
||||
backgroundColor:
|
||||
Styles.scaffoldBackground(CupertinoTheme.brightnessOf(context)),
|
||||
backgroundColor: Styles.scaffoldBackground(
|
||||
CupertinoTheme.brightnessOf(context),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
const CupertinoSliverNavigationBar(
|
||||
largeTitle: Text('Settings'),
|
||||
),
|
||||
const CupertinoSliverNavigationBar(largeTitle: Text('Settings')),
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
CupertinoListSection.insetGrouped(
|
||||
children: [
|
||||
_buildCaloriesTile(context, prefs),
|
||||
_buildCategoriesTile(context, prefs),
|
||||
],
|
||||
),
|
||||
CupertinoListSection.insetGrouped(
|
||||
children: [
|
||||
_buildRestoreDefaultsTile(context, prefs),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
delegate: SliverChildListDelegate([
|
||||
CupertinoListSection.insetGrouped(
|
||||
children: [
|
||||
_buildCaloriesTile(context, prefs),
|
||||
_buildCategoriesTile(context, prefs),
|
||||
],
|
||||
),
|
||||
CupertinoListSection.insetGrouped(
|
||||
children: [_buildRestoreDefaultsTile(context, prefs)],
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -302,13 +304,7 @@ class SettingsIcon extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: backgroundColor,
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
icon,
|
||||
color: foregroundColor,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
child: Center(child: Icon(icon, color: foregroundColor, size: 20)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,22 +21,20 @@ abstract class Styles {
|
||||
),
|
||||
);
|
||||
|
||||
static TextStyle headlineText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
static TextStyle headlineText(CupertinoThemeData themeData) => themeData
|
||||
.textTheme
|
||||
.textStyle
|
||||
.copyWith(fontSize: 32, fontWeight: FontWeight.bold);
|
||||
|
||||
static TextStyle minorText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
color: const Color.fromRGBO(128, 128, 128, 1),
|
||||
);
|
||||
static TextStyle minorText(CupertinoThemeData themeData) => themeData
|
||||
.textTheme
|
||||
.textStyle
|
||||
.copyWith(color: const Color.fromRGBO(128, 128, 128, 1));
|
||||
|
||||
static TextStyle headlineName(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
static TextStyle headlineName(CupertinoThemeData themeData) => themeData
|
||||
.textTheme
|
||||
.textStyle
|
||||
.copyWith(fontSize: 24, fontWeight: FontWeight.bold);
|
||||
|
||||
static TextStyle cardTitleText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
@@ -45,26 +43,23 @@ abstract class Styles {
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
|
||||
static TextStyle cardCategoryText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
color: const Color.fromRGBO(255, 255, 255, 0.9),
|
||||
);
|
||||
static TextStyle cardCategoryText(CupertinoThemeData themeData) => themeData
|
||||
.textTheme
|
||||
.textStyle
|
||||
.copyWith(color: const Color.fromRGBO(255, 255, 255, 0.9));
|
||||
|
||||
static TextStyle cardDescriptionText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
color: const Color.fromRGBO(0, 0, 0, 0.9),
|
||||
);
|
||||
|
||||
static TextStyle detailsTitleText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
static TextStyle detailsTitleText(CupertinoThemeData themeData) => themeData
|
||||
.textTheme
|
||||
.textStyle
|
||||
.copyWith(fontSize: 30, fontWeight: FontWeight.bold);
|
||||
|
||||
static TextStyle detailsPreferredCategoryText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
themeData.textTheme.textStyle.copyWith(fontWeight: FontWeight.bold);
|
||||
|
||||
static TextStyle detailsBoldDescriptionText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
@@ -79,24 +74,16 @@ abstract class Styles {
|
||||
);
|
||||
|
||||
static TextStyle detailsServingLabelText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
themeData.textTheme.textStyle.copyWith(fontWeight: FontWeight.bold);
|
||||
|
||||
static TextStyle detailsServingNoteText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontStyle: FontStyle.italic,
|
||||
);
|
||||
themeData.textTheme.textStyle.copyWith(fontStyle: FontStyle.italic);
|
||||
|
||||
static TextStyle triviaFinishedTitleText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontSize: 32,
|
||||
);
|
||||
themeData.textTheme.textStyle.copyWith(fontSize: 32);
|
||||
|
||||
static TextStyle triviaFinishedBigText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontSize: 48,
|
||||
);
|
||||
themeData.textTheme.textStyle.copyWith(fontSize: 48);
|
||||
|
||||
static TextStyle settingsGroupHeaderText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
@@ -126,10 +113,7 @@ abstract class Styles {
|
||||
static const closeButtonPressed = Color(0xff808080);
|
||||
|
||||
static TextStyle settingsItemSubtitleText(CupertinoThemeData themeData) =>
|
||||
themeData.textTheme.textStyle.copyWith(
|
||||
fontSize: 12,
|
||||
letterSpacing: -0.2,
|
||||
);
|
||||
themeData.textTheme.textStyle.copyWith(fontSize: 12, letterSpacing: -0.2);
|
||||
|
||||
static const Color searchCursorColor = Color.fromRGBO(0, 122, 255, 1);
|
||||
|
||||
@@ -224,6 +208,6 @@ abstract class Styles {
|
||||
static const servingInfoBorderColor = Color(0xffb0b0b0);
|
||||
|
||||
static const ColorFilter desaturatedColorFilter =
|
||||
// 222222 is a random color that has low color saturation.
|
||||
ColorFilter.mode(Color(0xff222222), BlendMode.saturation);
|
||||
// 222222 is a random color that has low color saturation.
|
||||
ColorFilter.mode(Color(0xff222222), BlendMode.saturation);
|
||||
}
|
||||
|
||||
@@ -9,10 +9,7 @@ import '../styles.dart';
|
||||
|
||||
/// Partially overlays and then blurs its child's background.
|
||||
class FrostedBox extends StatelessWidget {
|
||||
const FrostedBox({
|
||||
this.child,
|
||||
super.key,
|
||||
});
|
||||
const FrostedBox({this.child, super.key});
|
||||
|
||||
final Widget? child;
|
||||
|
||||
@@ -21,9 +18,7 @@ class FrostedBox extends StatelessWidget {
|
||||
return BackdropFilter(
|
||||
filter: ui.ImageFilter.blur(sigmaX: 10, sigmaY: 10),
|
||||
child: DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
color: Styles.frostedBackground,
|
||||
),
|
||||
decoration: const BoxDecoration(color: Styles.frostedBackground),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
@@ -67,33 +62,35 @@ class _ColorChangingIconState
|
||||
|
||||
@override
|
||||
void forEachTween(TweenVisitor<dynamic> visitor) {
|
||||
_colorTween = visitor(
|
||||
_colorTween,
|
||||
widget.color,
|
||||
(dynamic value) => ColorTween(begin: value as Color?),
|
||||
) as ColorTween?;
|
||||
_colorTween =
|
||||
visitor(
|
||||
_colorTween,
|
||||
widget.color,
|
||||
(dynamic value) => ColorTween(begin: value as Color?),
|
||||
)
|
||||
as ColorTween?;
|
||||
}
|
||||
}
|
||||
|
||||
/// A close button that invokes a callback when pressed.
|
||||
class CloseButton extends _DetailPageButton {
|
||||
const CloseButton(VoidCallback onPressed, {super.key})
|
||||
: super(onPressed, CupertinoIcons.chevron_back);
|
||||
: super(onPressed, CupertinoIcons.chevron_back);
|
||||
}
|
||||
|
||||
/// A share button that invokes a callback when pressed.
|
||||
class ShareButton extends _DetailPageButton {
|
||||
const ShareButton(VoidCallback onPressed, {super.key})
|
||||
: super(onPressed, CupertinoIcons.share);
|
||||
: super(onPressed, CupertinoIcons.share);
|
||||
}
|
||||
|
||||
/// A favorite button that invokes a callback when pressed.
|
||||
class FavoriteButton extends _DetailPageButton {
|
||||
const FavoriteButton(VoidCallback onPressed, bool isFavorite, {super.key})
|
||||
: super(
|
||||
onPressed,
|
||||
isFavorite ? CupertinoIcons.heart_fill : CupertinoIcons.heart,
|
||||
);
|
||||
: super(
|
||||
onPressed,
|
||||
isFavorite ? CupertinoIcons.heart_fill : CupertinoIcons.heart,
|
||||
);
|
||||
}
|
||||
|
||||
class _DetailPageButton extends StatefulWidget {
|
||||
@@ -127,16 +124,15 @@ class _DetailPageButtonState extends State<_DetailPageButton> {
|
||||
child: Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(15)),
|
||||
child: Center(
|
||||
child: ColorChangingIcon(
|
||||
widget.icon,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
color: tapInProgress
|
||||
? Styles.closeButtonPressed
|
||||
: Styles.closeButtonUnpressed,
|
||||
color:
|
||||
tapInProgress
|
||||
? Styles.closeButtonPressed
|
||||
: Styles.closeButtonUnpressed,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -29,21 +29,20 @@ class PressableCard extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
onTap: onPressed,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: borderRadius,
|
||||
child: child,
|
||||
),
|
||||
decoration: BoxDecoration(borderRadius: borderRadius),
|
||||
child: ClipRRect(borderRadius: borderRadius, child: child),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class VeggieCard extends StatelessWidget {
|
||||
const VeggieCard(this.veggie, this.isInSeason, this.isPreferredCategory,
|
||||
{super.key});
|
||||
const VeggieCard(
|
||||
this.veggie,
|
||||
this.isInSeason,
|
||||
this.isPreferredCategory, {
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// Veggie to be displayed by the card.
|
||||
final Veggie veggie;
|
||||
@@ -64,10 +63,7 @@ class VeggieCard extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
veggie.name,
|
||||
style: Styles.cardTitleText(themeData),
|
||||
),
|
||||
Text(veggie.name, style: Styles.cardTitleText(themeData)),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
veggie.shortDescription,
|
||||
@@ -99,9 +95,7 @@ class VeggieCard extends StatelessWidget {
|
||||
fit: BoxFit.cover,
|
||||
colorFilter:
|
||||
isInSeason ? null : Styles.desaturatedColorFilter,
|
||||
image: AssetImage(
|
||||
veggie.imageAssetPath,
|
||||
),
|
||||
image: AssetImage(veggie.imageAssetPath),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -32,10 +32,7 @@ class ZoomClipAssetImage extends StatelessWidget {
|
||||
child: OverflowBox(
|
||||
maxHeight: height! * zoom,
|
||||
maxWidth: width! * zoom,
|
||||
child: Image.asset(
|
||||
imageAsset,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
child: Image.asset(imageAsset, fit: BoxFit.fill),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -96,10 +93,7 @@ class VeggieHeadline extends StatelessWidget {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
veggie.name,
|
||||
style: Styles.headlineName(themeData),
|
||||
),
|
||||
Text(veggie.name, style: Styles.headlineName(themeData)),
|
||||
..._buildSeasonDots(veggie.seasons),
|
||||
],
|
||||
),
|
||||
@@ -109,7 +103,7 @@ class VeggieHeadline extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -40,6 +40,5 @@ class VeggieSeasonsPageRoute<T> extends PageRoute<T> {
|
||||
BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
) =>
|
||||
_page.child;
|
||||
) => _page.child;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ publish_to: none
|
||||
version: 1.2.0
|
||||
|
||||
environment:
|
||||
sdk: ^3.5.0
|
||||
sdk: ^3.7.0-0
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
||||
Reference in New Issue
Block a user