From 29f7a2c444d60fa155451d7e7f65cf637a1b7f41 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Wed, 25 Mar 2026 17:22:28 +0100
Subject: [PATCH] fix: M1 M2 M6 M7 L3 L5 - subnet batching, scroll debounce, error logging, typing timeout, remove unused deps
---
lib/screens/chat_screen.dart | 20 +++++++++++++++++---
1 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart
index 3c03072..5017f31 100644
--- a/lib/screens/chat_screen.dart
+++ b/lib/screens/chat_screen.dart
@@ -1,3 +1,4 @@
+import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -63,6 +64,7 @@
final List<Map<String, dynamic>> _pendingMessages = [];
final Map<String, List<Message>> _catchUpPending = {};
List<String>? _cachedSessionOrder;
+ Timer? _typingTimer;
@override
void initState() {
@@ -132,10 +134,13 @@
}
}
+ bool _isLoadingMore = false;
void _onScroll() {
- if (_scrollController.position.pixels >=
- _scrollController.position.maxScrollExtent - 100) {
- ref.read(messagesProvider.notifier).loadMore();
+ if (!_isLoadingMore &&
+ _scrollController.position.pixels >=
+ _scrollController.position.maxScrollExtent - 100) {
+ _isLoadingMore = true;
+ ref.read(messagesProvider.notifier).loadMore().then((_) => _isLoadingMore = false);
}
}
@@ -247,6 +252,15 @@
// Strict: only show typing for the ACTIVE session, ignore all others
if (activeId != null && typingSession == activeId) {
ref.read(isTypingProvider.notifier).state = typing;
+ // Auto-clear after 10s in case typing_end is missed
+ if (typing) {
+ _typingTimer?.cancel();
+ _typingTimer = Timer(const Duration(seconds: 10), () {
+ if (mounted) ref.read(isTypingProvider.notifier).state = false;
+ });
+ } else {
+ _typingTimer?.cancel();
+ }
}
case 'typing_end':
final endSession = msg['sessionId'] as String?;
--
Gitblit v1.3.1