Skip to content

Commit 722ff9a

Browse files
Added task swipe tour
1 parent 7eaf8fd commit 722ff9a

File tree

9 files changed

+374
-265
lines changed

9 files changed

+374
-265
lines changed

lib/app/modules/home/controllers/home_controller.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import 'package:taskwarrior/app/routes/app_pages.dart';
2424
import 'package:taskwarrior/app/services/tag_filter.dart';
2525
import 'package:taskwarrior/app/tour/filter_drawer_tour.dart';
2626
import 'package:taskwarrior/app/tour/home_page_tour.dart';
27+
import 'package:taskwarrior/app/tour/task_swipe_tour.dart';
2728
import 'package:taskwarrior/app/utils/constants/taskwarrior_colors.dart';
2829
import 'package:taskwarrior/app/utils/language/supported_language.dart';
2930
import 'package:taskwarrior/app/utils/taskchampion/credentials_storage.dart';
@@ -676,6 +677,34 @@ class HomeController extends GetxController {
676677
);
677678
}
678679

680+
final taskItemKey = GlobalKey();
681+
682+
void initTaskSwipeTutorial() {
683+
tutorialCoachMark = TutorialCoachMark(
684+
targets: addTaskSwipeTutorialTargets(taskItemKey: taskItemKey),
685+
colorShadow: TaskWarriorColors.black,
686+
paddingFocus: 10,
687+
opacityShadow: 1.00,
688+
hideSkip: true,
689+
onFinish: () {
690+
SaveTourStatus.saveTaskSwipeTutorialStatus(true);
691+
},
692+
);
693+
}
694+
695+
void showTaskSwipeTutorial(BuildContext context) {
696+
SaveTourStatus.getTaskSwipeTutorialStatus().then((value) {
697+
print("value is $value");
698+
print("tasks is ${tasks.isNotEmpty}");
699+
if (value == false) {
700+
initTaskSwipeTutorial();
701+
tutorialCoachMark.show(context: context);
702+
} else {
703+
debugPrint('User has already seen the task swipe tutorial');
704+
}
705+
});
706+
}
707+
679708
late RxString uuid = "".obs;
680709
late RxBool isHomeWidgetTaskTapped = false.obs;
681710

