| .. | .. |
|---|
| 223 | 223 | _push?.onMqttConnected(); |
|---|
| 224 | 224 | }; |
|---|
| 225 | 225 | _ws!.onResume = () { |
|---|
| 226 | | - // App came back from background with connection still alive. |
|---|
| 227 | | - // Send catch_up to fetch any messages missed during suspend. |
|---|
| 226 | + // App came back from background — connection may or may not be alive. |
|---|
| 227 | + // Try catch_up first, but if no response comes, force reconnect. |
|---|
| 228 | 228 | _chatLog('onResume: sending catch_up with lastSeq=$_lastSeq'); |
|---|
| 229 | + final seqBefore = _lastSeq; |
|---|
| 229 | 230 | _sendCommand('catch_up', {'lastSeq': _lastSeq}); |
|---|
| 231 | + // Force UI rebuild for any buffered messages |
|---|
| 232 | + Future.delayed(const Duration(milliseconds: 300), () { |
|---|
| 233 | + if (mounted) { |
|---|
| 234 | + setState(() {}); |
|---|
| 235 | + _scrollToBottom(); |
|---|
| 236 | + } |
|---|
| 237 | + }); |
|---|
| 238 | + // If catch_up didn't produce a response in 2s, connection is dead — reconnect |
|---|
| 239 | + Future.delayed(const Duration(seconds: 2), () { |
|---|
| 240 | + if (!mounted) return; |
|---|
| 241 | + if (_lastSeq == seqBefore) { |
|---|
| 242 | + // No new messages arrived — connection likely dead |
|---|
| 243 | + _chatLog('onResume: no catch_up response after 2s, forcing reconnect'); |
|---|
| 244 | + _ws?.forceReconnect(); |
|---|
| 245 | + } |
|---|
| 246 | + }); |
|---|
| 230 | 247 | }; |
|---|
| 231 | 248 | _ws!.onError = (error) { |
|---|
| 232 | 249 | debugPrint('MQTT error: $error'); |
|---|
| .. | .. |
|---|
| 247 | 264 | // sent immediately if already connected. |
|---|
| 248 | 265 | _push = PushService(mqttService: _ws!); |
|---|
| 249 | 266 | _push!.onNotificationTap = (data) { |
|---|
| 250 | | - // If notification carried a sessionId, switch to that session |
|---|
| 267 | + // Switch to the session immediately, then request catch_up. |
|---|
| 268 | + // The MQTT connection auto-reconnects on resume, and onResume |
|---|
| 269 | + // already sends catch_up. We just need to be on the right session. |
|---|
| 251 | 270 | final sessionId = data['sessionId'] as String?; |
|---|
| 252 | 271 | if (sessionId != null && mounted) { |
|---|
| 253 | 272 | _switchSession(sessionId); |
|---|