Add detailed logging and UI refresh for inventory sync
🔍 Debug Improvements: - Added detailed logging to track sync events - Print statements show: items received, added, updated, deleted - Logs Firebase connection status and errors - Easier to diagnose sync issues 🔄 UI Refresh Fix: - Added callback system to notify UI when sync occurs - HomeScreen invalidates providers after Firebase sync - UI now automatically refreshes when items sync - No manual refresh needed! 📝 Logging Output: - 📡 Starting Firebase sync for household: {id} - 🔄 Received {count} items from Firebase - ➕ Added new item from Firebase: {name} - 🔄 Updated item from Firebase: {name} - 🗑️ Deleting {count} items no longer in Firebase - ✅ UI refreshed after Firebase sync ✅ Build Status: - APK: 63.4MB - All tests passing - Ready for testing 🎯 How to Test: 1. Install on both phones 2. Check console logs (adb logcat) 3. Add item on Phone A 4. Watch logs on Phone B - should see sync messages 5. If no sync messages → Firebase not configured correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_syncService.removeSyncCallback(_onItemsSync);
|
||||||
_syncService.stopSync();
|
_syncService.stopSync();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
@@ -36,6 +37,9 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
|
|||||||
final settings = await HiveDatabase.getSettings();
|
final settings = await HiveDatabase.getSettings();
|
||||||
if (settings.currentHouseholdId != null) {
|
if (settings.currentHouseholdId != null) {
|
||||||
try {
|
try {
|
||||||
|
// Register callback to refresh UI when items sync
|
||||||
|
_syncService.addSyncCallback(_onItemsSync);
|
||||||
|
|
||||||
await _syncService.startSync(settings.currentHouseholdId!);
|
await _syncService.startSync(settings.currentHouseholdId!);
|
||||||
print('🔄 Started syncing inventory for household: ${settings.currentHouseholdId}');
|
print('🔄 Started syncing inventory for household: ${settings.currentHouseholdId}');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -44,6 +48,15 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onItemsSync() {
|
||||||
|
if (mounted) {
|
||||||
|
// Refresh all inventory providers when Firebase syncs
|
||||||
|
ref.invalidate(itemCountProvider);
|
||||||
|
ref.invalidate(expiringSoonProvider);
|
||||||
|
print('✅ UI refreshed after Firebase sync');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final itemCount = ref.watch(itemCountProvider);
|
final itemCount = ref.watch(itemCountProvider);
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import '../../../data/local/hive_database.dart';
|
import '../../../data/local/hive_database.dart';
|
||||||
import '../../inventory/models/food_item.dart';
|
import '../../inventory/models/food_item.dart';
|
||||||
|
|
||||||
@@ -7,18 +8,39 @@ import '../../inventory/models/food_item.dart';
|
|||||||
class InventorySyncService {
|
class InventorySyncService {
|
||||||
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
||||||
StreamSubscription? _itemsSubscription;
|
StreamSubscription? _itemsSubscription;
|
||||||
|
final _syncCallbacks = <VoidCallback>[];
|
||||||
|
|
||||||
|
/// Register a callback to be called when sync occurs
|
||||||
|
void addSyncCallback(VoidCallback callback) {
|
||||||
|
_syncCallbacks.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove a sync callback
|
||||||
|
void removeSyncCallback(VoidCallback callback) {
|
||||||
|
_syncCallbacks.remove(callback);
|
||||||
|
}
|
||||||
|
|
||||||
/// Start listening to household items from Firebase
|
/// Start listening to household items from Firebase
|
||||||
Future<void> startSync(String householdId) async {
|
Future<void> startSync(String householdId) async {
|
||||||
await stopSync(); // Stop any existing subscription
|
await stopSync(); // Stop any existing subscription
|
||||||
|
|
||||||
|
print('📡 Starting Firebase sync for household: $householdId');
|
||||||
|
|
||||||
_itemsSubscription = _firestore
|
_itemsSubscription = _firestore
|
||||||
.collection('households')
|
.collection('households')
|
||||||
.doc(householdId)
|
.doc(householdId)
|
||||||
.collection('items')
|
.collection('items')
|
||||||
.snapshots()
|
.snapshots()
|
||||||
.listen((snapshot) async {
|
.listen((snapshot) async {
|
||||||
|
print('🔄 Received ${snapshot.docs.length} items from Firebase');
|
||||||
await _handleItemsUpdate(snapshot, householdId);
|
await _handleItemsUpdate(snapshot, householdId);
|
||||||
|
|
||||||
|
// Notify listeners
|
||||||
|
for (final callback in _syncCallbacks) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}, onError: (error) {
|
||||||
|
print('❌ Firebase sync error: $error');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,10 +55,13 @@ class InventorySyncService {
|
|||||||
QuerySnapshot snapshot,
|
QuerySnapshot snapshot,
|
||||||
String householdId,
|
String householdId,
|
||||||
) async {
|
) async {
|
||||||
|
print('📦 Processing ${snapshot.docs.length} items from Firebase');
|
||||||
final box = await HiveDatabase.getFoodBox();
|
final box = await HiveDatabase.getFoodBox();
|
||||||
|
|
||||||
// Track Firebase item IDs
|
// Track Firebase item IDs
|
||||||
final firebaseItemIds = <String>{};
|
final firebaseItemIds = <String>{};
|
||||||
|
int newItems = 0;
|
||||||
|
int updatedItems = 0;
|
||||||
|
|
||||||
for (final doc in snapshot.docs) {
|
for (final doc in snapshot.docs) {
|
||||||
firebaseItemIds.add(doc.id);
|
firebaseItemIds.add(doc.id);
|
||||||
@@ -53,6 +78,8 @@ class InventorySyncService {
|
|||||||
if (existingItem == null) {
|
if (existingItem == null) {
|
||||||
// New item from Firebase - add to local Hive with specific key
|
// New item from Firebase - add to local Hive with specific key
|
||||||
await box.put(itemKey, item);
|
await box.put(itemKey, item);
|
||||||
|
newItems++;
|
||||||
|
print('➕ Added new item from Firebase: ${item.name} (key: $itemKey)');
|
||||||
} else {
|
} else {
|
||||||
// Update existing item if Firebase version is newer
|
// Update existing item if Firebase version is newer
|
||||||
final firebaseModified = DateTime.parse(data['lastModified'] as String);
|
final firebaseModified = DateTime.parse(data['lastModified'] as String);
|
||||||
@@ -61,11 +88,15 @@ class InventorySyncService {
|
|||||||
if (firebaseModified.isAfter(localModified)) {
|
if (firebaseModified.isAfter(localModified)) {
|
||||||
// Firebase version is newer - update local
|
// Firebase version is newer - update local
|
||||||
await box.put(itemKey, item);
|
await box.put(itemKey, item);
|
||||||
|
updatedItems++;
|
||||||
|
print('🔄 Updated item from Firebase: ${item.name} (key: $itemKey)');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print('📊 Sync stats: $newItems new, $updatedItems updated');
|
||||||
|
|
||||||
// Delete items that no longer exist in Firebase
|
// Delete items that no longer exist in Firebase
|
||||||
final itemsToDelete = <int>[];
|
final itemsToDelete = <int>[];
|
||||||
for (final item in box.values) {
|
for (final item in box.values) {
|
||||||
@@ -76,8 +107,11 @@ class InventorySyncService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final key in itemsToDelete) {
|
if (itemsToDelete.isNotEmpty) {
|
||||||
await box.delete(key);
|
print('🗑️ Deleting ${itemsToDelete.length} items that no longer exist in Firebase');
|
||||||
|
for (final key in itemsToDelete) {
|
||||||
|
await box.delete(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user