Skip to content

Commit 858641d

Browse files
authored
Merge pull request #378 from freddyc2003/master
[#306] Create text prompt for empty screens
2 parents 120052c + 043fa29 commit 858641d

File tree

5 files changed

+256
-222
lines changed

5 files changed

+256
-222
lines changed

lib/l10n/app_en.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,5 +665,7 @@
665665
"swiss_ball": "Swiss Ball",
666666
"triceps": "Triceps",
667667
"until_failure": "Until Failure",
668-
"none__bodyweight_exercise_": "none (bodyweight exercise)"
668+
"none__bodyweight_exercise_": "none (bodyweight exercise)",
669+
"textPromptTitle": "Ready to start?",
670+
"textPromptSubheading": "Press the action button to begin"
669671
}

lib/widgets/core/text_prompt.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
3+
4+
class TextPrompt extends StatelessWidget {
5+
@override
6+
Widget build(BuildContext context) {
7+
return Center(
8+
child: Column(
9+
mainAxisAlignment: MainAxisAlignment.center,
10+
children: [
11+
Text(
12+
AppLocalizations.of(context).textPromptTitle,
13+
style: Theme.of(context).textTheme.headlineMedium,
14+
),
15+
Padding(
16+
padding: EdgeInsets.only(top: 12),
17+
child: Text(AppLocalizations.of(context).textPromptSubheading),
18+
),
19+
],
20+
),
21+
);
22+
}
23+
}

lib/widgets/gallery/overview.dart

Lines changed: 70 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import 'package:provider/provider.dart';
2424
import 'package:wger/helpers/platform.dart';
2525
import 'package:wger/providers/gallery.dart';
2626
import 'package:wger/screens/form_screen.dart';
27+
import 'package:wger/widgets/core/text_prompt.dart';
2728

2829
import 'forms.dart';
2930

