From 1fff9bb3df159fe01341be8f2e22345a55ed2fb4 Mon Sep 17 00:00:00 2001 From: mahendra kasula Date: Mon, 10 Mar 2025 19:25:28 +0530 Subject: [PATCH 01/10] Create time_imit_view.dart --- .../settings/views/time_imit_view.dart | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 lib/app/modules/settings/views/time_imit_view.dart diff --git a/lib/app/modules/settings/views/time_imit_view.dart b/lib/app/modules/settings/views/time_imit_view.dart new file mode 100644 index 00000000..6ace985a --- /dev/null +++ b/lib/app/modules/settings/views/time_imit_view.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ultimate_alarm_clock/app/utils/constants.dart'; +import 'package:ultimate_alarm_clock/app/utils/utils.dart'; +import '../controllers/settings_controller.dart'; +import '../controllers/theme_controller.dart'; + +class TimeLimitView extends StatelessWidget { + TimeLimitView({ + Key? key, + required this.themeController, + required this.height, + required this.width, + }) : super(key: key); + + final ThemeController themeController; + final SettingsController controller = Get.find(); + final double width; + final double height; + + @override + Widget build(BuildContext context) { + int timeLimit; + return Obx( + () => Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + Utils.hapticFeedback(); + timeLimit = controller.challengeTimeLimit.value; + Get.defaultDialog( + onWillPop: () async { + Get.back(); + controller.challengeTimeLimit.value = timeLimit; + return true; + }, + titlePadding: const EdgeInsets.symmetric(vertical: 20, horizontal: 5), + backgroundColor: themeController.secondaryBackgroundColor.value, + title: 'Customize Challenge Timer'.tr, + titleStyle: Theme.of(context).textTheme.displaySmall, + content: Obx( + () => Column( + children: [ + Text( + '${controller.challengeTimeLimit.value} seconds'.tr, + style: Theme.of(context).textTheme.displaySmall, + ), + Slider( + value: controller.challengeTimeLimit.value.toDouble(), + onChanged: (double value) { + controller.challengeTimeLimit.value = value.toInt(); + }, + min: 5.0, + max: 60.0, + divisions: 55, + label: controller.challengeTimeLimit.value.toString(), + ), + ElevatedButton( + onPressed: () { + controller.saveSettings(); + Get.back(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: kprimaryColor, + ), + child: Text( + 'Apply Time Limit'.tr, + style: TextStyle( + color: themeController.secondaryTextColor.value, + ), + ), + ), + ], + ), + ), + ); + }, + child: Container( + width: width * 0.91, + height: height * 0.09, + decoration: Utils.getCustomTileBoxDecoration( + isLightMode: themeController.currentTheme.value == ThemeMode.light, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: ListTile( + tileColor: themeController.secondaryBackgroundColor.value, + title: Text( + 'Challenge Timer Limit'.tr, + style: TextStyle( + color: themeController.primaryTextColor.value, + fontSize: 15, + ), + ), + trailing: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + Obx( + () => Text( + '${controller.challengeTimeLimit.value.round().toInt()} seconds', + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: themeController.primaryTextColor.value, + fontSize: 13, + ), + ), + ), + Icon( + Icons.chevron_right, + color: themeController.primaryDisabledTextColor.value, + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} From 2b64c38142de4f2762e06d01d8862ed69aba9876 Mon Sep 17 00:00:00 2001 From: mahendra kasula Date: Mon, 10 Mar 2025 19:39:23 +0530 Subject: [PATCH 02/10] Update time_imit_view.dart --- .../settings/views/time_imit_view.dart | 176 +++++++++--------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/lib/app/modules/settings/views/time_imit_view.dart b/lib/app/modules/settings/views/time_imit_view.dart index 6ace985a..3d9c1d70 100644 --- a/lib/app/modules/settings/views/time_imit_view.dart +++ b/lib/app/modules/settings/views/time_imit_view.dart @@ -6,111 +6,111 @@ import '../controllers/settings_controller.dart'; import '../controllers/theme_controller.dart'; class TimeLimitView extends StatelessWidget { - TimeLimitView({ - Key? key, + const TimeLimitView({ + super.key, + required this.controller, required this.themeController, - required this.height, required this.width, - }) : super(key: key); + required this.height, + }); + final SettingsController controller; final ThemeController themeController; - final SettingsController controller = Get.find(); final double width; final double height; @override Widget build(BuildContext context) { - int timeLimit; + int initialTimeLimit; return Obx( - () => Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - Utils.hapticFeedback(); - timeLimit = controller.challengeTimeLimit.value; - Get.defaultDialog( - onWillPop: () async { - Get.back(); - controller.challengeTimeLimit.value = timeLimit; - return true; - }, - titlePadding: const EdgeInsets.symmetric(vertical: 20, horizontal: 5), - backgroundColor: themeController.secondaryBackgroundColor.value, - title: 'Customize Challenge Timer'.tr, - titleStyle: Theme.of(context).textTheme.displaySmall, - content: Obx( - () => Column( - children: [ - Text( - '${controller.challengeTimeLimit.value} seconds'.tr, - style: Theme.of(context).textTheme.displaySmall, - ), - Slider( - value: controller.challengeTimeLimit.value.toDouble(), - onChanged: (double value) { - controller.challengeTimeLimit.value = value.toInt(); - }, - min: 5.0, - max: 60.0, - divisions: 55, - label: controller.challengeTimeLimit.value.toString(), + () => InkWell( + onTap: () { + Utils.hapticFeedback(); + // Store the initial value before any changes. + initialTimeLimit = controller.challengeTimeLimit.value; + Get.defaultDialog( + onWillPop: () async { + Get.back(); + // Resetting the value to its initial state if the user cancels changes. + controller.challengeTimeLimit.value = initialTimeLimit; + return true; + }, + titlePadding: const EdgeInsets.symmetric(vertical: 20, horizontal: 5), + backgroundColor: themeController.secondaryBackgroundColor.value, + title: 'Customize Challenge Timer'.tr, + titleStyle: Theme.of(context).textTheme.displaySmall, + content: Obx( + () => Column( + children: [ + Text( + '${controller.challengeTimeLimit.value} seconds'.tr, + style: Theme.of(context).textTheme.displaySmall, + ), + Slider( + value: controller.challengeTimeLimit.value.toDouble(), + onChanged: (double newValue) { + controller.challengeTimeLimit.value = newValue.toInt(); + }, + min: 5.0, + max: 60.0, + divisions: 55, + label: controller.challengeTimeLimit.value.toString(), + ), + ElevatedButton( + onPressed: () { + controller.saveSettings(); + Get.back(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: kprimaryColor, ), - ElevatedButton( - onPressed: () { - controller.saveSettings(); - Get.back(); - }, - style: ElevatedButton.styleFrom( - backgroundColor: kprimaryColor, - ), - child: Text( - 'Apply Time Limit'.tr, - style: TextStyle( - color: themeController.secondaryTextColor.value, - ), + child: Text( + 'Apply Time Limit'.tr, + style: TextStyle( + color: themeController.secondaryTextColor.value, ), ), - ], - ), + ), + ], ), - ); - }, - child: Container( - width: width * 0.91, - height: height * 0.09, - decoration: Utils.getCustomTileBoxDecoration( - isLightMode: themeController.currentTheme.value == ThemeMode.light, ), - child: Center( - child: Padding( - padding: const EdgeInsets.only(left: 10, right: 10), - child: ListTile( - tileColor: themeController.secondaryBackgroundColor.value, - title: Text( - 'Challenge Timer Limit'.tr, - style: TextStyle( - color: themeController.primaryTextColor.value, - fontSize: 15, - ), + ); + }, + child: Container( + width: width * 0.91, + height: height * 0.09, + decoration: Utils.getCustomTileBoxDecoration( + isLightMode: themeController.currentTheme.value == ThemeMode.light, + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: ListTile( + tileColor: themeController.secondaryBackgroundColor.value, + title: Text( + 'Challenge Timer Limit'.tr, + style: TextStyle( + color: themeController.primaryTextColor.value, + fontSize: 15, ), - trailing: Wrap( - crossAxisAlignment: WrapCrossAlignment.center, - children: [ - Obx( - () => Text( - '${controller.challengeTimeLimit.value.round().toInt()} seconds', - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - color: themeController.primaryTextColor.value, - fontSize: 13, - ), - ), - ), - Icon( - Icons.chevron_right, - color: themeController.primaryDisabledTextColor.value, + ), + trailing: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + Obx( + () => Text( + '${controller.challengeTimeLimit.value.round()} seconds', + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: themeController.primaryTextColor.value, + fontSize: 13, + ), ), - ], - ), + ), + Icon( + Icons.chevron_right, + color: themeController.primaryDisabledTextColor.value, + ), + ], ), ), ), From 54005c7d7e96ba3c4e5cfbcd99e1c3551054376f Mon Sep 17 00:00:00 2001 From: mahendra kasula Date: Mon, 10 Mar 2025 19:40:21 +0530 Subject: [PATCH 03/10] Update settings_view.dart --- lib/app/modules/settings/views/settings_view.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/app/modules/settings/views/settings_view.dart b/lib/app/modules/settings/views/settings_view.dart index 680430cd..0620862d 100644 --- a/lib/app/modules/settings/views/settings_view.dart +++ b/lib/app/modules/settings/views/settings_view.dart @@ -9,6 +9,7 @@ import 'package:ultimate_alarm_clock/app/modules/settings/views/enable_haptic_fe import 'package:ultimate_alarm_clock/app/modules/settings/views/enable_sorted_alarm_list.dart'; import 'package:ultimate_alarm_clock/app/modules/settings/views/language_menu.dart'; import 'package:ultimate_alarm_clock/app/modules/settings/views/theme_value_tile.dart'; +import 'package:ultimate_alarm_clock/app/modules/settings/views/time_limit_view.dart'; import 'package:ultimate_alarm_clock/app/utils/utils.dart'; import '../controllers/settings_controller.dart'; import 'google_sign_in.dart'; @@ -114,6 +115,12 @@ class SettingsView extends GetView { const SizedBox( height: 20, ), + TimeLimitView( + controller: controller, + height: height, + width: width, + themeController: controller.themeController, + ) ], ), ), From 15d32c1ba9c56371b899b41c79f436bad2fa4819 Mon Sep 17 00:00:00 2001 From: mahendra kasula Date: Mon, 10 Mar 2025 19:43:04 +0530 Subject: [PATCH 04/10] Update settings_controller.dart --- .../controllers/settings_controller.dart | 62 ++++++++++++++----- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/lib/app/modules/settings/controllers/settings_controller.dart b/lib/app/modules/settings/controllers/settings_controller.dart index 5db0c333..472f3fa1 100644 --- a/lib/app/modules/settings/controllers/settings_controller.dart +++ b/lib/app/modules/settings/controllers/settings_controller.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_sign_in/google_sign_in.dart'; - import 'package:ultimate_alarm_clock/app/data/models/user_model.dart'; - import 'package:ultimate_alarm_clock/app/data/providers/secure_storage_provider.dart'; import 'package:ultimate_alarm_clock/app/modules/home/controllers/home_controller.dart'; import 'package:ultimate_alarm_clock/app/modules/settings/controllers/theme_controller.dart'; @@ -14,6 +12,7 @@ import 'package:fl_location/fl_location.dart'; import '../../../data/providers/get_storage_provider.dart'; import '../../../data/providers/google_cloud_api_provider.dart'; +import 'package:ultimate_alarm_clock/app/data/models/alarm_model.dart'; class SettingsController extends GetxController { HomeController homeController = Get.find(); @@ -65,6 +64,12 @@ class SettingsController extends GetxController { }, }; + // ChallengeSettingsController properties + final RxInt challengeTimeLimit = 30.obs; + AlarmModel? alarmRecord; + + SettingsController({this.alarmRecord}); + @override void onInit() async { super.onInit(); @@ -74,10 +79,37 @@ class SettingsController extends GetxController { userModel.value = await _secureStorageProvider.retrieveUserModel(); } _loadPreference(); + _loadChallengeSettings(); } - // Logins user using GoogleSignIn + void _loadChallengeSettings() async { + int storedTimeLimit = await _secureStorageProvider.readChallengeTimeLimit(); + challengeTimeLimit.value = storedTimeLimit; + if (alarmRecord != null) { + alarmRecord!.challengeTimeLimit = storedTimeLimit; + } + } + + void updateTimeLimit(int newLimit) { + challengeTimeLimit.value = newLimit; + // Ensure the updated limit is saved in the alarm record if it exists + if (alarmRecord != null) { + alarmRecord!.challengeTimeLimit = newLimit; + } + // Save the updated global challenge time limit + _secureStorageProvider.writeChallengeTimeLimit(newLimit); + } + + void saveSettings() { + if (alarmRecord != null) { + alarmRecord!.challengeTimeLimit = challengeTimeLimit.value; + // Save the updated alarmRecord to persistent storage or backend + } + // Save the updated global challenge time limit + _secureStorageProvider.writeChallengeTimeLimit(challengeTimeLimit.value); + } + // Logins user using GoogleSignIn Future logoutGoogle() async { await GoogleCloudProvider.logoutGoogle(); await SecureStorageProvider().deleteUserModel(); @@ -141,22 +173,23 @@ class SettingsController extends GetxController { var locationPermission = await FlLocation.checkLocationPermission(); if (locationPermission == LocationPermission.deniedForever) { - // Cannot request runtime permission because location permission is - // denied forever. + // Cannot request runtime permission because location permission is denied forever. return false; } else if (locationPermission == LocationPermission.denied) { // Ask the user for location permission. locationPermission = await FlLocation.requestLocationPermission(); if (locationPermission == LocationPermission.denied || - locationPermission == LocationPermission.deniedForever) return false; + locationPermission == LocationPermission.deniedForever) + return false; } // Location permission must always be allowed (LocationPermission.always) // to collect location data in the background. if (background == true && - locationPermission == LocationPermission.whileInUse) return false; + locationPermission == LocationPermission.whileInUse) + return false; - // Location services has been enabled and permission have been granted. + // Location services have been enabled and permissions have been granted. return true; } @@ -172,24 +205,19 @@ class SettingsController extends GetxController { currentLanguage.value = await storage.readCurrentLanguage(); - // Store the retrieved API key from the flutter secure storage + // Store the retrieved API key from flutter secure storage. String? retrievedAPIKey = await getKey(ApiKeys.openWeatherMap); - // If the API key has been previously stored there + // If the API key has been previously stored. if (retrievedAPIKey != null) { // Assign the controller's text to the retrieved API key so that - // when the user comes to update their API key, they're able - // to see the previously added API key + // when the user comes to update their API key, they see the previously added key. apiKey.text = retrievedAPIKey; } - // Store the retrieved weather state from the flutter secure storage + // Retrieve and update the weather state from flutter secure storage. String? retrievedWeatherState = await getWeatherState(); - - // If the weather state has been previously stored there if (retrievedWeatherState != null) { - // Assign the weatherKeyState to the previously stored weather state, - // but first convert the stored string to the WeatherKeyState enum weatherKeyState.value = WeatherKeyState.values.firstWhereOrNull( (weatherState) => weatherState.name == retrievedWeatherState, ) ?? From 93a7cebfe982cbdc9268356cb2c5c24b65c75b6a Mon Sep 17 00:00:00 2001 From: mahendra kasula Date: Mon, 10 Mar 2025 19:43:46 +0530 Subject: [PATCH 05/10] Update alarm_challenge_controller.dart --- .../alarm_challenge_controller.dart | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/lib/app/modules/alarmChallenge/controllers/alarm_challenge_controller.dart b/lib/app/modules/alarmChallenge/controllers/alarm_challenge_controller.dart index 9bc6e0de..2bd74619 100644 --- a/lib/app/modules/alarmChallenge/controllers/alarm_challenge_controller.dart +++ b/lib/app/modules/alarmChallenge/controllers/alarm_challenge_controller.dart @@ -10,6 +10,7 @@ import 'package:ultimate_alarm_clock/app/data/models/alarm_model.dart'; import 'package:ultimate_alarm_clock/app/utils/audio_utils.dart'; import 'package:ultimate_alarm_clock/app/utils/constants.dart'; import 'package:ultimate_alarm_clock/app/utils/utils.dart'; +import 'package:ultimate_alarm_clock/app/data/providers/secure_storage_provider.dart'; // Import secure storage provider class AlarmChallengeController extends GetxController { AlarmModel alarmRecord = Get.arguments; @@ -42,6 +43,7 @@ class AlarmChallengeController extends GetxController { bool shouldProcessStepCount = false; late Stream _stepCountStream; + Timer? _timer; void onButtonPressed(String buttonText) { displayValue.value += buttonText; @@ -89,7 +91,7 @@ class AlarmChallengeController extends GetxController { @override void onInit() async { super.onInit(); - _startTimer(); + await _startTimer(); String ringtoneName = alarmRecord.ringtoneName; @@ -199,29 +201,23 @@ class AlarmChallengeController extends GetxController { } } - void _startTimer() async { - const duration = Duration(seconds: 15); - const totalIterations = 1500000; - const decrement = 0.000001; - - for (var i = totalIterations; i > 0; i--) { - if (!isTimerEnabled) { - debugPrint('THIS IS THE BUG'); - break; - } - if (progress.value <= 0.0) { + Future _startTimer() async { + int challengeTimeLimit = await SecureStorageProvider().readChallengeTimeLimit(); + progress.value = 1.0; + _timer = Timer.periodic(Duration(milliseconds: 100), (timer) { + if (progress.value > 0) { + progress.value -= 1 / (challengeTimeLimit * 10); + } else { + timer.cancel(); shouldProcessStepCount = false; Get.until((route) => route.settings.name == '/alarm-ring'); - break; } - await Future.delayed(duration ~/ i); - progress.value -= decrement; - } + }); } restartTimer() { - progress.value = 1.0; // Reset the progress to its initial value - _startTimer(); // Start a new timer + _timer?.cancel(); + _startTimer(); } isChallengesComplete() { @@ -235,7 +231,7 @@ class AlarmChallengeController extends GetxController { @override void onClose() async { super.onClose(); - + _timer?.cancel(); shouldProcessStepCount = false; String ringtoneName = alarmRecord.ringtoneName; @@ -255,4 +251,3 @@ class AlarmChallengeController extends GetxController { } } } - From 76ca871ab207de57c6accbc96e46bfb9383c11f7 Mon Sep 17 00:00:00 2001 From: mahendra kasula Date: Mon, 10 Mar 2025 19:44:25 +0530 Subject: [PATCH 06/10] Update alarm_challenge_view.dart --- .../modules/alarmChallenge/views/alarm_challenge_view.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/app/modules/alarmChallenge/views/alarm_challenge_view.dart b/lib/app/modules/alarmChallenge/views/alarm_challenge_view.dart index fef97975..6b1a11e6 100644 --- a/lib/app/modules/alarmChallenge/views/alarm_challenge_view.dart +++ b/lib/app/modules/alarmChallenge/views/alarm_challenge_view.dart @@ -18,8 +18,6 @@ class AlarmChallengeView extends GetView { @override Widget build(BuildContext context) { - // var width = Get.width; - // var height = Get.height; final double width = MediaQuery.of(context).size.width; final double height = MediaQuery.of(context).size.height; @@ -157,7 +155,7 @@ class AlarmChallengeView extends GetView { ), Obx( () => Icon( - controller.isQrOngoing.value == + controller.isMathsOngoing.value == Status.completed ? Icons.done : Icons.arrow_forward_ios_sharp, From e43d8de74102a14b5d88ae9ce25839000a65e3eb Mon Sep 17 00:00:00 2001 From: mahendra kasula Date: Mon, 10 Mar 2025 19:45:42 +0530 Subject: [PATCH 07/10] Update secure_storage_provider.dart --- lib/app/data/providers/secure_storage_provider.dart | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/app/data/providers/secure_storage_provider.dart b/lib/app/data/providers/secure_storage_provider.dart index 24592e8d..1cc292c7 100644 --- a/lib/app/data/providers/secure_storage_provider.dart +++ b/lib/app/data/providers/secure_storage_provider.dart @@ -107,7 +107,7 @@ class SecureStorageProvider { ); } - //check 24 hrs enabled + // Check 24 hrs enabled Future read24HoursEnabled({required String key}) async { return await _secureStorage.read(key: key) == 'true'; } @@ -212,4 +212,15 @@ class SecureStorageProvider { value: timerId.toString(), ); } + + + Future writeChallengeTimeLimit(int timeLimit) async { + await _secureStorage.write(key: 'challengeTimeLimit', value: timeLimit.toString()); + } + + + Future readChallengeTimeLimit() async { + String? timeLimit = await _secureStorage.read(key: 'challengeTimeLimit'); + return timeLimit != null ? int.parse(timeLimit) : 30; + } } From 1c285d56aabfc0d77a7f9070994bd34c22cfe2ef Mon Sep 17 00:00:00 2001 From: mahendra-918 Date: Mon, 10 Mar 2025 20:16:51 +0530 Subject: [PATCH 08/10] final code --- lib/app/data/models/alarm_model.dart | 124 ++++++++++-------- ...me_imit_view.dart => time_limit_view.dart} | 0 2 files changed, 68 insertions(+), 56 deletions(-) rename lib/app/modules/settings/views/{time_imit_view.dart => time_limit_view.dart} (100%) diff --git a/lib/app/data/models/alarm_model.dart b/lib/app/data/models/alarm_model.dart index 4bd43aad..915a8134 100644 --- a/lib/app/data/models/alarm_model.dart +++ b/lib/app/data/models/alarm_model.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'package:cloud_firestore/cloud_firestore.dart' as firestore; - import 'package:isar/isar.dart'; import 'package:ultimate_alarm_clock/app/data/models/user_model.dart'; import 'package:ultimate_alarm_clock/app/utils/utils.dart'; @@ -59,57 +58,63 @@ class AlarmModel { late int guardianTimer; late String guardian; late bool isCall; + + // New optional field for a custom challenge time limit in seconds. + int? challengeTimeLimit; + @ignore Map? offsetDetails; - AlarmModel( - {required this.alarmTime, - required this.alarmID, - this.sharedUserIds = const [], - required this.ownerId, - required this.ownerName, - required this.lastEditedUserId, - required this.mutexLock, - this.isEnabled = true, - required this.days, - required this.intervalToAlarm, - required this.isActivityEnabled, - required this.minutesSinceMidnight, - required this.isLocationEnabled, - required this.isSharedAlarmEnabled, - required this.isWeatherEnabled, - required this.location, - required this.weatherTypes, - required this.isMathsEnabled, - required this.mathsDifficulty, - required this.numMathsQuestions, - required this.isShakeEnabled, - required this.shakeTimes, - required this.isQrEnabled, - required this.qrValue, - required this.isPedometerEnabled, - required this.numberOfSteps, - required this.activityInterval, - this.offsetDetails = const {}, - required this.mainAlarmTime, - required this.label, - required this.isOneTime, - required this.snoozeDuration, - required this.gradient, - required this.ringtoneName, - required this.note, - required this.deleteAfterGoesOff, - required this.showMotivationalQuote, - required this.volMax, - required this.volMin, - required this.activityMonitor, - required this.ringOn, - required this.alarmDate, - required this.profile, - required this.isGuardian, - required this.guardianTimer, - required this.guardian, - required this.isCall}); + AlarmModel({ + required this.alarmTime, + required this.alarmID, + this.sharedUserIds = const [], + required this.ownerId, + required this.ownerName, + required this.lastEditedUserId, + required this.mutexLock, + this.isEnabled = true, + required this.days, + required this.intervalToAlarm, + required this.isActivityEnabled, + required this.minutesSinceMidnight, + required this.isLocationEnabled, + required this.isSharedAlarmEnabled, + required this.isWeatherEnabled, + required this.location, + required this.weatherTypes, + required this.isMathsEnabled, + required this.mathsDifficulty, + required this.numMathsQuestions, + required this.isShakeEnabled, + required this.shakeTimes, + required this.isQrEnabled, + required this.qrValue, + required this.isPedometerEnabled, + required this.numberOfSteps, + required this.activityInterval, + this.offsetDetails = const {}, + required this.mainAlarmTime, + required this.label, + required this.isOneTime, + required this.snoozeDuration, + required this.gradient, + required this.ringtoneName, + required this.note, + required this.deleteAfterGoesOff, + required this.showMotivationalQuote, + required this.volMax, + required this.volMin, + required this.activityMonitor, + required this.ringOn, + required this.alarmDate, + required this.profile, + required this.isGuardian, + required this.guardianTimer, + required this.guardian, + required this.isCall, + this.challengeTimeLimit, + }); AlarmModel.fromDocumentSnapshot({ required firestore.DocumentSnapshot documentSnapshot, @@ -122,7 +127,6 @@ class AlarmModel { if (isSharedAlarmEnabled && user != null) { mainAlarmTime = documentSnapshot['alarmTime']; // Using offsetted time only if it is enabled - alarmTime = (offsetDetails![user.id]['offsetDuration'] != 0) ? offsetDetails![user.id]['offsettedTime'] : documentSnapshot['alarmTime']; @@ -179,6 +183,11 @@ class AlarmModel { guardianTimer = documentSnapshot['guardianTimer']; guardian = documentSnapshot['guardian']; isCall = documentSnapshot['isCall']; + + // Read the optional challengeTimeLimit if available. + challengeTimeLimit = documentSnapshot.data().toString().contains('challengeTimeLimit') + ? documentSnapshot['challengeTimeLimit'] + : null; } AlarmModel fromMapSQFlite(Map map) { @@ -231,6 +240,7 @@ class AlarmModel { guardian: map['guardian'], isCall: map['isCall'] == 1, ringOn: map['ringOn'] == 1, + challengeTimeLimit: map['challengeTimeLimit'], ); } @@ -283,6 +293,7 @@ class AlarmModel { 'guardianTimer': guardianTimer, 'guardian': guardian, 'isCall': isCall ? 1 : 0, + 'challengeTimeLimit': challengeTimeLimit, }; } @@ -338,14 +349,13 @@ class AlarmModel { guardian = alarmData['guardian']; isCall = alarmData['isCall']; ringOn = alarmData['ringOn']; - } - AlarmModel.fromJson(String alarmData, UserModel? user) { - AlarmModel.fromMap(jsonDecode(alarmData)); + // Read challengeTimeLimit if available. + challengeTimeLimit = alarmData['challengeTimeLimit']; } - static String toJson(AlarmModel alarmRecord) { - return jsonEncode(AlarmModel.toMap(alarmRecord)); + String toJson() { + return jsonEncode(AlarmModel.toMap(this)); } static Map toMap(AlarmModel alarmRecord) { @@ -390,12 +400,14 @@ class AlarmModel { 'volMax': alarmRecord.volMax, 'activityMonitor': alarmRecord.activityMonitor, 'alarmDate': alarmRecord.alarmDate, + 'ringOn': alarmRecord.ringOn, 'profile': alarmRecord.profile, 'isGuardian': alarmRecord.isGuardian, 'guardianTimer': alarmRecord.guardianTimer, 'guardian': alarmRecord.guardian, 'isCall': alarmRecord.isCall, - 'ringOn': alarmRecord.ringOn + 'ringOn': alarmRecord.ringOn, + 'challengeTimeLimit': alarmRecord.challengeTimeLimit, }; if (alarmRecord.isSharedAlarmEnabled) { diff --git a/lib/app/modules/settings/views/time_imit_view.dart b/lib/app/modules/settings/views/time_limit_view.dart similarity index 100% rename from lib/app/modules/settings/views/time_imit_view.dart rename to lib/app/modules/settings/views/time_limit_view.dart From 8d134d55a81d74ab85ebf4e3385ac430b47e8e66 Mon Sep 17 00:00:00 2001 From: mahendra-918 Date: Mon, 10 Mar 2025 20:30:40 +0530 Subject: [PATCH 09/10] changes --- lib/app/data/models/alarm_model.dart | 4 --- .../controllers/settings_controller.dart | 26 ------------------- .../settings/views/time_limit_view.dart | 2 -- 3 files changed, 32 deletions(-) diff --git a/lib/app/data/models/alarm_model.dart b/lib/app/data/models/alarm_model.dart index 915a8134..374e143c 100644 --- a/lib/app/data/models/alarm_model.dart +++ b/lib/app/data/models/alarm_model.dart @@ -418,17 +418,13 @@ class AlarmModel { } String boolListToString(List boolList) { - // Rotate the list to start with Sunday var rotatedList = [boolList.last] + boolList.sublist(0, boolList.length - 1); - // Convert the list of bools to a string of 1s and 0s return rotatedList.map((b) => b ? '1' : '0').join(); } List stringToBoolList(String s) { - // Rotate the string to start with Monday final rotatedString = s.substring(1) + s[0]; - // Convert the rotated string to a list of boolean values return rotatedString.split('').map((c) => c == '1').toList(); } } diff --git a/lib/app/modules/settings/controllers/settings_controller.dart b/lib/app/modules/settings/controllers/settings_controller.dart index 472f3fa1..cc666abf 100644 --- a/lib/app/modules/settings/controllers/settings_controller.dart +++ b/lib/app/modules/settings/controllers/settings_controller.dart @@ -92,24 +92,18 @@ class SettingsController extends GetxController { void updateTimeLimit(int newLimit) { challengeTimeLimit.value = newLimit; - // Ensure the updated limit is saved in the alarm record if it exists if (alarmRecord != null) { alarmRecord!.challengeTimeLimit = newLimit; } - // Save the updated global challenge time limit _secureStorageProvider.writeChallengeTimeLimit(newLimit); } void saveSettings() { if (alarmRecord != null) { alarmRecord!.challengeTimeLimit = challengeTimeLimit.value; - // Save the updated alarmRecord to persistent storage or backend } - // Save the updated global challenge time limit _secureStorageProvider.writeChallengeTimeLimit(challengeTimeLimit.value); } - - // Logins user using GoogleSignIn Future logoutGoogle() async { await GoogleCloudProvider.logoutGoogle(); await SecureStorageProvider().deleteUserModel(); @@ -126,13 +120,9 @@ class SettingsController extends GetxController { getKey(ApiKeys key) async { return await _secureStorageProvider.retrieveApiKey(key); } - - // Add weather state to the flutter secure storage addWeatherState(String weatherState) async { await _secureStorageProvider.storeWeatherState(weatherState); } - - // Get weather state from the flutter secure storage getWeatherState() async { return await _secureStorageProvider.retrieveWeatherState(); } @@ -140,7 +130,6 @@ class SettingsController extends GetxController { Future isApiKeyValid(String apiKey) async { final weather = WeatherFactory(apiKey); try { - // ignore: unused_local_variable final currentWeather = await weather.currentWeatherByLocation( currentPoint.value.latitude, currentPoint.value.longitude, @@ -167,29 +156,22 @@ class SettingsController extends GetxController { Future _checkAndRequestPermission({bool? background}) async { if (!await FlLocation.isLocationServicesEnabled) { - // Location services are disabled. return false; } var locationPermission = await FlLocation.checkLocationPermission(); if (locationPermission == LocationPermission.deniedForever) { - // Cannot request runtime permission because location permission is denied forever. return false; } else if (locationPermission == LocationPermission.denied) { - // Ask the user for location permission. locationPermission = await FlLocation.requestLocationPermission(); if (locationPermission == LocationPermission.denied || locationPermission == LocationPermission.deniedForever) return false; } - - // Location permission must always be allowed (LocationPermission.always) - // to collect location data in the background. if (background == true && locationPermission == LocationPermission.whileInUse) return false; - // Location services have been enabled and permissions have been granted. return true; } @@ -204,18 +186,10 @@ class SettingsController extends GetxController { .readSortedAlarmListValue(key: _sortedAlarmListKey); currentLanguage.value = await storage.readCurrentLanguage(); - - // Store the retrieved API key from flutter secure storage. String? retrievedAPIKey = await getKey(ApiKeys.openWeatherMap); - - // If the API key has been previously stored. if (retrievedAPIKey != null) { - // Assign the controller's text to the retrieved API key so that - // when the user comes to update their API key, they see the previously added key. apiKey.text = retrievedAPIKey; } - - // Retrieve and update the weather state from flutter secure storage. String? retrievedWeatherState = await getWeatherState(); if (retrievedWeatherState != null) { weatherKeyState.value = WeatherKeyState.values.firstWhereOrNull( diff --git a/lib/app/modules/settings/views/time_limit_view.dart b/lib/app/modules/settings/views/time_limit_view.dart index 3d9c1d70..ec18939c 100644 --- a/lib/app/modules/settings/views/time_limit_view.dart +++ b/lib/app/modules/settings/views/time_limit_view.dart @@ -26,12 +26,10 @@ class TimeLimitView extends StatelessWidget { () => InkWell( onTap: () { Utils.hapticFeedback(); - // Store the initial value before any changes. initialTimeLimit = controller.challengeTimeLimit.value; Get.defaultDialog( onWillPop: () async { Get.back(); - // Resetting the value to its initial state if the user cancels changes. controller.challengeTimeLimit.value = initialTimeLimit; return true; }, From a228fdd1594f1e6f9a3bb350b8bc180ec85bbc12 Mon Sep 17 00:00:00 2001 From: mahendra-918 Date: Tue, 18 Mar 2025 12:47:15 +0530 Subject: [PATCH 10/10] changes --- lib/app/data/models/alarm_model.dart | 19 ++-------- .../providers/secure_storage_provider.dart | 10 +++--- .../views/alarm_challenge_view.dart | 2 +- .../controllers/settings_controller.dart | 35 ++++++++----------- .../modules/settings/views/settings_view.dart | 2 +- .../settings/views/time_limit_view.dart | 2 +- 6 files changed, 26 insertions(+), 44 deletions(-) diff --git a/lib/app/data/models/alarm_model.dart b/lib/app/data/models/alarm_model.dart index 374e143c..3866cc92 100644 --- a/lib/app/data/models/alarm_model.dart +++ b/lib/app/data/models/alarm_model.dart @@ -58,10 +58,6 @@ class AlarmModel { late int guardianTimer; late String guardian; late bool isCall; - - // New optional field for a custom challenge time limit in seconds. - int? challengeTimeLimit; - @ignore Map? offsetDetails; @@ -113,7 +109,6 @@ class AlarmModel { required this.guardianTimer, required this.guardian, required this.isCall, - this.challengeTimeLimit, }); AlarmModel.fromDocumentSnapshot({ @@ -183,11 +178,6 @@ class AlarmModel { guardianTimer = documentSnapshot['guardianTimer']; guardian = documentSnapshot['guardian']; isCall = documentSnapshot['isCall']; - - // Read the optional challengeTimeLimit if available. - challengeTimeLimit = documentSnapshot.data().toString().contains('challengeTimeLimit') - ? documentSnapshot['challengeTimeLimit'] - : null; } AlarmModel fromMapSQFlite(Map map) { @@ -240,7 +230,6 @@ class AlarmModel { guardian: map['guardian'], isCall: map['isCall'] == 1, ringOn: map['ringOn'] == 1, - challengeTimeLimit: map['challengeTimeLimit'], ); } @@ -293,7 +282,6 @@ class AlarmModel { 'guardianTimer': guardianTimer, 'guardian': guardian, 'isCall': isCall ? 1 : 0, - 'challengeTimeLimit': challengeTimeLimit, }; } @@ -349,9 +337,6 @@ class AlarmModel { guardian = alarmData['guardian']; isCall = alarmData['isCall']; ringOn = alarmData['ringOn']; - - // Read challengeTimeLimit if available. - challengeTimeLimit = alarmData['challengeTimeLimit']; } String toJson() { @@ -407,7 +392,6 @@ class AlarmModel { 'guardian': alarmRecord.guardian, 'isCall': alarmRecord.isCall, 'ringOn': alarmRecord.ringOn, - 'challengeTimeLimit': alarmRecord.challengeTimeLimit, }; if (alarmRecord.isSharedAlarmEnabled) { @@ -418,8 +402,11 @@ class AlarmModel { } String boolListToString(List boolList) { + // Rotate the list to start with Sunday var rotatedList = [boolList.last] + boolList.sublist(0, boolList.length - 1); + + // Convert the list of bools to a string of 1s and 0s return rotatedList.map((b) => b ? '1' : '0').join(); } diff --git a/lib/app/data/providers/secure_storage_provider.dart b/lib/app/data/providers/secure_storage_provider.dart index 1cc292c7..deb96449 100644 --- a/lib/app/data/providers/secure_storage_provider.dart +++ b/lib/app/data/providers/secure_storage_provider.dart @@ -215,12 +215,12 @@ class SecureStorageProvider { Future writeChallengeTimeLimit(int timeLimit) async { - await _secureStorage.write(key: 'challengeTimeLimit', value: timeLimit.toString()); - } + await _secureStorage.write(key: 'challengeTimeLimit', value: timeLimit.toString()); +} Future readChallengeTimeLimit() async { - String? timeLimit = await _secureStorage.read(key: 'challengeTimeLimit'); - return timeLimit != null ? int.parse(timeLimit) : 30; - } + String? timeLimit = await _secureStorage.read(key: 'challengeTimeLimit'); + return timeLimit != null ? int.parse(timeLimit) : 30; +} } diff --git a/lib/app/modules/alarmChallenge/views/alarm_challenge_view.dart b/lib/app/modules/alarmChallenge/views/alarm_challenge_view.dart index 6b1a11e6..d689ff50 100644 --- a/lib/app/modules/alarmChallenge/views/alarm_challenge_view.dart +++ b/lib/app/modules/alarmChallenge/views/alarm_challenge_view.dart @@ -155,7 +155,7 @@ class AlarmChallengeView extends GetView { ), Obx( () => Icon( - controller.isMathsOngoing.value == + controller.isQrOngoing.value == Status.completed ? Icons.done : Icons.arrow_forward_ios_sharp, diff --git a/lib/app/modules/settings/controllers/settings_controller.dart b/lib/app/modules/settings/controllers/settings_controller.dart index cc666abf..94ce553d 100644 --- a/lib/app/modules/settings/controllers/settings_controller.dart +++ b/lib/app/modules/settings/controllers/settings_controller.dart @@ -12,7 +12,6 @@ import 'package:fl_location/fl_location.dart'; import '../../../data/providers/get_storage_provider.dart'; import '../../../data/providers/google_cloud_api_provider.dart'; -import 'package:ultimate_alarm_clock/app/data/models/alarm_model.dart'; class SettingsController extends GetxController { HomeController homeController = Get.find(); @@ -21,6 +20,7 @@ class SettingsController extends GetxController { final _hapticFeedbackKey = 'haptic_feedback'; var is24HrsEnabled = false.obs; final _f24HrsEnabledKey = '24_hours_format'; + final RxInt challengeTimeLimit = 30.obs; var isSortedAlarmListEnabled = true.obs; final _sortedAlarmListKey = 'sorted_alarm_list'; var currentLanguage = 'en_US'.obs; @@ -64,12 +64,6 @@ class SettingsController extends GetxController { }, }; - // ChallengeSettingsController properties - final RxInt challengeTimeLimit = 30.obs; - AlarmModel? alarmRecord; - - SettingsController({this.alarmRecord}); - @override void onInit() async { super.onInit(); @@ -83,27 +77,17 @@ class SettingsController extends GetxController { } void _loadChallengeSettings() async { + // Store the retrieved challenge time limit from secure storage int storedTimeLimit = await _secureStorageProvider.readChallengeTimeLimit(); challengeTimeLimit.value = storedTimeLimit; - if (alarmRecord != null) { - alarmRecord!.challengeTimeLimit = storedTimeLimit; - } } void updateTimeLimit(int newLimit) { challengeTimeLimit.value = newLimit; - if (alarmRecord != null) { - alarmRecord!.challengeTimeLimit = newLimit; - } _secureStorageProvider.writeChallengeTimeLimit(newLimit); } - void saveSettings() { - if (alarmRecord != null) { - alarmRecord!.challengeTimeLimit = challengeTimeLimit.value; - } - _secureStorageProvider.writeChallengeTimeLimit(challengeTimeLimit.value); - } + // Logins user using GoogleSignIn Future logoutGoogle() async { await GoogleCloudProvider.logoutGoogle(); await SecureStorageProvider().deleteUserModel(); @@ -120,9 +104,11 @@ class SettingsController extends GetxController { getKey(ApiKeys key) async { return await _secureStorageProvider.retrieveApiKey(key); } + addWeatherState(String weatherState) async { await _secureStorageProvider.storeWeatherState(weatherState); } + getWeatherState() async { return await _secureStorageProvider.retrieveWeatherState(); } @@ -186,10 +172,19 @@ class SettingsController extends GetxController { .readSortedAlarmListValue(key: _sortedAlarmListKey); currentLanguage.value = await storage.readCurrentLanguage(); + + // Store the retrieved API key from the flutter secure storage String? retrievedAPIKey = await getKey(ApiKeys.openWeatherMap); + + // If the API key has been previously stored there if (retrievedAPIKey != null) { + // Assign the controller's text to the retrieved API key so that + // when the user comes to update their API key, they're able + // to see the previously added API key apiKey.text = retrievedAPIKey; } + + // Store the retrieved weather state from the flutter secure storage String? retrievedWeatherState = await getWeatherState(); if (retrievedWeatherState != null) { weatherKeyState.value = WeatherKeyState.values.firstWhereOrNull( @@ -244,4 +239,4 @@ class SettingsController extends GetxController { storage.writeCurrentLanguage(local.value); storage.writeLocale(languageCode, countryCode); } -} +} \ No newline at end of file diff --git a/lib/app/modules/settings/views/settings_view.dart b/lib/app/modules/settings/views/settings_view.dart index 0620862d..9fd3aeff 100644 --- a/lib/app/modules/settings/views/settings_view.dart +++ b/lib/app/modules/settings/views/settings_view.dart @@ -128,4 +128,4 @@ class SettingsView extends GetView { ), ); } -} +} \ No newline at end of file diff --git a/lib/app/modules/settings/views/time_limit_view.dart b/lib/app/modules/settings/views/time_limit_view.dart index ec18939c..dc3164db 100644 --- a/lib/app/modules/settings/views/time_limit_view.dart +++ b/lib/app/modules/settings/views/time_limit_view.dart @@ -56,7 +56,7 @@ class TimeLimitView extends StatelessWidget { ), ElevatedButton( onPressed: () { - controller.saveSettings(); + // controller.saveSettings(); Get.back(); }, style: ElevatedButton.styleFrom(