From 0af9986262e53b232731408ad38e9fda3da2cfa2 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Wed, 01 Apr 2026 18:02:59 +0200
Subject: [PATCH] feat: smart badge counting, persisted unreads, flutter_app_badger, race condition fixes
---
lib/screens/chat_screen.dart | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart
index 63fc4cd..77af560 100644
--- a/lib/screens/chat_screen.dart
+++ b/lib/screens/chat_screen.dart
@@ -67,6 +67,7 @@
final Map<String, List<Message>> _catchUpPending = {};
List<String>? _cachedSessionOrder;
Timer? _typingTimer;
+ bool _unreadCountsLoaded = false;
@override
void initState() {
@@ -80,6 +81,16 @@
// Load persisted state BEFORE connecting
final prefs = await SharedPreferences.getInstance();
_lastSeq = prefs.getInt('lastSeq') ?? 0;
+ // Restore persisted unread counts
+ final savedUnreads = prefs.getString('unreadCounts');
+ if (savedUnreads != null && mounted) {
+ try {
+ final map = (jsonDecode(savedUnreads) as Map<String, dynamic>)
+ .map((k, v) => MapEntry(k, v as int));
+ ref.read(unreadCountsProvider.notifier).state = map;
+ } catch (_) {}
+ }
+ _unreadCountsLoaded = true;
// Restore saved session order and active session
_cachedSessionOrder = prefs.getStringList('sessionOrder');
final savedSessionId = prefs.getString('activeSessionId');
@@ -133,7 +144,17 @@
if (_ws != null && !_ws!.isConnected) {
_ws!.connect();
}
+ // Don't update badge here — provider might not have loaded persisted counts yet.
+ // Native applicationDidBecomeActive reads correct value from UserDefaults.
+ } else if (state == AppLifecycleState.paused && _unreadCountsLoaded) {
+ // Set badge to total unread count when going to background
+ _updateBadgeFromUnreads();
}
+ }
+
+ void _updateBadgeFromUnreads() {
+ final counts = ref.read(unreadCountsProvider);
+ _persistUnreadCounts(counts);
}
bool _isLoadingMore = false;
@@ -675,6 +696,18 @@
final counts = Map<String, int>.from(ref.read(unreadCountsProvider));
counts[sessionId] = (counts[sessionId] ?? 0) + 1;
ref.read(unreadCountsProvider.notifier).state = counts;
+ _persistUnreadCounts(counts);
+ }
+
+ void _persistUnreadCounts(Map<String, int> counts) {
+ final total = counts.values.fold<int>(0, (sum, v) => sum + v);
+ // Set badge immediately via platform channel (synchronous native call)
+ PushService.setBadge(total);
+ // Also persist to SharedPreferences for app restart
+ SharedPreferences.getInstance().then((prefs) {
+ prefs.setString('unreadCounts', jsonEncode(counts));
+ prefs.setInt('badgeCount', total);
+ });
}
Future<void> _switchSession(String sessionId) async {
@@ -691,6 +724,10 @@
final counts = Map<String, int>.from(ref.read(unreadCountsProvider));
counts.remove(sessionId);
ref.read(unreadCountsProvider.notifier).state = counts;
+ _persistUnreadCounts(counts);
+
+ // Update badge to reflect remaining unreads
+ _updateBadgeFromUnreads();
_sendCommand('switch', {'sessionId': sessionId});
_scrollToBottom();
--
Gitblit v1.3.1