Skip to content

Commit 1135738

Browse files
authored
Merge pull request #272 from its-me-abhishek/main
Added tours for reports page and filter drawer
2 parents 573b69d + 32fe7bd commit 1135738

File tree

6 files changed

+521
-105
lines changed

6 files changed

+521
-105
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:shared_preferences/shared_preferences.dart';
2+
3+
class SaveFilterTour {
4+
Future<SharedPreferences> data = SharedPreferences.getInstance();
5+
6+
void saveFilterTourStatus() async {
7+
final value = await data;
8+
value.setBool('filter_tour', true);
9+
}
10+
11+
Future<bool> getFilterTourStatus() async {
12+
final value = await data;
13+
if (value.containsKey('filter_tour')) {
14+
bool? getData = value.getBool('filter_tour');
15+
return getData!;
16+
} else {
17+
return false;
18+
}
19+
}
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:shared_preferences/shared_preferences.dart';
2+
3+
class SaveReportsTour {
4+
Future<SharedPreferences> data = SharedPreferences.getInstance();
5+
6+
void saveReportsTourStatus() async {
7+
final value = await data;
8+
value.setBool('reports_tour', true);
9+
}
10+
11+
Future<bool> getReportsTourStatus() async {
12+
final value = await data;
13+
if (value.containsKey('reports_tour')) {
14+
bool? getData = value.getBool('reports_tour');
15+
return getData!;
16+
} else {
17+
return false;
18+
}
19+
}
20+
}

lib/drawer/filter_drawer.dart

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,80 @@ import 'package:flutter/material.dart';
44
import 'package:google_fonts/google_fonts.dart';
55

66
import 'package:taskwarrior/config/app_settings.dart';
7+
import 'package:taskwarrior/controller/filter_drawer_tour_controller.dart';
8+
import 'package:taskwarrior/drawer/filter_drawer_tour.dart';
79
import 'package:taskwarrior/model/storage/storage_widget.dart';
810
import 'package:taskwarrior/views/home/home.dart';
911
import 'package:taskwarrior/widgets/project_filter.dart';
1012
import 'package:taskwarrior/widgets/tag_filter.dart';
13+
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
1114

12-
// ignore: must_be_immutable
13-
class FilterDrawer extends StatelessWidget {
14-
FilterDrawer(this.filters, {super.key});
15+
class FilterDrawer extends StatefulWidget {
16+
final Filters filters;
17+
18+
const FilterDrawer(this.filters, {super.key});
19+
20+
@override
21+
// ignore: library_private_types_in_public_api
22+
_FilterDrawerState createState() => _FilterDrawerState();
23+
}
24+
25+
class _FilterDrawerState extends State<FilterDrawer> {
26+
final GlobalKey statusKey = GlobalKey();
27+
final GlobalKey projectsKey = GlobalKey();
28+
final GlobalKey filterTagKey = GlobalKey();
29+
final GlobalKey sortByKey = GlobalKey();
30+
31+
bool isSaved = false;
1532
var tileColor = AppSettings.isDarkMode
1633
? const Color.fromARGB(255, 48, 46, 46)
1734
: const Color.fromARGB(255, 220, 216, 216);
35+
late TutorialCoachMark tutorialCoachMark;
36+
37+
void _initFilterDrawerTour() {
38+
tutorialCoachMark = TutorialCoachMark(
39+
targets: filterDrawer(
40+
statusKey: statusKey,
41+
projectsKey: projectsKey,
42+
filterTagKey: filterTagKey,
43+
sortByKey: sortByKey,
44+
),
45+
colorShadow: Colors.black,
46+
paddingFocus: 10,
47+
opacityShadow: 1.00,
48+
hideSkip: true,
49+
onFinish: () {
50+
SaveFilterTour().saveFilterTourStatus();
51+
},
52+
);
53+
}
54+
55+
void _showFilterDrawerTour() {
56+
Future.delayed(
57+
const Duration(seconds: 2),
58+
() {
59+
SaveFilterTour().getFilterTourStatus().then((value) => {
60+
if (value == false)
61+
{
62+
tutorialCoachMark.show(context: context),
63+
}
64+
else
65+
{
66+
// ignore: avoid_print
67+
print('User has seen this page'),
68+
}
69+
});
70+
},
71+
);
72+
}
73+
74+
@override
75+
void initState() {
76+
super.initState();
77+
_initFilterDrawerTour();
78+
_showFilterDrawerTour();
79+
}
1880

19-
final Filters filters;
2081
@override
2182
Widget build(BuildContext context) {
2283
var storageWidget = StorageWidget.of(context);
@@ -63,6 +124,7 @@ class FilterDrawer extends StatelessWidget {
63124
),
64125
child: ListTile(
65126
title: RichText(
127+
key: statusKey,
66128
maxLines: 2,
67129
text: TextSpan(
68130
children: <TextSpan>[
@@ -77,7 +139,9 @@ class FilterDrawer extends StatelessWidget {
77139
),
78140
),
79141
TextSpan(
80-
text: filters.pendingFilter ? 'pending' : 'completed',
142+
text: widget.filters.pendingFilter
143+
? 'pending'
144+
: 'completed',
81145
style: GoogleFonts.poppins(
82146
fontSize: 15,
83147
color: AppSettings.isDarkMode
@@ -88,7 +152,7 @@ class FilterDrawer extends StatelessWidget {
88152
],
89153
),
90154
),
91-
onTap: filters.togglePendingFilter,
155+
onTap: widget.filters.togglePendingFilter,
92156
textColor: AppSettings.isDarkMode
93157
? Colors.white
94158
: Color.fromARGB(255, 48, 46, 46),
@@ -98,6 +162,7 @@ class FilterDrawer extends StatelessWidget {
98162
color: Color.fromARGB(0, 48, 46, 46),
99163
),
100164
Container(
165+
key: projectsKey,
101166
width: MediaQuery.of(context).size.width * 1,
102167
// padding: const EdgeInsets.all(12),
103168
decoration: BoxDecoration(
@@ -106,15 +171,16 @@ class FilterDrawer extends StatelessWidget {
106171
border: Border.all(color: Colors.grey.shade300),
107172
),
108173
child: ProjectsColumn(
109-
filters.projects,
110-
filters.projectFilter,
111-
filters.toggleProjectFilter,
174+
widget.filters.projects,
175+
widget.filters.projectFilter,
176+
widget.filters.toggleProjectFilter,
112177
),
113178
),
114179
const Divider(
115180
color: Color.fromARGB(0, 48, 46, 46),
116181
),
117182
Container(
183+
key: filterTagKey,
118184
width: MediaQuery.of(context).size.width * 1,
119185
padding: const EdgeInsets.all(12),
120186
decoration: BoxDecoration(
@@ -146,7 +212,7 @@ class FilterDrawer extends StatelessWidget {
146212
),
147213
Padding(
148214
padding: const EdgeInsets.symmetric(horizontal: 8.0),
149-
child: TagFiltersWrap(filters.tagFilters),
215+
child: TagFiltersWrap(widget.filters.tagFilters),
150216
),
151217
const Divider(
152218
color: Color.fromARGB(0, 48, 46, 46),
@@ -158,6 +224,7 @@ class FilterDrawer extends StatelessWidget {
158224
color: Color.fromARGB(0, 48, 46, 46),
159225
),
160226
Container(
227+
key: sortByKey,
161228
width: MediaQuery.of(context).size.width * 1,
162229
padding: const EdgeInsets.all(12),
163230
decoration: BoxDecoration(

lib/drawer/filter_drawer_tour.dart

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:google_fonts/google_fonts.dart';
3+
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
4+
5+
List<TargetFocus> filterDrawer({
6+
required GlobalKey statusKey,
7+
required GlobalKey projectsKey,
8+
required GlobalKey filterTagKey,
9+
required GlobalKey sortByKey,
10+
}) {
11+
List<TargetFocus> targets = [];
12+
13+
// statusKey
14+
targets.add(
15+
TargetFocus(
16+
keyTarget: statusKey,
17+
alignSkip: Alignment.topRight,
18+
radius: 10,
19+
shape: ShapeLightFocus.RRect,
20+
contents: [
21+
TargetContent(
22+
align: ContentAlign.top,
23+
builder: (context, controller) {
24+
return Container(
25+
alignment: Alignment.center,
26+
child: Column(
27+
crossAxisAlignment: CrossAxisAlignment.center,
28+
mainAxisAlignment: MainAxisAlignment.center,
29+
children: <Widget>[
30+
Text(
31+
"Filter tasks based on their completion status",
32+
textAlign: TextAlign.center,
33+
style: GoogleFonts.poppins(
34+
color: Colors.white,
35+
),
36+
),
37+
],
38+
),
39+
);
40+
},
41+
),
42+
],
43+
),
44+
);
45+
46+
// projectsKey
47+
targets.add(
48+
TargetFocus(
49+
keyTarget: projectsKey,
50+
alignSkip: Alignment.topRight,
51+
radius: 10,
52+
shape: ShapeLightFocus.RRect,
53+
contents: [
54+
TargetContent(
55+
align: ContentAlign.top,
56+
builder: (context, controller) {
57+
return Container(
58+
alignment: Alignment.center,
59+
child: Column(
60+
crossAxisAlignment: CrossAxisAlignment.center,
61+
mainAxisAlignment: MainAxisAlignment.center,
62+
children: <Widget>[
63+
Text(
64+
"Filter tasks based on the projects",
65+
textAlign: TextAlign.center,
66+
style: GoogleFonts.poppins(
67+
color: Colors.white,
68+
),
69+
),
70+
],
71+
),
72+
);
73+
},
74+
),
75+
],
76+
),
77+
);
78+
79+
// filterTagByKey
80+
targets.add(
81+
TargetFocus(
82+
keyTarget: filterTagKey,
83+
alignSkip: Alignment.topRight,
84+
radius: 10,
85+
shape: ShapeLightFocus.RRect,
86+
contents: [
87+
TargetContent(
88+
align: ContentAlign.top,
89+
builder: (context, controller) {
90+
return Container(
91+
alignment: Alignment.center,
92+
child: Column(
93+
crossAxisAlignment: CrossAxisAlignment.center,
94+
mainAxisAlignment: MainAxisAlignment.center,
95+
children: <Widget>[
96+
Text(
97+
"Toggle between AND and OR tag union types",
98+
textAlign: TextAlign.center,
99+
style: GoogleFonts.poppins(
100+
color: Colors.white,
101+
),
102+
),
103+
],
104+
),
105+
);
106+
},
107+
),
108+
],
109+
),
110+
);
111+
112+
// sortByKey
113+
targets.add(
114+
TargetFocus(
115+
keyTarget: sortByKey,
116+
alignSkip: Alignment.topRight,
117+
radius: 10,
118+
shape: ShapeLightFocus.RRect,
119+
contents: [
120+
TargetContent(
121+
align: ContentAlign.top,
122+
builder: (context, controller) {
123+
return Container(
124+
alignment: Alignment.center,
125+
child: Column(
126+
crossAxisAlignment: CrossAxisAlignment.center,
127+
mainAxisAlignment: MainAxisAlignment.center,
128+
children: <Widget>[
129+
Text(
130+
"Sort tasks based on time of creation, urgency, due date, start date, etc.",
131+
textAlign: TextAlign.center,
132+
style: GoogleFonts.poppins(
133+
color: Colors.white,
134+
),
135+
),
136+
],
137+
),
138+
);
139+
},
140+
),
141+
],
142+
),
143+
);
144+
return targets;
145+
}

0 commit comments

Comments
 (0)