@@ -38,77 +39,79 @@ class Gallery extends StatelessWidget {
3839
padding: const EdgeInsets.all(5),
3940
child: RefreshIndicator(
4041
onRefresh: () => provider.fetchAndSetGallery(),
41-
child: MasonryGridView.count(
42-
crossAxisCount: 2,
43-
mainAxisSpacing: 5,
44-
crossAxisSpacing: 5,
45-
itemCount: provider.images.length,
46-
itemBuilder: (context, index) {
47-
final currentImage = provider.images[index];
42+
child: provider.images.length == 0
43+
? TextPrompt()
44+
: MasonryGridView.count(
45+
crossAxisCount: 2,
46+
mainAxisSpacing: 5,
47+
crossAxisSpacing: 5,
48+
itemCount: provider.images.length,
49+
itemBuilder: (context, index) {
50+
final currentImage = provider.images[index];
4851

49-
return GestureDetector(
50-
onTap: () {
51-
showModalBottomSheet(
52-
builder: (context) => Container(
53-
key: Key('image-${currentImage.id}-detail'),
54-
padding: const EdgeInsets.all(10),
55-
color: Colors.white,
56-
child: Column(
57-
children: [
58-
Text(
59-
DateFormat.yMd(Localizations.localeOf(context).languageCode)
60-
.format(currentImage.date),
61-
style: Theme.of(context).textTheme.headline5,
62-
),
63-
Expanded(
64-
child: Image.network(currentImage.url!),
65-
),
66-
Padding(
67-
padding: const EdgeInsets.symmetric(vertical: 8),
68-
child: Text(currentImage.description),
69-
),
70-
Row(
71-
mainAxisAlignment: MainAxisAlignment.center,
72-
children: [
73-
IconButton(
74-
icon: const Icon(Icons.delete),
75-
onPressed: () {
76-
Provider.of<GalleryProvider>(context, listen: false)
77-
.deleteImage(currentImage);
78-
Navigator.of(context).pop();
79-
}),
80-
if (!isDesktop)
81-
IconButton(
82-
icon: const Icon(Icons.edit),
83-
onPressed: () {
84-
Navigator.pushNamed(
85-
context,
86-
FormScreen.routeName,
87-
arguments: FormScreenArguments(
88-
AppLocalizations.of(context).edit,
89-
ImageForm(currentImage),
90-
hasListView: true,
91-
),
92-
);
93-
},
52+
return GestureDetector(
53+
onTap: () {
54+
showModalBottomSheet(
55+
builder: (context) => Container(
56+
key: Key('image-${currentImage.id}-detail'),
57+
padding: const EdgeInsets.all(10),
58+
color: Colors.white,
59+
child: Column(
60+
children: [
61+
Text(
62+
DateFormat.yMd(Localizations.localeOf(context).languageCode)
63+
.format(currentImage.date),
64+
style: Theme.of(context).textTheme.headline5,
9465
),
95-
],
96-
)
97-
],
66+
Expanded(
67+
child: Image.network(currentImage.url!),
68+
),
69+
Padding(
70+
padding: const EdgeInsets.symmetric(vertical: 8),
71+
child: Text(currentImage.description),
72+
),
73+
Row(
74+
mainAxisAlignment: MainAxisAlignment.center,
75+
children: [
76+
IconButton(
77+
icon: const Icon(Icons.delete),
78+
onPressed: () {
79+
Provider.of<GalleryProvider>(context, listen: false)
80+
.deleteImage(currentImage);
81+
Navigator.of(context).pop();
82+
}),
83+
if (!isDesktop)
84+
IconButton(
85+
icon: const Icon(Icons.edit),
86+
onPressed: () {
87+
Navigator.pushNamed(
88+
context,
89+
FormScreen.routeName,
90+
arguments: FormScreenArguments(
91+
AppLocalizations.of(context).edit,
92+
ImageForm(currentImage),
93+
hasListView: true,
94+
),
95+
);
96+
},
97+
),
98+
],
99+
)
100+
],
101+
),
102+
),
103+
context: context,
104+
);
105+
},
106+
child: FadeInImage(
107+
key: Key('image-${currentImage.id}'),
108+
placeholder: const AssetImage('assets/images/placeholder.png'),
109+
image: NetworkImage(currentImage.url!),
110+
fit: BoxFit.cover,
98111
),
99-
),
100-
context: context,
101-
);
102-
},
103-
child: FadeInImage(
104-
key: Key('image-${currentImage.id}'),
105-
placeholder: const AssetImage('assets/images/placeholder.png'),
106-
image: NetworkImage(currentImage.url!),
107-
fit: BoxFit.cover,
112+
);
113+
},
108114
),
109-
);
110-
},
111-
),
112115
),
113116
);
114117
}

lib/widgets/nutrition/nutritional_plans_list.dart

Lines changed: 80 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
2121
import 'package:intl/intl.dart';
2222
import 'package:wger/providers/nutrition.dart';
2323
import 'package:wger/screens/nutritional_plan_screen.dart';
24+
import 'package:wger/widgets/core/text_prompt.dart';
2425

2526
class NutritionalPlansList extends StatelessWidget {
2627
final NutritionPlansProvider _nutritionProvider;
@@ -31,87 +32,89 @@ class NutritionalPlansList extends StatelessWidget {
3132
Widget build(BuildContext context) {
3233
return RefreshIndicator(
3334
onRefresh: () => _nutritionProvider.fetchAndSetAllPlansSparse(),
34-
child: ListView.builder(
35-
padding: const EdgeInsets.all(10.0),
36-
itemCount: _nutritionProvider.items.length,
37-
itemBuilder: (context, index) {
38-
final currentPlan = _nutritionProvider.items[index];
39-
return Dismissible(
40-
key: Key(currentPlan.id.toString()),
41-
confirmDismiss: (direction) async {
42-
// Delete workout from DB
43-
final bool? res = await showDialog(
44-
context: context,
45-
builder: (BuildContext contextDialog) {
46-
return AlertDialog(
47-
content: Text(
48-
AppLocalizations.of(context).confirmDelete(currentPlan.description),
49-
),
50-
actions: [
51-
TextButton(
52-
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
53-
onPressed: () => Navigator.of(contextDialog).pop(),
54-
),
55-
TextButton(
56-
child: Text(
57-
AppLocalizations.of(context).delete,
58-
style: TextStyle(color: Theme.of(context).errorColor),
59-
),
60-
onPressed: () {
61-
// Confirmed, delete the workout
62-
_nutritionProvider.deletePlan(currentPlan.id!);
35+
child: _nutritionProvider.items.length == 0
36+
? TextPrompt()
37+
: ListView.builder(
38+
padding: const EdgeInsets.all(10.0),
39+
itemCount: _nutritionProvider.items.length,
40+
itemBuilder: (context, index) {
41+
final currentPlan = _nutritionProvider.items[index];
42+
return Dismissible(
43+
key: Key(currentPlan.id.toString()),
44+
confirmDismiss: (direction) async {
45+
// Delete workout from DB
46+
final bool? res = await showDialog(
47+
context: context,
48+
builder: (BuildContext contextDialog) {
49+
return AlertDialog(
50+
content: Text(
51+
AppLocalizations.of(context).confirmDelete(currentPlan.description),
52+
),
53+
actions: [
54+
TextButton(
55+
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
56+
onPressed: () => Navigator.of(contextDialog).pop(),
57+
),
58+
TextButton(
59+
child: Text(
60+
AppLocalizations.of(context).delete,
61+
style: TextStyle(color: Theme.of(context).errorColor),
62+
),
63+
onPressed: () {
64+
// Confirmed, delete the workout
65+
_nutritionProvider.deletePlan(currentPlan.id!);
6366

64-
// Close the popup
65-
Navigator.of(contextDialog).pop();
67+
// Close the popup
68+
Navigator.of(contextDialog).pop();
6669

67-
// and inform the user
68-
ScaffoldMessenger.of(context).showSnackBar(
69-
SnackBar(
70-
content: Text(
71-
AppLocalizations.of(context).successfullyDeleted,
72-
textAlign: TextAlign.center,
73-
),
70+
// and inform the user
71+
ScaffoldMessenger.of(context).showSnackBar(
72+
SnackBar(
73+
content: Text(
74+
AppLocalizations.of(context).successfullyDeleted,
75+
textAlign: TextAlign.center,
76+
),
77+
),
78+
);
79+
},
7480
),
75-
);
76-
},
77-
),
78-
],
79-
);
80-
});
81-
return res;
82-
},
83-
background: Container(
84-
color: Theme.of(context).errorColor,
85-
alignment: Alignment.centerRight,
86-
padding: const EdgeInsets.only(right: 20),
87-
margin: const EdgeInsets.symmetric(
88-
horizontal: 4,
89-
vertical: 4,
90-
),
91-
child: const Icon(
92-
Icons.delete,
93-
color: Colors.white,
94-
),
95-
),
96-
direction: DismissDirection.endToStart,
97-
child: Card(
98-
child: ListTile(
99-
onTap: () {
100-
Navigator.of(context).pushNamed(
101-
NutritionalPlanScreen.routeName,
102-
arguments: currentPlan,
103-
);
104-
},
105-
title: Text(currentPlan.getLabel(context)),
106-
subtitle: Text(
107-
DateFormat.yMd(Localizations.localeOf(context).languageCode)
108-
.format(currentPlan.creationDate),
109-
),
110-
),
81+
],
82+
);
83+
});
84+
return res;
85+
},
86+
background: Container(
87+
color: Theme.of(context).errorColor,
88+
alignment: Alignment.centerRight,
89+
padding: const EdgeInsets.only(right: 20),
90+
margin: const EdgeInsets.symmetric(
91+
horizontal: 4,
92+
vertical: 4,
93+
),
94+
child: const Icon(
95+
Icons.delete,
96+
color: Colors.white,
97+
),
98+
),
99+
direction: DismissDirection.endToStart,
100+
child: Card(
101+
child: ListTile(
102+
onTap: () {
103+
Navigator.of(context).pushNamed(
104+
NutritionalPlanScreen.routeName,
105+
arguments: currentPlan,
106+
);
107+
},
108+
title: Text(currentPlan.getLabel(context)),
109+
subtitle: Text(
110+
DateFormat.yMd(Localizations.localeOf(context).languageCode)
111+
.format(currentPlan.creationDate),
112+
),
113+
),
114+
),
115+
);
116+
},
111117
),
112-
);
113-
},
114-
),
115118
);
116119
}
117120
}

0 commit comments

Comments
 (0)