Skip to content
Open
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
38 changes: 37 additions & 1 deletion lib/app/modules/home/views/home_page_body.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'package:get/get.dart';
import 'package:taskwarrior/app/modules/home/views/show_tasks.dart';
import 'package:taskwarrior/app/modules/home/views/show_tasks_replica.dart';
import 'package:taskwarrior/app/modules/home/views/tasks_builder.dart';
import 'package:taskwarrior/app/modules/home/views/tutorial_modal.dart';
import 'package:taskwarrior/app/utils/app_settings/app_settings.dart';
import 'package:taskwarrior/app/utils/constants/taskwarrior_colors.dart';
import 'package:taskwarrior/app/utils/themes/theme_extension.dart';
import 'package:taskwarrior/app/utils/language/sentence_manager.dart';
Expand All @@ -13,10 +15,44 @@ class HomePageBody extends StatelessWidget {
final HomeController controller;
const HomePageBody({required this.controller, super.key});

void _showTutorialModal(BuildContext context) {
Future.delayed(
const Duration(milliseconds: 500),
() async {
bool promptShown = await SaveTourStatus.getTutorialPromptShown();
if (!promptShown && context.mounted) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext dialogContext) {
return TutorialModal(
onYes: () async {
await SaveTourStatus.saveTutorialPromptShown(true);
if (dialogContext.mounted) {
Navigator.of(dialogContext).pop();
controller.initInAppTour();
controller.tutorialCoachMark.show(context: context);
}
},
onNo: () async {
await SaveTourStatus.saveTutorialPromptShown(true);
await SaveTourStatus.disableAllTutorials();
if (dialogContext.mounted) {
Navigator.of(dialogContext).pop();
}
},
);
},
);
}
},
);
}

