From 61d0b831abb2c39546981cc8db1b39c2e41ede57 Mon Sep 17 00:00:00 2001 From: Janez T Date: Wed, 15 Oct 2025 14:59:00 +0200 Subject: [PATCH] feat: Enhance message sending feedback and improve reconnection logic with optimized delays --- lib/providers/connection_provider.dart | 11 +++++++- lib/providers/messages_provider.dart | 9 +++++++ lib/services/ble/ble_connection_manager.dart | 27 ++++++++++++++------ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/providers/connection_provider.dart b/lib/providers/connection_provider.dart index 3791e9e..e0688ad 100644 --- a/lib/providers/connection_provider.dart +++ b/lib/providers/connection_provider.dart @@ -522,10 +522,19 @@ class ConnectionProvider with ChangeNotifier { // Channel messages are ephemeral (not persisted) - mark as "sent" immediately // They don't have ACK/TAG mechanism like direct messages if (messageId != null) { - print('✅ [Provider] Channel message sent successfully - marking as sent: $messageId'); + print('✅ [ConnectionProvider] Channel message sent successfully'); + print(' Message ID: $messageId'); + print(' onMessageSent callback exists: ${onMessageSent != null}'); + + // Small delay to ensure the message is in the MessagesProvider list + // before we try to mark it as sent + await Future.delayed(const Duration(milliseconds: 50)); + // Use a dummy ACK tag (0) and timeout (0) for channel messages // This will trigger the callback to mark the message as "sent" + print(' Calling onMessageSent callback...'); onMessageSent?.call(messageId, 0, 0); + print(' onMessageSent callback completed'); } } catch (e) { _error = 'Failed to send channel message: $e'; diff --git a/lib/providers/messages_provider.dart b/lib/providers/messages_provider.dart index 2dcd55c..0ff0384 100644 --- a/lib/providers/messages_provider.dart +++ b/lib/providers/messages_provider.dart @@ -334,6 +334,12 @@ class MessagesProvider with ChangeNotifier { /// Add a sent message with initial status void addSentMessage(Message message) { + print('📝 [MessagesProvider] addSentMessage called'); + print(' Message ID: ${message.id}'); + print(' Message type: ${message.messageType}'); + print(' Initial status: ${message.deliveryStatus}'); + print(' Message text preview: ${message.text.substring(0, message.text.length > 30 ? 30 : message.text.length)}...'); + // Always enhance message with SAR parser to detect SAR markers final enhancedMessage = SarMessageParser.enhanceMessage(message); @@ -348,6 +354,8 @@ class MessagesProvider with ChangeNotifier { deliveryStatus: MessageDeliveryStatus.sending, ); _messages.add(sendingMessage); + print(' ✅ Message added to list at index ${_messages.length - 1}'); + print(' Total messages in list: ${_messages.length}'); // If it's a SAR marker message, extract and store the marker if (sendingMessage.isSarMarker) { @@ -359,6 +367,7 @@ class MessagesProvider with ChangeNotifier { _persistMessages(); notifyListeners(); + print(' ✅ notifyListeners() called - UI should update'); } /// Update message status to sent with ACK tag diff --git a/lib/services/ble/ble_connection_manager.dart b/lib/services/ble/ble_connection_manager.dart index 4c5a254..ed4c602 100644 --- a/lib/services/ble/ble_connection_manager.dart +++ b/lib/services/ble/ble_connection_manager.dart @@ -20,8 +20,19 @@ class BleConnectionManager { int _reconnectionAttempt = 0; Timer? _reconnectionTimer; StreamSubscription? _connectionStateSubscription; - static const int _maxReconnectionAttempts = 5; - static const List _reconnectionDelaysMs = [1000, 2000, 3000, 5000, 10000]; // Exponential backoff + + // SAR-optimized reconnection: ~15 minutes total + // Pattern: Fast retries first (for temporary issues), then slower retries (for extended disconnections) + static const int _maxReconnectionAttempts = 30; + static const List _reconnectionDelaysMs = [ + 2000, // 2s - immediate retry + 3000, // 3s - quick retry + 5000, // 5s - fast retry + 10000, // 10s - moderate retry + 15000, // 15s - longer retry + 30000, // 30s - extended retry + 30000, // 30s - keep trying every 30s after this + ]; // Total: ~15 minutes of reconnection attempts // Callbacks OnConnectionStateCallback? onConnectionStateChanged; @@ -234,17 +245,17 @@ class BleConnectionManager { onReconnectionAttempt?.call(_reconnectionAttempt, _maxReconnectionAttempts); if (_reconnectionAttempt > _maxReconnectionAttempts) { - print('❌ [BLE] Max reconnection attempts reached. Giving up.'); + print('❌ [BLE] Max reconnection attempts reached after ~15 minutes. Giving up.'); _isReconnecting = false; - onError?.call('Connection lost. Max reconnection attempts ($_maxReconnectionAttempts) reached.'); + onError?.call('Connection lost. Unable to reconnect after 15 minutes ($_maxReconnectionAttempts attempts).'); return; } - // Calculate delay with exponential backoff + // Calculate delay with exponential backoff (uses last delay for attempts beyond array length) final delayIndex = (_reconnectionAttempt - 1).clamp(0, _reconnectionDelaysMs.length - 1); final delayMs = _reconnectionDelaysMs[delayIndex]; - print('🔄 [BLE] Waiting ${delayMs}ms before reconnection attempt $_reconnectionAttempt...'); + print('🔄 [BLE] Waiting ${(delayMs / 1000).toStringAsFixed(0)}s before reconnection attempt $_reconnectionAttempt...'); // Wait before attempting reconnection _reconnectionTimer = Timer(Duration(milliseconds: delayMs), () async { @@ -272,7 +283,7 @@ class BleConnectionManager { if (_reconnectionAttempt < _maxReconnectionAttempts) { _attemptReconnection(); } else { - onError?.call('Connection lost. Unable to reconnect after $_maxReconnectionAttempts attempts.'); + onError?.call('Connection lost. Unable to reconnect after 15 minutes ($_maxReconnectionAttempts attempts).'); } } } catch (e) { @@ -283,7 +294,7 @@ class BleConnectionManager { if (_reconnectionAttempt < _maxReconnectionAttempts) { _attemptReconnection(); } else { - onError?.call('Connection lost. Unable to reconnect: $e'); + onError?.call('Connection lost. Unable to reconnect after 15 minutes: $e'); } } });