From 61c897630c4928eaed2c9e7d7b65007b098b7d35 Mon Sep 17 00:00:00 2001 From: Winston Lowe Date: Mon, 11 May 2026 18:19:45 -0700 Subject: [PATCH] fix: Improve message key handling and enhance contact tile key uniqueness --- lib/screens/channel_chat_screen.dart | 11 +++++++++-- lib/screens/channels_screen.dart | 2 +- lib/screens/chat_screen.dart | 7 ++++++- lib/screens/contacts_screen.dart | 2 ++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/screens/channel_chat_screen.dart b/lib/screens/channel_chat_screen.dart index 96383153..05b9e914 100644 --- a/lib/screens/channel_chat_screen.dart +++ b/lib/screens/channel_chat_screen.dart @@ -377,6 +377,7 @@ class _ChannelChatScreenState extends State { final reversedMessages = messages.reversed.toList(); final itemCount = reversedMessages.length + (_isLoadingOlder ? 1 : 0); + final keyedMessageIds = {}; // Auto-scroll to bottom if user is already at bottom WidgetsBinding.instance.addPostFrameCallback((_) { @@ -413,14 +414,20 @@ class _ChannelChatScreenState extends State { } final messageIndex = index; final message = reversedMessages[messageIndex]; - if (!_messageKeys.containsKey(message.messageId)) { + final shouldAttachMessageKey = keyedMessageIds.add( + message.messageId, + ); + if (shouldAttachMessageKey && + !_messageKeys.containsKey(message.messageId)) { _messageKeys[message.messageId] = GlobalKey(); } final isUnreadAnchor = _unreadDividerMessageId != null && message.messageId == _unreadDividerMessageId; return Container( - key: _messageKeys[message.messageId]!, + key: shouldAttachMessageKey + ? _messageKeys[message.messageId] + : null, child: Builder( builder: (context) { final textScale = context diff --git a/lib/screens/channels_screen.dart b/lib/screens/channels_screen.dart index 0957f283..b6f2f91f 100644 --- a/lib/screens/channels_screen.dart +++ b/lib/screens/channels_screen.dart @@ -394,7 +394,7 @@ class _ChannelsScreenState extends State { } return Card( - key: ValueKey('channel_${channel.index}'), + key: ValueKey('${channel.index}_${channel.pskHex}_${channel.name}'), margin: const EdgeInsets.only(bottom: 12), child: GestureDetector( onSecondaryTapUp: PlatformInfo.isDesktop diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 03062994..992008a9 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -451,6 +451,7 @@ class _ChatScreenState extends State { ) { // Reverse messages so newest appear at bottom with reverse: true final reversedMessages = messages.reversed.toList(); + var unreadAnchorKeyAssigned = false; final itemCount = reversedMessages.length + (_isLoadingOlder ? 1 : 0); // Auto-scroll to bottom if user is already at bottom @@ -525,7 +526,11 @@ class _ChatScreenState extends State { children: [const UnreadDivider(), bubble], ) : bubble; - if (identical(message, _pendingUnreadScrollTarget)) { + final shouldAttachUnreadScrollKey = + !unreadAnchorKeyAssigned && + identical(message, _pendingUnreadScrollTarget); + if (shouldAttachUnreadScrollKey) { + unreadAnchorKeyAssigned = true; return KeyedSubtree(key: _unreadScrollKey, child: child); } return child; diff --git a/lib/screens/contacts_screen.dart b/lib/screens/contacts_screen.dart index 0a819b20..67c3b38f 100644 --- a/lib/screens/contacts_screen.dart +++ b/lib/screens/contacts_screen.dart @@ -827,6 +827,7 @@ class _ContactsScreenState extends State { contact, ); return _ContactTile( + key: ValueKey(contact.publicKeyHex), contact: contact, lastSeen: _resolveLastSeen(contact), unreadCount: unreadCount, @@ -1495,6 +1496,7 @@ class _ContactTile extends StatelessWidget { final VoidCallback onLongPress; const _ContactTile({ + super.key, required this.contact, required this.lastSeen, required this.unreadCount,