diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index b96aef98..9483a202 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -150,6 +150,8 @@ class MeshCoreConnector extends ChangeNotifier { final Set _knownContactKeys = {}; final Map _contactUnreadCount = {}; bool _unreadStateLoaded = false; + int _cachedContactsUnreadTotal = 0; + int _cachedChannelsUnreadTotal = 0; final Map _pendingRepeaterAcks = {}; String? _activeContactKey; int? _activeChannelIndex; @@ -342,22 +344,28 @@ class MeshCoreConnector extends ChangeNotifier { int getTotalContactsUnreadCount() { if (!_unreadStateLoaded) return 0; - var total = 0; - for (final contact in _contacts) { - total += getUnreadCountForContact(contact); - } - return total; + return _cachedContactsUnreadTotal; } int getTotalChannelsUnreadCount() { if (!_unreadStateLoaded) return 0; - var total = 0; - // Check all channels (from _channels or _cachedChannels) + return _cachedChannelsUnreadTotal; + } + + /// Recalculates both cached unread totals from scratch. + /// Called when unread state is first loaded. + void _recalculateCachedUnreadTotals() { + _recalculateCachedContactsUnreadTotal(); + _recalculateCachedChannelsUnreadTotal(); + } + + void _recalculateCachedContactsUnreadTotal() { + _cachedContactsUnreadTotal = _contactUnreadCount.values.fold(0, (a, b) => a + b); + } + + void _recalculateCachedChannelsUnreadTotal() { final allChannels = _channels.isNotEmpty ? _channels : _cachedChannels; - for (final channel in allChannels) { - total += channel.unreadCount; - } - return total; + _cachedChannelsUnreadTotal = allChannels.fold(0, (total, ch) => total + ch.unreadCount); } bool isChannelSmazEnabled(int channelIndex) { @@ -377,11 +385,13 @@ class MeshCoreConnector extends ChangeNotifier { ..clear() ..addAll(await _unreadStore.loadContactUnreadCount()); _unreadStateLoaded = true; + _recalculateCachedUnreadTotals(); notifyListeners(); } Future loadCachedChannels() async { _cachedChannels = await _channelStore.loadChannels(); + _recalculateCachedChannelsUnreadTotal(); } void setActiveContact(String? contactKeyHex) { @@ -408,6 +418,7 @@ class MeshCoreConnector extends ChangeNotifier { final previousCount = _contactUnreadCount[contactKeyHex] ?? 0; if (previousCount > 0) { _contactUnreadCount[contactKeyHex] = 0; + _cachedContactsUnreadTotal -= previousCount; _appDebugLogService?.info( 'Contact $contactKeyHex marked as read (was $previousCount unread)', tag: 'Unread', @@ -424,6 +435,7 @@ class MeshCoreConnector extends ChangeNotifier { if (channel != null && channel.unreadCount > 0) { final previousCount = channel.unreadCount; channel.unreadCount = 0; + _cachedChannelsUnreadTotal -= previousCount; _appDebugLogService?.info( 'Channel ${channel.name.isNotEmpty ? channel.name : channelIndex} marked as read (was $previousCount unread)', tag: 'Unread', @@ -1656,6 +1668,7 @@ class MeshCoreConnector extends ChangeNotifier { if (completed) { _hasLoadedChannels = true; _previousChannelsCache.clear(); + _recalculateCachedChannelsUnreadTotal(); } // Keep cache on failure/disconnection for future attempts } @@ -2703,6 +2716,7 @@ class MeshCoreConnector extends ChangeNotifier { final channel = _findChannelByIndex(channelIndex); if (channel != null) { channel.unreadCount++; + _cachedChannelsUnreadTotal++; _appDebugLogService?.info( 'Channel ${channel.name.isNotEmpty ? channel.name : channelIndex} unread count incremented to ${channel.unreadCount}', tag: 'Unread', @@ -2747,6 +2761,7 @@ class MeshCoreConnector extends ChangeNotifier { final currentCount = _contactUnreadCount[contactKey] ?? 0; _contactUnreadCount[contactKey] = currentCount + 1; + _cachedContactsUnreadTotal++; _appDebugLogService?.info( 'Contact $contactKey unread count incremented to ${currentCount + 1}', tag: 'Unread',