| .. | .. |
|---|
| 1 | +import 'dart:async'; |
|---|
| 1 | 2 | import 'dart:convert'; |
|---|
| 2 | 3 | import 'dart:io'; |
|---|
| 3 | 4 | |
|---|
| .. | .. |
|---|
| 63 | 64 | final List<Map<String, dynamic>> _pendingMessages = []; |
|---|
| 64 | 65 | final Map<String, List<Message>> _catchUpPending = {}; |
|---|
| 65 | 66 | List<String>? _cachedSessionOrder; |
|---|
| 67 | + Timer? _typingTimer; |
|---|
| 66 | 68 | |
|---|
| 67 | 69 | @override |
|---|
| 68 | 70 | void initState() { |
|---|
| .. | .. |
|---|
| 132 | 134 | } |
|---|
| 133 | 135 | } |
|---|
| 134 | 136 | |
|---|
| 137 | + bool _isLoadingMore = false; |
|---|
| 135 | 138 | void _onScroll() { |
|---|
| 136 | | - if (_scrollController.position.pixels >= |
|---|
| 137 | | - _scrollController.position.maxScrollExtent - 100) { |
|---|
| 138 | | - ref.read(messagesProvider.notifier).loadMore(); |
|---|
| 139 | + if (!_isLoadingMore && |
|---|
| 140 | + _scrollController.position.pixels >= |
|---|
| 141 | + _scrollController.position.maxScrollExtent - 100) { |
|---|
| 142 | + _isLoadingMore = true; |
|---|
| 143 | + ref.read(messagesProvider.notifier).loadMore().then((_) => _isLoadingMore = false); |
|---|
| 139 | 144 | } |
|---|
| 140 | 145 | } |
|---|
| 141 | 146 | |
|---|
| .. | .. |
|---|
| 247 | 252 | // Strict: only show typing for the ACTIVE session, ignore all others |
|---|
| 248 | 253 | if (activeId != null && typingSession == activeId) { |
|---|
| 249 | 254 | ref.read(isTypingProvider.notifier).state = typing; |
|---|
| 255 | + // Auto-clear after 10s in case typing_end is missed |
|---|
| 256 | + if (typing) { |
|---|
| 257 | + _typingTimer?.cancel(); |
|---|
| 258 | + _typingTimer = Timer(const Duration(seconds: 10), () { |
|---|
| 259 | + if (mounted) ref.read(isTypingProvider.notifier).state = false; |
|---|
| 260 | + }); |
|---|
| 261 | + } else { |
|---|
| 262 | + _typingTimer?.cancel(); |
|---|
| 263 | + } |
|---|
| 250 | 264 | } |
|---|
| 251 | 265 | case 'typing_end': |
|---|
| 252 | 266 | final endSession = msg['sessionId'] as String?; |
|---|