@override
Widget build(BuildContext context) {
controller.initInAppTour();
controller.showInAppTour(context);
_showTutorialModal(context);
TaskwarriorColorTheme tColors =
Theme.of(context).extension<TaskwarriorColorTheme>()!;
return DoubleBackToCloseApp(
Expand Down
134 changes: 134 additions & 0 deletions lib/app/modules/home/views/tutorial_modal.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:taskwarrior/app/utils/app_settings/app_settings.dart';
import 'package:taskwarrior/app/utils/language/sentence_manager.dart';
import 'package:taskwarrior/app/utils/themes/theme_extension.dart';

class TutorialModal extends StatelessWidget {
final VoidCallback onYes;
final VoidCallback onNo;

const TutorialModal({
super.key,
required this.onYes,
required this.onNo,
});

@override
Widget build(BuildContext context) {
TaskwarriorColorTheme tColors =
Theme.of(context).extension<TaskwarriorColorTheme>()!;
final sentences =
SentenceManager(currentLanguage: AppSettings.selectedLanguage)
.sentences;

return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
elevation: 10,
backgroundColor: tColors.dialogBackgroundColor,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Icon
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: tColors.primaryBackgroundColor?.withValues(alpha: 0.3),
shape: BoxShape.circle,
),
child: Icon(
Icons.school_outlined,
size: 48,
color: tColors.primaryTextColor,
),
),
const SizedBox(height: 20),

// Title
Text(
sentences.tutorialModalWelcome,
style: GoogleFonts.poppins(
fontSize: 24,
fontWeight: FontWeight.bold,
color: tColors.primaryTextColor,
),
),
const SizedBox(height: 12),

// Message
Text(
sentences.tutorialModalMessage,
textAlign: TextAlign.center,
style: GoogleFonts.poppins(
fontSize: 16,
color: tColors.primaryTextColor?.withValues(alpha: 0.8),
height: 1.5,
),
),
const SizedBox(height: 28),

// Buttons - Vertical Layout
Column(
mainAxisSize: MainAxisSize.min,
children: [
// Primary Action: Keep Tutorials (with outline and filled background)
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: onYes,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: tColors.primaryBackgroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(
color: tColors.primaryBackgroundColor ?? Colors.blue,
width: 2,
),
),
elevation: 2,
),
child: Text(
sentences.tutorialModalKeepTutorials,
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
color: tColors.primaryTextColor,
),
),
),
),
const SizedBox(height: 12),
// Secondary Action: Skip all Tutorials (text button, no outline, smaller font)
SizedBox(
width: double.infinity,
child: TextButton(
onPressed: onNo,
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: Text(
sentences.tutorialModalSkipAllTutorials,
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w500,
color: tColors.primaryTextColor?.withValues(alpha: 0.7),
),
),
),
),
],
),
],
),
),
);
}
}
18 changes: 18 additions & 0 deletions lib/app/utils/app_settings/save_tour_status.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,22 @@ class SaveTourStatus {
static Future<bool> getTaskSwipeTutorialStatus() async {
return _preferences?.getBool('task_swipe_tutorial_completed') ?? false;
}

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

static Future<bool> getTutorialPromptShown() async {
return _preferences?.getBool('tutorial_prompt_shown') ?? false;
}

static Future disableAllTutorials() async {
await saveReportsTourStatus(true);
await saveInAppTourStatus(true);
await saveFilterTourStatus(true);
await saveProfileTourStatus(true);
await saveDetailsTourStatus(true);
await saveManageTaskServerTourStatus(true);
await saveTaskSwipeTutorialStatus(true);
}
}
10 changes: 10 additions & 0 deletions lib/app/utils/language/bengali_sentences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,16 @@ class BengaliSentences extends Sentences {
String get logs => 'লগস';
@override
String get checkAllDebugLogsHere => 'এখানে সমস্ত ডিবাগ লগ পরীক্ষা করুন';

@override
String get tutorialModalWelcome => 'স্বাগতম!';
@override
String get tutorialModalMessage =>
'আপনি কি এই অ্যাপটি কীভাবে ব্যবহার করতে হয় তা শেখার জন্য একটি দ্রুত টিউটোরিয়াল দেখতে চান?';
@override
String get tutorialModalKeepTutorials => 'টিউটোরিয়াল রাখুন';
@override
String get tutorialModalSkipAllTutorials => 'সমস্ত টিউটোরিয়াল এড়িয়ে যান';
// সেটিংস
@override
String get syncSetting => 'সিঙ্ক সেটিংস';
Expand Down
10 changes: 10 additions & 0 deletions lib/app/utils/language/english_sentences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,16 @@ class EnglishSentences extends Sentences {
String get logs => 'Logs';
@override
String get checkAllDebugLogsHere => 'Check all debug logs here';

@override
String get tutorialModalWelcome => 'Welcome!';
@override
String get tutorialModalMessage =>
'Would you like to see a quick tutorial to learn how to use this app?';
@override
String get tutorialModalKeepTutorials => 'Keep Tutorials';
@override
String get tutorialModalSkipAllTutorials => 'Skip all Tutorials';
// Settings
@override
String get syncSetting => 'Sync Settings';
Expand Down
9 changes: 9 additions & 0 deletions lib/app/utils/language/french_sentences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,15 @@ class FrenchSentences extends Sentences {
String get checkAllDebugLogsHere =>
'Vérifiez tous les journaux de débogage ici';

@override
String get tutorialModalWelcome => 'Bienvenue!';
@override
String get tutorialModalMessage =>
'Souhaitez-vous voir un tutoriel rapide pour apprendre à utiliser cette application?';
@override
String get tutorialModalKeepTutorials => 'Conserver les tutoriels';
@override
String get tutorialModalSkipAllTutorials => 'Ignorer tous les tutoriels';
// Paramètres
@override
String get syncSetting => 'Paramètres de Synchronisation';
Expand Down
10 changes: 10 additions & 0 deletions lib/app/utils/language/hindi_sentences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,16 @@ class HindiSentences extends Sentences {
String get logs => 'लॉग्स';
@override
String get checkAllDebugLogsHere => 'यहाँ सभी डिबग लॉग्स देखें';

@override
String get tutorialModalWelcome => 'स्वागत है!';
@override
String get tutorialModalMessage =>
'क्या आप इस ऐप का उपयोग करना सीखने के लिए एक त्वरित ट्यूटोरियल देखना चाहेंगे?';
@override
String get tutorialModalKeepTutorials => 'ट्यूटोरियल रखें';
@override
String get tutorialModalSkipAllTutorials => 'सभी ट्यूटोरियल छोड़ें';
// सेटिंग
@override
String get syncSetting => 'सिंक सेटिंग';
Expand Down
9 changes: 9 additions & 0 deletions lib/app/utils/language/marathi_sentences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,15 @@ class MarathiSentences extends Sentences {
@override
String get checkAllDebugLogsHere => 'येथे सर्व डीबग लॉग्ज तपासा';

@override
String get tutorialModalWelcome => 'स्वागत आहे!';
@override
String get tutorialModalMessage =>
'तुम्हाला हे अॅप वापरण्याचे शिकण्यासाठी एक जलद ट्यूटोरियल पहायचा आहे का?';
@override
String get tutorialModalKeepTutorials => 'ट्यूटोरियल ठेवा';
@override
String get tutorialModalSkipAllTutorials => 'सर्व ट्यूटोरियल सोडा';
// शेटिंग
@override
String get syncSetting => 'सिंक शेटिंग';
Expand Down
6 changes: 6 additions & 0 deletions lib/app/utils/language/sentences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -350,4 +350,10 @@ abstract class Sentences {
String get profilePageChangeProfileMode;
String get profilePageSelectProfileMode;
String get profilePageSuccessfullyChangedProfileModeTo;

// Tutorial modal strings
String get tutorialModalWelcome;
String get tutorialModalMessage;
String get tutorialModalKeepTutorials;
String get tutorialModalSkipAllTutorials;
}
9 changes: 9 additions & 0 deletions lib/app/utils/language/spanish_sentences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,15 @@ class SpanishSentences extends Sentences {
String get checkAllDebugLogsHere =>
'Consulta todos los registros de depuración aquí';

@override
String get tutorialModalWelcome => '¡Bienvenido!';
@override
String get tutorialModalMessage =>
'¿Te gustaría ver un tutorial rápido para aprender a usar esta aplicación?';
@override
String get tutorialModalKeepTutorials => 'Mantener tutoriales';
@override
String get tutorialModalSkipAllTutorials => 'Omitir todos los tutoriales';
//
@override
String get syncSetting => 'Configuración de sincronización';
Expand Down