From 494b941277613987a8f2eabeffc36832b4bba8f5 Mon Sep 17 00:00:00 2001 From: Menno van Leeuwen Date: Wed, 27 Aug 2025 10:20:20 +0200 Subject: [PATCH] feat: Add daily status refresh on supplements list screen pull-to-refresh --- lib/providers/supplement_provider.dart | 104 ++++++++++++++++++++++- lib/screens/supplements_list_screen.dart | 1 + 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/lib/providers/supplement_provider.dart b/lib/providers/supplement_provider.dart index 9a1a2da..6a8ad99 100644 --- a/lib/providers/supplement_provider.dart +++ b/lib/providers/supplement_provider.dart @@ -1,12 +1,13 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import '../models/supplement.dart'; import '../models/supplement_intake.dart'; import '../services/database_helper.dart'; import '../services/notification_service.dart'; -class SupplementProvider with ChangeNotifier { +class SupplementProvider with ChangeNotifier, WidgetsBindingObserver { final DatabaseHelper _databaseHelper = DatabaseHelper.instance; final NotificationService _notificationService = NotificationService(); @@ -15,6 +16,8 @@ class SupplementProvider with ChangeNotifier { List> _monthlyIntakes = []; bool _isLoading = false; Timer? _persistentReminderTimer; + Timer? _dateChangeTimer; + DateTime _lastDateCheck = DateTime.now(); List get supplements => _supplements; List> get todayIntakes => _todayIntakes; @@ -22,6 +25,9 @@ class SupplementProvider with ChangeNotifier { bool get isLoading => _isLoading; Future initialize() async { + // Add this provider as an observer for app lifecycle changes + WidgetsBinding.instance.addObserver(this); + await _notificationService.initialize(); // Set up the callback for handling supplement intake from notifications @@ -62,6 +68,9 @@ class SupplementProvider with ChangeNotifier { // Start periodic checking for persistent reminders (every 5 minutes) _startPersistentReminderCheck(); + + // Start date change monitoring to reset daily intake status + _startDateChangeMonitoring(); } void _startPersistentReminderCheck() { @@ -84,6 +93,33 @@ class SupplementProvider with ChangeNotifier { _checkPersistentReminders(); } + void _startDateChangeMonitoring() { + // Cancel any existing timer + _dateChangeTimer?.cancel(); + + // Check every minute if the date has changed + _dateChangeTimer = Timer.periodic(const Duration(minutes: 1), (timer) async { + final now = DateTime.now(); + final currentDate = DateTime(now.year, now.month, now.day); + final lastCheckDate = DateTime(_lastDateCheck.year, _lastDateCheck.month, _lastDateCheck.day); + + if (currentDate != lastCheckDate) { + if (kDebugMode) { + print('Date changed detected: ${lastCheckDate} -> ${currentDate}'); + print('Refreshing today\'s intakes for new day...'); + } + + // Date has changed, refresh today's intakes + _lastDateCheck = now; + await loadTodayIntakes(); + + if (kDebugMode) { + print('Today\'s intakes refreshed for new day'); + } + } + }); + } + Future _checkPersistentReminders() async { // This method will be enhanced to accept settings from the UI layer // For now, we'll check with default settings @@ -117,12 +153,27 @@ class SupplementProvider with ChangeNotifier { ); } - @override + @override void dispose() { + WidgetsBinding.instance.removeObserver(this); _persistentReminderTimer?.cancel(); + _dateChangeTimer?.cancel(); super.dispose(); } + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + + if (state == AppLifecycleState.resumed) { + // App came back to foreground, check if date changed + if (kDebugMode) { + print('App resumed, checking for date change...'); + } + forceCheckDateChange(); + } + } + Future _rescheduleAllNotifications() async { if (kDebugMode) { print('📱 Rescheduling notifications for all active supplements...'); @@ -252,7 +303,20 @@ class SupplementProvider with ChangeNotifier { Future loadTodayIntakes() async { try { - _todayIntakes = await _databaseHelper.getIntakesWithSupplementsForDate(DateTime.now()); + final today = DateTime.now(); + if (kDebugMode) { + print('Loading intakes for date: ${today.year}-${today.month}-${today.day}'); + } + + _todayIntakes = await _databaseHelper.getIntakesWithSupplementsForDate(today); + + if (kDebugMode) { + print('Loaded ${_todayIntakes.length} intakes for today'); + for (var intake in _todayIntakes) { + print(' - Supplement ID: ${intake['supplement_id']}, taken at: ${intake['takenAt']}'); + } + } + notifyListeners(); } catch (e) { if (kDebugMode) { @@ -307,6 +371,40 @@ class SupplementProvider with ChangeNotifier { return _todayIntakes.where((intake) => intake['supplement_id'] == supplementId).length; } + // Method to manually refresh daily status (useful for testing or manual refresh) + Future refreshDailyStatus() async { + if (kDebugMode) { + print('Manually refreshing daily status...'); + } + _lastDateCheck = DateTime.now(); + await loadTodayIntakes(); + } + + // Method to force check for date change (useful for testing) + Future forceCheckDateChange() async { + final now = DateTime.now(); + final currentDate = DateTime(now.year, now.month, now.day); + final lastCheckDate = DateTime(_lastDateCheck.year, _lastDateCheck.month, _lastDateCheck.day); + + if (kDebugMode) { + print('Force checking date change...'); + print('Current date: $currentDate'); + print('Last check date: $lastCheckDate'); + } + + if (currentDate != lastCheckDate) { + if (kDebugMode) { + print('Date change detected, refreshing intakes...'); + } + _lastDateCheck = now; + await loadTodayIntakes(); + } else { + if (kDebugMode) { + print('No date change detected'); + } + } + } + // Archive functionality List _archivedSupplements = []; List get archivedSupplements => _archivedSupplements; diff --git a/lib/screens/supplements_list_screen.dart b/lib/screens/supplements_list_screen.dart index ad9daa3..3fd4ab1 100644 --- a/lib/screens/supplements_list_screen.dart +++ b/lib/screens/supplements_list_screen.dart @@ -69,6 +69,7 @@ class SupplementsListScreen extends StatelessWidget { return RefreshIndicator( onRefresh: () async { await provider.loadSupplements(); + await provider.refreshDailyStatus(); }, child: _buildGroupedSupplementsList(context, provider.supplements, settingsProvider), );