lib/app/modules/home/views/add_task_bottom_sheet.dart

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ class AddTaskBottomSheet extends StatelessWidget {
250250
},
251251
fieldHintText: "Month/Date/Year",
252252
context: context,
253-
initialDate: homeController.due.value?? DateTime.now(),
253+
initialDate: homeController.due.value ?? DateTime.now(),
254254
firstDate: DateTime.now(),
255255
lastDate: DateTime(2037, 12, 31),
256256
);
@@ -355,10 +355,7 @@ class AddTaskBottomSheet extends StatelessWidget {
355355
crossAxisAlignment: CrossAxisAlignment.center,
356356
children: [
357357
Text(
358-
"${SentenceManager(
359-
currentLanguage: homeController.selectedLanguage.value)
360-
.sentences
361-
.addTaskPriority} :",
358+
"${SentenceManager(currentLanguage: homeController.selectedLanguage.value).sentences.addTaskPriority} :",
362359
style: GoogleFonts.poppins(
363360
fontWeight: TaskWarriorFonts.bold,
364361
color: AppSettings.isDarkMode
@@ -367,51 +364,54 @@ class AddTaskBottomSheet extends StatelessWidget {
367364
),
368365
textAlign: TextAlign.left,
369366
),
370-
const SizedBox(width: 2,),
367+
const SizedBox(
368+
width: 2,
369+
),
371370
Obx(
372371
() => Row(
373372
children: [
374-
for(int i=0;i<homeController.priorityList.length;i++)
373+
for (int i = 0; i < homeController.priorityList.length; i++)
375374
Padding(
376375
padding: const EdgeInsets.symmetric(horizontal: 2.5),
377376
child: GestureDetector(
378377
onTap: () {
379-
homeController.priority.value = homeController.priorityList[i];
378+
homeController.priority.value =
379+
homeController.priorityList[i];
380380
debugPrint(homeController.priority.value);
381381
},
382382
child: AnimatedContainer(
383383
duration: const Duration(milliseconds: 100),
384384
height: 30,
385385
width: 37,
386386
decoration: BoxDecoration(
387-
388-
borderRadius: BorderRadius.circular(8),
389-
border: Border.all(
390-
color: homeController.priority.value == homeController.priorityList[i]
391-
? AppSettings.isDarkMode
392-
? TaskWarriorColors.kLightPrimaryBackgroundColor
393-
: TaskWarriorColors.kprimaryBackgroundColor
394-
: AppSettings.isDarkMode
395-
? TaskWarriorColors.kprimaryBackgroundColor
396-
: TaskWarriorColors.kLightPrimaryBackgroundColor,
397-
)
398-
),
387+
borderRadius: BorderRadius.circular(8),
388+
border: Border.all(
389+
color: homeController.priority.value ==
390+
homeController.priorityList[i]
391+
? AppSettings.isDarkMode
392+
? TaskWarriorColors
393+
.kLightPrimaryBackgroundColor
394+
: TaskWarriorColors
395+
.kprimaryBackgroundColor
396+
: AppSettings.isDarkMode
397+
? TaskWarriorColors
398+
.kprimaryBackgroundColor
399+
: TaskWarriorColors
400+
.kLightPrimaryBackgroundColor,
401+
)),
399402
child: Center(
400403
child: Text(
401404
homeController.priorityList[i],
402405
textAlign: TextAlign.center,
403406
style: GoogleFonts.poppins(
404-
fontWeight: FontWeight.bold,
405-
fontSize: 17,
406-
color: homeController.priorityColors[i]
407-
),
407+
fontWeight: FontWeight.bold,
408+
fontSize: 17,
409+
color: homeController.priorityColors[i]),
408410
),
409411
),
410412
),
411-
412413
),
413414
)
414-
415415
],
416416
),
417417
)
@@ -448,8 +448,7 @@ class AddTaskBottomSheet extends StatelessWidget {
448448
Widget buildAddButton(BuildContext context) {
449449
return TextButton(
450450
child: Text(
451-
SentenceManager(
452-
currentLanguage: homeController.selectedLanguage.value)
451+
SentenceManager(currentLanguage: homeController.selectedLanguage.value)
453452
.sentences
454453
.addTaskAdd,
455454
style: TextStyle(
@@ -460,12 +459,12 @@ class AddTaskBottomSheet extends StatelessWidget {
460459
),
461460
onPressed: () async {
462461
// print(homeController.formKey.currentState);
463-
if(homeController.due.value!=null&&DateTime.now().isAfter(homeController.due.value!)){
462+
if (homeController.due.value != null &&
463+
DateTime.now().isAfter(homeController.due.value!)) {
464464
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
465465
content: Text(
466466
SentenceManager(
467-
currentLanguage:
468-
homeController.selectedLanguage.value)
467+
currentLanguage: homeController.selectedLanguage.value)
469468
.sentences
470469
.addTaskTimeInPast,
471470
style: TextStyle(
@@ -476,8 +475,7 @@ class AddTaskBottomSheet extends StatelessWidget {
476475
),
477476
backgroundColor: AppSettings.isDarkMode
478477
? TaskWarriorColors.ksecondaryBackgroundColor
479-
: TaskWarriorColors
480-
.kLightSecondaryBackgroundColor,
478+
: TaskWarriorColors.kLightSecondaryBackgroundColor,
481479
duration: const Duration(seconds: 2)));
482480
return;
483481
}
@@ -501,13 +499,12 @@ class AddTaskBottomSheet extends StatelessWidget {
501499
homeController.priority.value = 'M';
502500
homeController.tagcontroller.text = '';
503501
homeController.tags.value = [];
504-
homeController.due.value=null;
502+
homeController.due.value = null;
505503
homeController.update();
506504
// Navigator.of(context).pop();
507505
Get.back();
508506
if (Platform.isAndroid) {
509-
WidgetController widgetController =
510-
Get.put(WidgetController());
507+
WidgetController widgetController = Get.put(WidgetController());
511508
widgetController.fetchAllData();
512509

513510
widgetController.update();
@@ -518,7 +515,8 @@ class AddTaskBottomSheet extends StatelessWidget {
518515
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
519516
content: Text(
520517
SentenceManager(
521-
currentLanguage: homeController.selectedLanguage.value)
518+
currentLanguage:
519+
homeController.selectedLanguage.value)
522520
.sentences
523521
.addTaskTaskAddedSuccessfully,
524522
style: TextStyle(
@@ -542,6 +540,7 @@ class AddTaskBottomSheet extends StatelessWidget {
542540
if (value) {
543541
storageWidget.synchronize(context, true);
544542
}
543+
homeController.showTaskSwipeTutorial(context);
545544
} on FormatException catch (e) {
546545
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
547546
content: Text(
@@ -567,18 +566,20 @@ class AddTaskBottomSheet extends StatelessWidget {
567566
if (tag.isNotEmpty) {
568567
String trimmedString = tag.trim();
569568
List<String> tags = trimmedString.split(" ");
570-
for(tag in tags){
571-
if(checkTagIfExists(tag)) {
569+
for (tag in tags) {
570+
if (checkTagIfExists(tag)) {
572571
removeTag(tag);
573572
}
574573
homeController.tags.add(tag);
575574
}
576575
homeController.tagcontroller.text = '';
577576
}
578577
}
579-
bool checkTagIfExists(String tag){
578+
579+
bool checkTagIfExists(String tag) {
580580
return homeController.tags.contains(tag);
581581
}
582+
582583
void removeTag(String tag) {
583584
homeController.tags.remove(tag);
584585
}

lib/app/modules/home/views/add_task_to_taskc_bottom_sheet.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ class AddTaskToTaskcBottomSheet extends StatelessWidget {
352352
end: '',
353353
modified: 'r');
354354
await homeController.taskdb.insertTask(task);
355+
homeController.showTaskSwipeTutorial(context);
355356
homeController.namecontroller.text = '';
356357
homeController.due.value = null;
357358
homeController.priority.value = 'M';

lib/app/modules/home/views/tasks_builder.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ class TasksBuilder extends StatelessWidget {
7676
action: SnackBarAction(
7777
label: 'Undo',
7878
onPressed: () {
79-
undoChanges(
80-
context, id, 'pending');
81-
79+
undoChanges(context, id, 'pending');
8280
},
8381
),
8482
));
@@ -180,9 +178,13 @@ class TasksBuilder extends StatelessWidget {
180178
primary: false,
181179
itemBuilder: (context, index) {
182180
var task = taskData[index];
181+
final itemKey = index == 0
182+
? storageWidget.taskItemKey
183+
: ValueKey(task.uuid);
184+
183185
return pendingFilter
184186
? Slidable(
185-
key: ValueKey(task.uuid),
187+
key: itemKey,
186188
startActionPane: ActionPane(
187189
motion: const BehindMotion(),
188190
children: [

lib/app/tour/task_swipe_tour.dart

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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> addTaskSwipeTutorialTargets({
6+
required GlobalKey taskItemKey,
7+
}) {
8+
List<TargetFocus> targets = [];
9+
10+
targets.add(
11+
TargetFocus(
12+
identify: "taskSwipeTutorial",
13+
keyTarget: taskItemKey,
14+
alignSkip: Alignment.bottomRight,
15+
radius: 10,
16+
shape: ShapeLightFocus.RRect,
17+
contents: [
18+
TargetContent(
19+
align: ContentAlign.bottom,
20+
builder: (context, controller) {
21+
return Container(
22+
alignment: Alignment.center,
23+
child: Column(
24+
crossAxisAlignment: CrossAxisAlignment.center,
25+
mainAxisAlignment: MainAxisAlignment.center,
26+
children: <Widget>[
27+
Text(
28+
"Task Swipe Actions",
29+
textAlign: TextAlign.center,
30+
style: GoogleFonts.poppins(
31+
color: Colors.white,
32+
fontWeight: FontWeight.bold,
33+
fontSize: 22.0,
34+
),
35+
),
36+
const SizedBox(height: 8),
37+
Text(
38+
"This is how you manage your tasks quickly : ",
39+
textAlign: TextAlign.center,
40+
style: GoogleFonts.poppins(
41+
color: Colors.white,
42+
fontStyle: FontStyle.italic,
43+
fontSize: 16.0,
44+
),
45+
),
46+
Padding(
47+
padding: const EdgeInsets.only(top: 16.0),
48+
child: Row(
49+
mainAxisAlignment: MainAxisAlignment.center,
50+
children: [
51+
const Icon(Icons.arrow_right_alt,
52+
color: Colors.green, size: 28),
53+
const SizedBox(width: 8),
54+
Flexible(
55+
child: Text(
56+
"Swipe RIGHT to COMPLETE",
57+
textAlign: TextAlign.left,
58+
style: GoogleFonts.poppins(
59+
color: Colors.white,
60+
fontWeight: FontWeight.w500,
61+
),
62+
),
63+
),
64+
],
65+
),
66+
),
67+
Padding(
68+
padding: const EdgeInsets.only(top: 10.0),
69+
child: Row(
70+
mainAxisAlignment: MainAxisAlignment.center,
71+
children: [
72+
const Icon(Icons.arrow_right_alt,
73+
textDirection: TextDirection.rtl,
74+
color: Colors.red,
75+
size: 28),
76+
const SizedBox(width: 8),
77+
Flexible(
78+
child: Text(
79+
"Swipe LEFT to DELETE",
80+
textAlign: TextAlign.left,
81+
style: GoogleFonts.poppins(
82+
color: Colors.white,
83+
fontWeight: FontWeight.w500,
84+
),
85+
),
86+
),
87+
],
88+
),
89+
),
90+
],
91+
),
92+
);
93+
},
94+
),
95+
],
96+
),
97+
);
98+
99+
return targets;
100+
}

lib/app/utils/app_settings/save_tour_status.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,12 @@ class SaveTourStatus {
5454
static Future<bool> getManageTaskServerTourStatus() async {
5555
return _preferences?.getBool('manage_task_server_tour') ?? false;
5656
}
57+
58+
static Future saveTaskSwipeTutorialStatus(bool status) async {
59+
await _preferences?.setBool('task_swipe_tutorial_completed', status);
60+
}
61+
62+
static Future<bool> getTaskSwipeTutorialStatus() async {
63+
return _preferences?.getBool('task_swipe_tutorial_completed') ?? false;
64+
}
5765
}

macos/Flutter/GeneratedPluginRegistrant.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import flutter_timezone
1414
import package_info_plus
1515
import path_provider_foundation
1616
import shared_preferences_foundation
17-
import sqflite_darwin
17+
import sqflite
1818
import url_launcher_macos
1919

2020
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {

0 commit comments

Comments
 (0)