diff --git a/lib/app/data/models/alarm_model.dart b/lib/app/data/models/alarm_model.dart index 4bd43aad..0e2069e7 100644 --- a/lib/app/data/models/alarm_model.dart +++ b/lib/app/data/models/alarm_model.dart @@ -62,6 +62,9 @@ class AlarmModel { @ignore Map? offsetDetails; + @Index() + late DateTime lastModifiedDate; + AlarmModel( {required this.alarmTime, required this.alarmID, @@ -109,7 +112,10 @@ class AlarmModel { required this.isGuardian, required this.guardianTimer, required this.guardian, - required this.isCall}); + required this.isCall, + DateTime? lastModifiedDate}) { + this.lastModifiedDate = lastModifiedDate ?? DateTime.now(); + } AlarmModel.fromDocumentSnapshot({ required firestore.DocumentSnapshot documentSnapshot, @@ -179,6 +185,9 @@ class AlarmModel { guardianTimer = documentSnapshot['guardianTimer']; guardian = documentSnapshot['guardian']; isCall = documentSnapshot['isCall']; + lastModifiedDate = documentSnapshot['lastModifiedDate'] != null + ? (documentSnapshot['lastModifiedDate'] as firestore.Timestamp).toDate() + : DateTime.now(); } AlarmModel fromMapSQFlite(Map map) { @@ -337,7 +346,6 @@ class AlarmModel { guardianTimer = alarmData['guardianTimer']; guardian = alarmData['guardian']; isCall = alarmData['isCall']; - ringOn = alarmData['ringOn']; } AlarmModel.fromJson(String alarmData, UserModel? user) { @@ -395,7 +403,8 @@ class AlarmModel { 'guardianTimer': alarmRecord.guardianTimer, 'guardian': alarmRecord.guardian, 'isCall': alarmRecord.isCall, - 'ringOn': alarmRecord.ringOn + 'ringOn': alarmRecord.ringOn, + 'lastModifiedDate': firestore.Timestamp.fromDate(alarmRecord.lastModifiedDate), }; if (alarmRecord.isSharedAlarmEnabled) { diff --git a/lib/app/data/models/sort_model.dart b/lib/app/data/models/sort_model.dart new file mode 100644 index 00000000..3075e9f7 --- /dev/null +++ b/lib/app/data/models/sort_model.dart @@ -0,0 +1,39 @@ +enum AlarmSortMode { + defaultSort, + timeOfDay, + label, + creationDate, + lastModified, + customOrder; + + String get displayName { + switch (this) { + case AlarmSortMode.defaultSort: + return 'Smart Sort (Enabled + Next Occurrence)'; + case AlarmSortMode.timeOfDay: + return 'Time of Day'; + case AlarmSortMode.label: + return 'Alarm Label'; + case AlarmSortMode.creationDate: + return 'Creation Date'; + case AlarmSortMode.lastModified: + return 'Last Modified'; + case AlarmSortMode.customOrder: + return 'Custom Order'; + } + } +} + +enum SortDirection { + ascending, + descending; + + String get displayName { + switch (this) { + case SortDirection.ascending: + return 'Ascending'; + case SortDirection.descending: + return 'Descending'; + } + } +} \ No newline at end of file diff --git a/lib/app/data/providers/secure_storage_provider.dart b/lib/app/data/providers/secure_storage_provider.dart index 24592e8d..8d860847 100644 --- a/lib/app/data/providers/secure_storage_provider.dart +++ b/lib/app/data/providers/secure_storage_provider.dart @@ -212,4 +212,20 @@ class SecureStorageProvider { value: timerId.toString(), ); } + + Future readSortMode(String key) async { + return await _secureStorage.read(key: key); + } + + Future readSortDirection(String key) async { + return await _secureStorage.read(key: key); + } + + Future writeSortMode(String key, String value) async { + await _secureStorage.write(key: key, value: value); + } + + Future writeSortDirection(String key, String value) async { + await _secureStorage.write(key: key, value: value); + } } diff --git a/lib/app/modules/addOrUpdateAlarm/controllers/add_or_update_alarm_controller.dart b/lib/app/modules/addOrUpdateAlarm/controllers/add_or_update_alarm_controller.dart index cdc9a591..1a40b3c7 100644 --- a/lib/app/modules/addOrUpdateAlarm/controllers/add_or_update_alarm_controller.dart +++ b/lib/app/modules/addOrUpdateAlarm/controllers/add_or_update_alarm_controller.dart @@ -1075,6 +1075,7 @@ class AddOrUpdateAlarmController extends GetxController { guardian: guardian.value, isCall: isCall.value, ringOn: isFutureDate.value, + lastModifiedDate: DateTime.now(), ); } @@ -1351,7 +1352,6 @@ class AddOrUpdateAlarmController extends GetxController { storage.writeProfile(profileModel.profileName); homeController.writeProfileName(profileModel.profileName); } -} int orderedCountryCode(Country countryA, Country countryB) { // `??` for null safety of 'dialCode' @@ -1360,3 +1360,4 @@ class AddOrUpdateAlarmController extends GetxController { return int.parse(dialCodeA).compareTo(int.parse(dialCodeB)); } +} diff --git a/lib/app/modules/addOrUpdateAlarm/views/guardian_angel.dart b/lib/app/modules/addOrUpdateAlarm/views/guardian_angel.dart index b0315a11..804058c6 100644 --- a/lib/app/modules/addOrUpdateAlarm/views/guardian_angel.dart +++ b/lib/app/modules/addOrUpdateAlarm/views/guardian_angel.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl_phone_number_input/intl_phone_number_input.dart'; +import 'package:intl_phone_number_input/src/models/country_model.dart'; import 'package:ultimate_alarm_clock/app/modules/addOrUpdateAlarm/controllers/add_or_update_alarm_controller.dart'; import 'package:ultimate_alarm_clock/app/modules/settings/controllers/theme_controller.dart'; import 'package:ultimate_alarm_clock/app/utils/constants.dart'; @@ -17,95 +18,91 @@ class GuardianAngel extends StatelessWidget { final AddOrUpdateAlarmController controller; final ThemeController themeController; + static int orderedCountryCode(Country countryA, Country countryB) { + String dialCodeA = countryA.dialCode?.replaceAll('+', '') ?? '0'; + String dialCodeB = countryB.dialCode?.replaceAll('+', '') ?? '0'; + return int.parse(dialCodeA).compareTo(int.parse(dialCodeB)); + } + @override Widget build(BuildContext context) { - // Check if using Firestore and the current user is the owner - // and if not using, just show the tile - return Column( children: [ ListTile( onTap: () async { - var phonePerm = - await Permission.phone.request().isGranted; - var smsPerm = await Permission.sms.request().isGranted; + var phonePerm = await Permission.phone.request().isGranted; + var smsPerm = await Permission.sms.request().isGranted; - if (phonePerm && smsPerm) { - Get.dialog( - Dialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18), - ), - backgroundColor: themeController - .secondaryBackgroundColor.value, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: InternationalPhoneNumberInput( - textFieldController: controller - .contactTextEditingController, - onInputChanged: (value) {}, - onInputValidated: (value) {}, - spaceBetweenSelectorAndTextField: 0, - selectorConfig: const SelectorConfig( - showFlags: true, - setSelectorButtonAsPrefixIcon: true, - leadingPadding: 0, - trailingSpace: false, - countryComparator: orderedCountryCode, - ), - ), + if (phonePerm && smsPerm) { + Get.dialog( + Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), ), - Padding( - padding: EdgeInsets.symmetric( - vertical: controller - .homeController.scalingFactor * - 8, - horizontal: controller - .homeController.scalingFactor * - 4, - ), - child: Row( + backgroundColor: themeController.secondaryBackgroundColor.value, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Option(0, Icons.sms, 'Text'), - Option(1, Icons.call, 'Call'), - const Spacer(), - Submit(), + Padding( + padding: const EdgeInsets.all(8.0), + child: InternationalPhoneNumberInput( + textFieldController: controller.contactTextEditingController, + onInputChanged: (value) {}, + onInputValidated: (value) {}, + spaceBetweenSelectorAndTextField: 0, + selectorConfig: const SelectorConfig( + showFlags: true, + setSelectorButtonAsPrefixIcon: true, + leadingPadding: 0, + trailingSpace: false, + countryComparator: orderedCountryCode, + ), + ), + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: controller.homeController.scalingFactor * 8, + horizontal: controller.homeController.scalingFactor * 4, + ), + child: Row( + children: [ + Option(0, Icons.sms, 'Text'), + Option(1, Icons.call, 'Call'), + const Spacer(), + Submit(), + ], + ), + ), ], ), ), - ], - ), - ), - ), - ); - } - }, - title: Row( - children: [ - FittedBox( - fit: BoxFit.scaleDown, - alignment: Alignment.centerLeft, - child: Obx( - () => Text( - 'Guardian Angel'.tr, - style: TextStyle( - color: themeController.primaryTextColor.value, + ), + ); + } + }, + title: Row( + children: [ + FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: Obx( + () => Text( + 'Guardian Angel'.tr, + style: TextStyle( + color: themeController.primaryTextColor.value, + ), ), ), ), - ), Obx( () => IconButton( icon: Icon( - Icons.info_sharp, - size: 21, - color: themeController.primaryTextColor.value.withOpacity(0.3), - ), + Icons.info_sharp, + size: 21, + color: themeController.primaryTextColor.value.withOpacity(0.3), + ), onPressed: () { Utils.showModal( context: context, diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index edcabf86..4e3c8404 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -19,6 +19,8 @@ import 'package:ultimate_alarm_clock/app/data/providers/secure_storage_provider. import 'package:ultimate_alarm_clock/app/modules/settings/controllers/theme_controller.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/models/sort_model.dart'; +import 'package:ultimate_alarm_clock/app/modules/settings/controllers/settings_controller.dart'; import '../../../data/models/profile_model.dart'; import '../../../data/providers/google_cloud_api_provider.dart'; @@ -152,74 +154,7 @@ class HomeController extends GetxController { ...latestFirestoreAlarms, ...latestIsarAlarms, ]; - - if (isSortedAlarmListEnabled.value) { - alarms.sort((a, b) { - final String timeA = a.alarmTime; - final String timeB = b.alarmTime; - - // Convert the alarm time strings to DateTime objects for comparison - DateTime dateTimeA = DateFormat('HH:mm').parse(timeA); - DateTime dateTimeB = DateFormat('HH:mm').parse(timeB); - - // Compare the DateTime objects to sort in ascending order - return dateTimeA.compareTo(dateTimeB); - }); - } else { - alarms.sort((a, b) { - // First sort by isEnabled - if (a.isEnabled != b.isEnabled) { - return a.isEnabled ? -1 : 1; - } - - // Then sort by upcoming time - int aUpcomingTime = a.minutesSinceMidnight; - int bUpcomingTime = b.minutesSinceMidnight; - - // Check if alarm repeats on any day - bool aRepeats = a.days.any((day) => day); - bool bRepeats = b.days.any((day) => day); - - // If alarm repeats on any day, find the next up+coming day - if (aRepeats) { - int currentDay = DateTime.now().weekday - 1; - for (int i = 0; i < a.days.length; i++) { - int dayIndex = (currentDay + i) % a.days.length; - if (a.days[dayIndex]) { - aUpcomingTime += i * Duration.minutesPerDay; - break; - } - } - } else { - // If alarm is one-time and has already passed, set upcoming time - // to next day - if (aUpcomingTime <= - DateTime.now().hour * 60 + DateTime.now().minute) { - aUpcomingTime += Duration.minutesPerDay; - } - } - - if (bRepeats) { - int currentDay = DateTime.now().weekday - 1; - for (int i = 0; i < b.days.length; i++) { - int dayIndex = (currentDay + i) % b.days.length; - if (b.days[dayIndex]) { - bUpcomingTime += i * Duration.minutesPerDay; - break; - } - } - } else { - // If alarm is one-time and has already passed, set upcoming time - // to next day - if (bUpcomingTime <= - DateTime.now().hour * 60 + DateTime.now().minute) { - bUpcomingTime += Duration.minutesPerDay; - } - } - - return aUpcomingTime.compareTo(bUpcomingTime); - }); - } + sortAlarms(alarms); return alarms; }, @@ -735,4 +670,128 @@ class HomeController extends GetxController { isCall: profileModel.value.isCall, ringOn: false); } + + void sortAlarms(List alarms) { + final settingsController = Get.find(); + + if (!settingsController.isSortedAlarmListEnabled.value) { + return; + } + List sortedAlarms = List.from(alarms); + + switch (settingsController.currentSortMode.value) { + case AlarmSortMode.defaultSort: + _defaultSort(sortedAlarms); + break; + case AlarmSortMode.timeOfDay: + _timeOfDaySort(sortedAlarms); + break; + case AlarmSortMode.label: + _labelSort(sortedAlarms); + break; + case AlarmSortMode.creationDate: + _creationDateSort(sortedAlarms); + break; + case AlarmSortMode.lastModified: + _lastModifiedSort(sortedAlarms); + break; + case AlarmSortMode.customOrder: + break; + } + if (settingsController.currentSortDirection.value == SortDirection.descending) { + sortedAlarms = sortedAlarms.reversed.toList(); + } + alarms.clear(); + alarms.addAll(sortedAlarms); + } + + void _defaultSort(List alarms) { + alarms.sort((a, b) { + + if (a.isEnabled != b.isEnabled) { + return a.isEnabled ? -1 : 1; + } + + + return _compareUpcomingTime(a, b); + }); + } + + void _timeOfDaySort(List alarms) { + alarms.sort((a, b) { + return a.minutesSinceMidnight.compareTo(b.minutesSinceMidnight); + }); + } + + void _labelSort(List alarms) { + alarms.sort((a, b) { + return (a.label ?? '').compareTo(b.label ?? ''); + }); + } + + void _creationDateSort(List alarms) { + alarms.sort((a, b) { + return b.alarmID.compareTo(a.alarmID); + }); + } + + void _lastModifiedSort(List alarms) { + alarms.sort((a, b) { + return b.lastModifiedDate.compareTo(a.lastModifiedDate); + }); + } + + int _compareUpcomingTime(AlarmModel a, AlarmModel b) { + int aUpcomingTime = a.minutesSinceMidnight; + int bUpcomingTime = b.minutesSinceMidnight; + + + bool aRepeats = a.days.any((day) => day); + bool bRepeats = b.days.any((day) => day); + + + if (aRepeats) { + aUpcomingTime = _calculateNextOccurrence(a); + } else if (aUpcomingTime <= DateTime.now().hour * 60 + DateTime.now().minute) { + aUpcomingTime += Duration.minutesPerDay; + } + + if (bRepeats) { + bUpcomingTime = _calculateNextOccurrence(b); + } else if (bUpcomingTime <= DateTime.now().hour * 60 + DateTime.now().minute) { + bUpcomingTime += Duration.minutesPerDay; + } + + return aUpcomingTime.compareTo(bUpcomingTime); + } + + int _calculateNextOccurrence(AlarmModel alarm) { + int currentDay = DateTime.now().weekday - 1; + int minutesSinceMidnight = alarm.minutesSinceMidnight; + int currentTimeInMinutes = DateTime.now().hour * 60 + DateTime.now().minute; + + + for (int i = 0; i < alarm.days.length; i++) { + int dayIndex = (currentDay + i) % alarm.days.length; + if (alarm.days[dayIndex]) { + if (i == 0 && minutesSinceMidnight <= currentTimeInMinutes) { + continue; + } + return minutesSinceMidnight + i * Duration.minutesPerDay; + } + } + + for (int i = 0; i < alarm.days.length; i++) { + if (alarm.days[i]) { + return minutesSinceMidnight + (7 - currentDay + i) * Duration.minutesPerDay; + } + } + + return minutesSinceMidnight; + } + + void refreshAlarmList() { + + update(); + } } diff --git a/lib/app/modules/settings/controllers/settings_controller.dart b/lib/app/modules/settings/controllers/settings_controller.dart index 5db0c333..c8b23668 100644 --- a/lib/app/modules/settings/controllers/settings_controller.dart +++ b/lib/app/modules/settings/controllers/settings_controller.dart @@ -3,6 +3,7 @@ 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/models/sort_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'; @@ -65,6 +66,12 @@ class SettingsController extends GetxController { }, }; + final _sortModeKey = 'sortMode'; + final _sortDirectionKey = 'sortDirection'; + + final Rx currentSortMode = AlarmSortMode.defaultSort.obs; + final Rx currentSortDirection = SortDirection.ascending.obs; + @override void onInit() async { super.onInit(); @@ -74,6 +81,17 @@ class SettingsController extends GetxController { userModel.value = await _secureStorageProvider.retrieveUserModel(); } _loadPreference(); + + String? savedSortMode = await _secureStorageProvider.readSortMode(_sortModeKey); + String? savedSortDirection = await _secureStorageProvider.readSortDirection(_sortDirectionKey); + + currentSortMode.value = savedSortMode != null + ? AlarmSortMode.values.firstWhere((e) => e.name == savedSortMode) + : AlarmSortMode.defaultSort; + + currentSortDirection.value = savedSortDirection != null + ? SortDirection.values.firstWhere((e) => e.name == savedSortDirection) + : SortDirection.ascending; } // Logins user using GoogleSignIn @@ -242,4 +260,27 @@ class SettingsController extends GetxController { storage.writeCurrentLanguage(local.value); storage.writeLocale(languageCode, countryCode); } + + void _saveSortPreferences() async { + await _secureStorageProvider.writeSortMode( + _sortModeKey, + currentSortMode.value.name, + ); + await _secureStorageProvider.writeSortDirection( + _sortDirectionKey, + currentSortDirection.value.name, + ); + } + + void updateSortMode(AlarmSortMode mode) { + currentSortMode.value = mode; + _saveSortPreferences(); + homeController.refreshAlarmList(); + } + + void updateSortDirection(SortDirection direction) { + currentSortDirection.value = direction; + _saveSortPreferences(); + homeController.refreshAlarmList(); + } } diff --git a/lib/app/modules/settings/views/settings_view.dart b/lib/app/modules/settings/views/settings_view.dart index 680430cd..e09ecc8e 100644 --- a/lib/app/modules/settings/views/settings_view.dart +++ b/lib/app/modules/settings/views/settings_view.dart @@ -12,6 +12,8 @@ import 'package:ultimate_alarm_clock/app/modules/settings/views/theme_value_tile import 'package:ultimate_alarm_clock/app/utils/utils.dart'; import '../controllers/settings_controller.dart'; import 'google_sign_in.dart'; +import 'package:ultimate_alarm_clock/app/modules/settings/views/sort_options_view.dart'; +import 'package:ultimate_alarm_clock/app/modules/settings/controllers/theme_controller.dart'; class SettingsView extends GetView { const SettingsView({super.key}); @@ -114,6 +116,15 @@ class SettingsView extends GetView { const SizedBox( height: 20, ), + Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: SortOptionsView( + controller: controller, + themeController: Get.find(), + height: height, + width: width, + ), + ), ], ), ), diff --git a/lib/app/modules/settings/views/sort_options_view.dart b/lib/app/modules/settings/views/sort_options_view.dart new file mode 100644 index 00000000..7c6082ee --- /dev/null +++ b/lib/app/modules/settings/views/sort_options_view.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ultimate_alarm_clock/app/data/models/sort_model.dart'; +import 'package:ultimate_alarm_clock/app/modules/settings/controllers/settings_controller.dart'; +import 'package:ultimate_alarm_clock/app/modules/settings/controllers/theme_controller.dart'; +import 'package:ultimate_alarm_clock/app/utils/constants.dart'; + +class SortOptionsView extends StatelessWidget { + final SettingsController controller; + final ThemeController themeController; + final double height; + final double width; + + const SortOptionsView({ + super.key, + required this.controller, + required this.themeController, + required this.height, + required this.width, + }); + + @override + Widget build(BuildContext context) { + return Obx( + () => Container( + width: width * 0.91, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(18)), + color: themeController.secondaryBackgroundColor.value, + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Sort Options'.tr, + style: Theme.of(context).textTheme.titleMedium!.copyWith( + color: themeController.primaryTextColor.value, + ), + ), + const SizedBox(height: 15), + + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Enable Sorting'.tr, + style: Theme.of(context).textTheme.bodyLarge!.copyWith( + color: themeController.primaryTextColor.value, + ), + ), + Switch.adaptive( + value: controller.isSortedAlarmListEnabled.value, + activeColor: ksecondaryColor, + onChanged: (bool value) { + controller.toggleSortedAlarmList(value); + }, + ), + ], + ), + const SizedBox(height: 10), + + if (controller.isSortedAlarmListEnabled.value) ...[ + Text( + 'Sort By'.tr, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: themeController.primaryTextColor.value, + ), + ), + const SizedBox(height: 5), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: themeController.primaryBackgroundColor.value, + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + value: controller.currentSortMode.value, + isExpanded: true, + dropdownColor: themeController.primaryBackgroundColor.value, + padding: const EdgeInsets.symmetric(horizontal: 15), + items: AlarmSortMode.values.map((mode) { + return DropdownMenuItem( + value: mode, + child: Text( + mode.displayName, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: themeController.primaryTextColor.value, + ), + ), + ); + }).toList(), + onChanged: (mode) { + if (mode != null) controller.updateSortMode(mode); + }, + ), + ), + ), + const SizedBox(height: 15), + + if (controller.currentSortMode.value != AlarmSortMode.customOrder) ...[ + Text( + 'Direction'.tr, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: themeController.primaryTextColor.value, + ), + ), + const SizedBox(height: 5), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: themeController.primaryBackgroundColor.value, + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + value: controller.currentSortDirection.value, + isExpanded: true, + dropdownColor: themeController.primaryBackgroundColor.value, + padding: const EdgeInsets.symmetric(horizontal: 15), + items: SortDirection.values.map((direction) { + return DropdownMenuItem( + value: direction, + child: Text( + direction.displayName, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: themeController.primaryTextColor.value, + ), + ), + ); + }).toList(), + onChanged: (direction) { + if (direction != null) { + controller.updateSortDirection(direction); + } + }, + ), + ), + ), + ], + ], + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/app/utils/utils.dart b/lib/app/utils/utils.dart index 53c16127..b58586ad 100644 --- a/lib/app/utils/utils.dart +++ b/lib/app/utils/utils.dart @@ -76,6 +76,7 @@ class Utils { guardian: '', isCall: false, ringOn: false, + lastModifiedDate: DateTime.now(), ); static String formatDateTimeToHHMMSS(DateTime dateTime) {