From 83b2817cc416d57851e8bd1fcc943ac77f6dca8b Mon Sep 17 00:00:00 2001 From: zach Date: Tue, 30 Dec 2025 20:23:49 -0700 Subject: [PATCH] fix reply colors and reaction counts also fix race condition when connecting --- lib/connector/meshcore_connector.dart | 39 ++++++++++++++++++++------- lib/screens/channel_chat_screen.dart | 16 ++++++----- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index d8221de..e7b96ba 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -1955,10 +1955,19 @@ class MeshCoreConnector extends ChangeNotifier { // Parse reaction info final reactionInfo = Message.parseReaction(message.text); if (reactionInfo != null) { - // Find target message and add reaction - _processContactReaction(messages, reactionInfo); - _messageStore.saveMessages(pubKeyHex, messages); - notifyListeners(); + // Check if we've already processed this exact reaction + final isDuplicate = messages.any((m) => + m.text == message.text && + m.senderKey == message.senderKey && + m.timestamp.millisecondsSinceEpoch == message.timestamp.millisecondsSinceEpoch + ); + + if (!isDuplicate) { + // New reaction - process it + _processContactReaction(messages, reactionInfo); + _messageStore.saveMessages(pubKeyHex, messages); + notifyListeners(); + } return; // Don't add reaction as a visible message } @@ -2095,10 +2104,20 @@ class MeshCoreConnector extends ChangeNotifier { // Parse reaction info final reactionInfo = ChannelMessage.parseReaction(message.text); if (reactionInfo != null) { - // Find target message and add reaction - _processReaction(messages, reactionInfo); - // Save updated messages - _channelMessageStore.saveChannelMessages(channelIndex, messages); + // Check if we've already processed this exact reaction by looking for duplicate in messages + // Reaction messages are kept in the list but won't be displayed (filtered in UI or here) + final isDuplicate = messages.any((m) => + m.text == message.text && + m.senderName == message.senderName && + m.timestamp.millisecondsSinceEpoch == message.timestamp.millisecondsSinceEpoch + ); + + if (!isDuplicate) { + // New reaction - process it + _processReaction(messages, reactionInfo); + // Save updated messages + _channelMessageStore.saveChannelMessages(channelIndex, messages); + } return false; // Don't add reaction as a visible message } @@ -2302,8 +2321,8 @@ class MeshCoreConnector extends ChangeNotifier { _device = null; _rxCharacteristic = null; _txCharacteristic = null; - _deviceDisplayName = null; - _deviceId = null; + // Preserve deviceId and displayName for UI display during reconnection + // They're only cleared on manual disconnect via disconnect() method _maxContacts = _defaultMaxContacts; _maxChannels = _defaultMaxChannels; _isSyncingQueuedMessages = false; diff --git a/lib/screens/channel_chat_screen.dart b/lib/screens/channel_chat_screen.dart index cc936c6..e2dac21 100644 --- a/lib/screens/channel_chat_screen.dart +++ b/lib/screens/channel_chat_screen.dart @@ -344,6 +344,8 @@ class _ChannelChatScreenState extends State { final connector = context.read(); final isOwnNode = message.replyToSenderName == connector.selfName; final replyText = message.replyToText ?? ''; + final colorScheme = Theme.of(context).colorScheme; + final previewTextColor = colorScheme.onSurface.withValues(alpha: 0.7); final gifId = _parseGifId(replyText); final poi = _parsePoiMessage(replyText); @@ -352,17 +354,17 @@ class _ChannelChatScreenState extends State { if (gifId != null) { contentPreview = Row( children: [ - Icon(Icons.gif_box, size: 14, color: Colors.grey[600]), + Icon(Icons.gif_box, size: 14, color: previewTextColor), const SizedBox(width: 4), - Text('GIF', style: TextStyle(fontSize: 12, color: Colors.grey[700])), + Text('GIF', style: TextStyle(fontSize: 12, color: previewTextColor)), ], ); } else if (poi != null) { contentPreview = Row( children: [ - Icon(Icons.location_on_outlined, size: 14, color: Colors.grey[600]), + Icon(Icons.location_on_outlined, size: 14, color: previewTextColor), const SizedBox(width: 4), - Text('Location', style: TextStyle(fontSize: 12, color: Colors.grey[700])), + Text('Location', style: TextStyle(fontSize: 12, color: previewTextColor)), ], ); } else { @@ -372,7 +374,7 @@ class _ChannelChatScreenState extends State { overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 12, - color: Colors.grey[700], + color: previewTextColor, fontStyle: FontStyle.italic, ), ); @@ -383,11 +385,11 @@ class _ChannelChatScreenState extends State { child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.black.withValues(alpha: 0.05), + color: colorScheme.surfaceContainerHighest.withValues(alpha: 0.5), borderRadius: BorderRadius.circular(8), border: Border( left: BorderSide( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, width: 3, ), ),