这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions lib/app/modules/home/controllers/home_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import 'package:taskwarrior/app/routes/app_pages.dart';
import 'package:taskwarrior/app/services/tag_filter.dart';
import 'package:taskwarrior/app/tour/filter_drawer_tour.dart';
import 'package:taskwarrior/app/tour/home_page_tour.dart';
import 'package:taskwarrior/app/tour/task_swipe_tour.dart';
import 'package:taskwarrior/app/utils/constants/taskwarrior_colors.dart';
import 'package:taskwarrior/app/utils/language/supported_language.dart';
import 'package:taskwarrior/app/utils/taskchampion/credentials_storage.dart';
Expand Down Expand Up @@ -673,6 +674,34 @@ class HomeController extends GetxController {
);
}

final taskItemKey = GlobalKey();

void initTaskSwipeTutorial() {
tutorialCoachMark = TutorialCoachMark(
targets: addTaskSwipeTutorialTargets(taskItemKey: taskItemKey),
colorShadow: TaskWarriorColors.black,
paddingFocus: 10,
opacityShadow: 1.00,
hideSkip: true,
onFinish: () {
SaveTourStatus.saveTaskSwipeTutorialStatus(true);
},
);
}

void showTaskSwipeTutorial(BuildContext context) {
SaveTourStatus.getTaskSwipeTutorialStatus().then((value) {
print("value is $value");
print("tasks is ${tasks.isNotEmpty}");
if (value == false) {
initTaskSwipeTutorial();
tutorialCoachMark.show(context: context);
} else {
debugPrint('User has already seen the task swipe tutorial');
}
});
}

late RxString uuid = "".obs;
late RxBool isHomeWidgetTaskTapped = false.obs;

Expand Down
10 changes: 6 additions & 4 deletions lib/app/modules/home/views/tasks_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ class TasksBuilder extends StatelessWidget {
action: SnackBarAction(
label: 'Undo',
onPressed: () {
undoChanges(
context, id, 'pending');

undoChanges(context, id, 'pending');
},
),
));
Expand Down Expand Up @@ -170,9 +168,13 @@ class TasksBuilder extends StatelessWidget {
primary: false,
itemBuilder: (context, index) {
var task = taskData[index];
final itemKey = index == 0
? storageWidget.taskItemKey
: ValueKey(task.uuid);

return pendingFilter
? Slidable(
key: ValueKey(task.uuid),
key: itemKey,
startActionPane: ActionPane(
motion: const BehindMotion(),
children: [
Expand Down
100 changes: 100 additions & 0 deletions lib/app/tour/task_swipe_tour.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';

List<TargetFocus> addTaskSwipeTutorialTargets({
required GlobalKey taskItemKey,
}) {
List<TargetFocus> targets = [];

targets.add(
TargetFocus(
identify: "taskSwipeTutorial",
keyTarget: taskItemKey,
alignSkip: Alignment.bottomRight,
radius: 10,
shape: ShapeLightFocus.RRect,
contents: [
TargetContent(
align: ContentAlign.bottom,
builder: (context, controller) {
return Container(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Task Swipe Actions",
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 22.0,
),
),
const SizedBox(height: 8),
Text(
"This is how you manage your tasks quickly : ",
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
color: Colors.white,
fontStyle: FontStyle.italic,
fontSize: 16.0,
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.arrow_right_alt,
color: Colors.green, size: 28),
const SizedBox(width: 8),
Flexible(
child: Text(
"Swipe RIGHT to COMPLETE",
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.arrow_right_alt,
textDirection: TextDirection.rtl,
color: Colors.red,
size: 28),
const SizedBox(width: 8),
Flexible(
child: Text(
"Swipe LEFT to DELETE",
textAlign: TextAlign.left,
style: GoogleFonts.poppins(
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
],
),
),
],
),
);
},
),
],
),
);

return targets;
}
8 changes: 8 additions & 0 deletions lib/app/utils/app_settings/save_tour_status.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,12 @@ class SaveTourStatus {
static Future<bool> getManageTaskServerTourStatus() async {
return _preferences?.getBool('manage_task_server_tour') ?? false;
}

static Future saveTaskSwipeTutorialStatus(bool status) async {
await _preferences?.setBool('task_swipe_tutorial_completed', status);
}

static Future<bool> getTaskSwipeTutorialStatus() async {
return _preferences?.getBool('task_swipe_tutorial_completed') ?? false;
}
}
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ dependencies:
package_info_plus: ^8.3.0
pem: ^2.0.1
permission_handler: ^11.4.0
shared_preferences: ^2.2.2
shared_preferences: ^2.5.2
shared_preferences_web: ^2.0.3
sizer: ^3.0.5
sqflite: ^2.3.3+1
Expand All @@ -61,7 +61,7 @@ dependencies:
timezone: ^0.10.0
tuple: ^2.0.0
tutorial_coach_mark: ^1.2.11
url_launcher: ^6.1.14
url_launcher: ^6.3.1
uuid: ^4.2.2
built_collection: ^5.1.1
textfield_tags: ^3.0.1
Expand Down
54 changes: 54 additions & 0 deletions test/tour/task_swipe_tour_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:taskwarrior/app/tour/task_swipe_tour.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';

class MockTutorialCoachMarkController extends Mock
implements TutorialCoachMarkController {}

void main() {
group('Task Swipe Tour', () {
late GlobalKey taskItemKey;
final controller = MockTutorialCoachMarkController();

setUp(() {
taskItemKey = GlobalKey();
});

test('should return a list of TargetFocus with correct properties', () {
final targets = addTaskSwipeTutorialTargets(
taskItemKey: taskItemKey,
);

expect(targets.length, 1);

expect(targets[0].keyTarget, taskItemKey);
expect(targets[0].identify, "taskSwipeTutorial");
expect(targets[0].alignSkip, Alignment.bottomRight);
expect(targets[0].shape, ShapeLightFocus.RRect);
expect(targets[0].radius, 10);
});

testWidgets('should render correct text for task swipe TargetContent',
(WidgetTester tester) async {
final targets = addTaskSwipeTutorialTargets(
taskItemKey: taskItemKey,
);

final content = targets[0].contents!.first;

await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (context) => content.builder!(context, controller),
),
));

expect(find.text("Task Swipe Actions"), findsOneWidget);
expect(find.text("This is how you manage your tasks quickly : "),
findsOneWidget);
expect(find.text("Swipe RIGHT to COMPLETE"), findsOneWidget);
expect(find.text("Swipe LEFT to DELETE"), findsOneWidget);
});
});
}