diff --git a/landing/.vitepress/config.ts b/landing/.vitepress/config.ts index 0072448..97dea48 100644 --- a/landing/.vitepress/config.ts +++ b/landing/.vitepress/config.ts @@ -44,6 +44,12 @@ export default defineConfig({ { text: 'Configuration', link: '/docs/guide/configuration' }, { text: 'Themes', link: '/docs/guide/themes' } ] + }, + { + text: 'Updates', + items: [ + { text: 'Changelog', link: '/docs/changelog' } + ] } ] }, diff --git a/landing/docs/changelog.md b/landing/docs/changelog.md new file mode 100644 index 0000000..bf2c024 --- /dev/null +++ b/landing/docs/changelog.md @@ -0,0 +1,35 @@ +# Changelog + +All notable changes to Keep Track will be documented in this page. + +## [Unreleased] + +### Fixed + +#### Notification Settings Screen Error +- **Issue**: Opening the Notification Settings screen would display "Error loading settings" with a `PlatformException: Missing type parameter` error +- **Cause**: The `flutter_local_notifications` plugin's internal cache (stored in SharedPreferences) became corrupted, containing notification data with missing required fields +- **Solution**: Added error handling in the notification service to gracefully catch and recover from corrupted notification cache errors +- **Files Changed**: + - `lib/core/services/notification/notification_service.dart` - Added try-catch around `cancelNotification()` and `cancelAllNotifications()` methods + - `lib/features/notifications/presentation/state/notification_settings_controller.dart` - Added error handling in `_applySettings()` to prevent settings load failures + +**Workaround for existing users**: If you still experience issues after updating, clear the app data from your device settings (Settings > Apps > Keep Track > Storage > Clear Data). This will reset the corrupted notification cache. + +--- + +## [0.7.4] - 2025-01-25 + +### Added +- Build workflow updates +- Local version updates for workflows + +### Fixed +- Navigation counter bug for pomodoro +- Removed unnecessary assets and fixed security risk issue on workflow + +--- + +## Previous Releases + +For older releases, please check the [GitHub Releases](https://github.com/Khesir/KeepTrack/releases) page. diff --git a/lib/core/services/notification/notification_service.dart b/lib/core/services/notification/notification_service.dart index 21ed52c..fe16f76 100644 --- a/lib/core/services/notification/notification_service.dart +++ b/lib/core/services/notification/notification_service.dart @@ -307,15 +307,53 @@ class NotificationService { Future cancelNotification(int id) async { if (!_initialized || _plugin == null) return; - await _plugin!.cancel(id); - AppLogger.info('NotificationService: Notification cancelled - ID: $id'); + try { + await _plugin!.cancel(id); + AppLogger.info('NotificationService: Notification cancelled - ID: $id'); + } catch (e, stackTrace) { + // Handle corrupted notification cache (Missing type parameter error) + AppLogger.warning( + 'NotificationService: Failed to cancel notification $id, attempting cache clear', + ); + await _clearNotificationCacheOnError(e, stackTrace); + } } /// Cancel all notifications Future cancelAllNotifications() async { if (!_initialized || _plugin == null) return; - await _plugin!.cancelAll(); - AppLogger.info('NotificationService: All notifications cancelled'); + try { + await _plugin!.cancelAll(); + AppLogger.info('NotificationService: All notifications cancelled'); + } catch (e, stackTrace) { + // Handle corrupted notification cache + AppLogger.warning( + 'NotificationService: Failed to cancel all notifications, attempting cache clear', + ); + await _clearNotificationCacheOnError(e, stackTrace); + } + } + + /// Handle corrupted notification cache by clearing it + Future _clearNotificationCacheOnError(Object error, StackTrace stackTrace) async { + AppLogger.error('NotificationService: Notification cache error', error, stackTrace); + + // On Android, try to clear the notification cache + if (Platform.isAndroid && _plugin != null) { + try { + final androidPlugin = _plugin!.resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>(); + if (androidPlugin != null) { + // Clear all notifications from the system + await androidPlugin.cancelAll(); + AppLogger.info('NotificationService: Cleared all notifications via Android plugin'); + } + } catch (e2) { + AppLogger.error('NotificationService: Could not clear notification cache', e2, stackTrace); + // The corrupted cache is stored in SharedPreferences + // User may need to clear app data from device settings + } + } } } diff --git a/lib/features/notifications/presentation/state/notification_settings_controller.dart b/lib/features/notifications/presentation/state/notification_settings_controller.dart index c038e9c..4f1fd8c 100644 --- a/lib/features/notifications/presentation/state/notification_settings_controller.dart +++ b/lib/features/notifications/presentation/state/notification_settings_controller.dart @@ -106,16 +106,24 @@ class NotificationSettingsController /// Apply settings to scheduler Future _applySettings(NotificationSettings settings) async { - await _scheduler.rescheduleAllDailyReminders( - financeEnabled: settings.financeReminderEnabled, - financeTime: settings.financeReminderTime, - morningEnabled: settings.morningReminderEnabled, - morningTime: settings.morningReminderTime, - eveningEnabled: settings.eveningReminderEnabled, - eveningTime: settings.eveningReminderTime, - ); - - AppLogger.info('NotificationSettingsController: Settings applied'); + try { + await _scheduler.rescheduleAllDailyReminders( + financeEnabled: settings.financeReminderEnabled, + financeTime: settings.financeReminderTime, + morningEnabled: settings.morningReminderEnabled, + morningTime: settings.morningReminderTime, + eveningEnabled: settings.eveningReminderEnabled, + eveningTime: settings.eveningReminderTime, + ); + AppLogger.info('NotificationSettingsController: Settings applied'); + } catch (e, stackTrace) { + // Log but don't fail - settings can still be saved even if scheduling fails + AppLogger.error( + 'NotificationSettingsController: Failed to apply notification schedules', + e, + stackTrace, + ); + } } /// Reset all settings to defaults