Matthias Nott
2026-04-01 0af9986262e53b232731408ad38e9fda3da2cfa2
lib/screens/chat_screen.dart
....@@ -67,6 +67,7 @@
6767 final Map<String, List<Message>> _catchUpPending = {};
6868 List<String>? _cachedSessionOrder;
6969 Timer? _typingTimer;
70
+ bool _unreadCountsLoaded = false;
7071
7172 @override
7273 void initState() {
....@@ -80,6 +81,16 @@
8081 // Load persisted state BEFORE connecting
8182 final prefs = await SharedPreferences.getInstance();
8283 _lastSeq = prefs.getInt('lastSeq') ?? 0;
84
+ // Restore persisted unread counts
85
+ final savedUnreads = prefs.getString('unreadCounts');
86
+ if (savedUnreads != null && mounted) {
87
+ try {
88
+ final map = (jsonDecode(savedUnreads) as Map<String, dynamic>)
89
+ .map((k, v) => MapEntry(k, v as int));
90
+ ref.read(unreadCountsProvider.notifier).state = map;
91
+ } catch (_) {}
92
+ }
93
+ _unreadCountsLoaded = true;
8394 // Restore saved session order and active session
8495 _cachedSessionOrder = prefs.getStringList('sessionOrder');
8596 final savedSessionId = prefs.getString('activeSessionId');
....@@ -133,7 +144,17 @@
133144 if (_ws != null && !_ws!.isConnected) {
134145 _ws!.connect();
135146 }
147
+ // Don't update badge here — provider might not have loaded persisted counts yet.
148
+ // Native applicationDidBecomeActive reads correct value from UserDefaults.
149
+ } else if (state == AppLifecycleState.paused && _unreadCountsLoaded) {
150
+ // Set badge to total unread count when going to background
151
+ _updateBadgeFromUnreads();
136152 }
153
+ }
154
+
155
+ void _updateBadgeFromUnreads() {
156
+ final counts = ref.read(unreadCountsProvider);
157
+ _persistUnreadCounts(counts);
137158 }
138159
139160 bool _isLoadingMore = false;
....@@ -675,6 +696,18 @@
675696 final counts = Map<String, int>.from(ref.read(unreadCountsProvider));
676697 counts[sessionId] = (counts[sessionId] ?? 0) + 1;
677698 ref.read(unreadCountsProvider.notifier).state = counts;
699
+ _persistUnreadCounts(counts);
700
+ }
701
+
702
+ void _persistUnreadCounts(Map<String, int> counts) {
703
+ final total = counts.values.fold<int>(0, (sum, v) => sum + v);
704
+ // Set badge immediately via platform channel (synchronous native call)
705
+ PushService.setBadge(total);
706
+ // Also persist to SharedPreferences for app restart
707
+ SharedPreferences.getInstance().then((prefs) {
708
+ prefs.setString('unreadCounts', jsonEncode(counts));
709
+ prefs.setInt('badgeCount', total);
710
+ });
678711 }
679712
680713 Future<void> _switchSession(String sessionId) async {
....@@ -691,6 +724,10 @@
691724 final counts = Map<String, int>.from(ref.read(unreadCountsProvider));
692725 counts.remove(sessionId);
693726 ref.read(unreadCountsProvider.notifier).state = counts;
727
+ _persistUnreadCounts(counts);
728
+
729
+ // Update badge to reflect remaining unreads
730
+ _updateBadgeFromUnreads();
694731
695732 _sendCommand('switch', {'sessionId': sessionId});
696733 _scrollToBottom();