Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(llc): reply being considered deleted if a new message was typed inside its thread #1866

Merged
merged 3 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/stream_chat/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Unreleased

🐞 Fixed
- Fixes a thread message causing reply messages on the main thread to be considered deleted

## 7.0.2

🐞 Fixed
Expand Down
85 changes: 56 additions & 29 deletions packages/stream_chat/lib/src/client/channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2103,54 +2103,57 @@ class ChannelClientState {

/// Updates the [message] in the state if it exists. Adds it otherwise.
void updateMessage(Message message) {
// Regular messages, which are shown in channel.
// Determine if the message should be displayed in the channel view.
if (message.parentId == null || message.showInChannel == true) {
// Create a new list of messages to avoid modifying the original
// list directly.
var newMessages = [...messages];
final oldIndex = newMessages.indexWhere((m) => m.id == message.id);

if (oldIndex != -1) {
// If the message already exists, prepare it for update.
final oldMessage = newMessages[oldIndex];
var updatedMessage = message.syncWith(oldMessage);
// Add quoted message to the message if it is not present.
if (message.quotedMessageId != null && message.quotedMessage == null) {

// Preserve quotedMessage if the update doesn't include a new
// quotedMessage.
if (message.quotedMessageId != null &&
message.quotedMessage == null &&
oldMessage.quotedMessage != null) {
updatedMessage = updatedMessage.copyWith(
quotedMessage: oldMessage.quotedMessage,
);
}

// Update the message in the list.
newMessages[oldIndex] = updatedMessage;

// Update quoted message reference for every message if available.
newMessages = [...newMessages].map((it) {
// Early return if the message doesn't have a quoted message.
// Update quotedMessage references in all messages.
newMessages = newMessages.map((it) {
// Skip if the current message does not quote the updated message.
if (it.quotedMessageId != message.id) return it;

// Setting it to null will remove the quoted message from the message
// So, we are setting the same message but with the deleted state.
return it.copyWith(
quotedMessage: updatedMessage.copyWith(
type: 'deleted',
deletedAt: DateTime.now(),
),
);
// Update the quotedMessage only if the updatedMessage indicates
// deletion.
if (message.type == 'deleted') {
return it.copyWith(
quotedMessage: updatedMessage.copyWith(
type: message.type,
deletedAt: message.deletedAt,
),
);
}
return it;
}).toList();
} else {
// If the message is new, add it to the list.
newMessages.add(message);
}

final newPinnedMessages = [...pinnedMessages];
final oldPinnedIndex =
newPinnedMessages.indexWhere((m) => m.id == message.id);

// Handle pinned messages
if (message.pinned) {
if (oldPinnedIndex != -1) {
newPinnedMessages[oldPinnedIndex] = message;
} else {
newPinnedMessages.add(message);
}
} else {
newPinnedMessages.removeWhere((m) => m.id == message.id);
}
// Handle updates to pinned messages.
final newPinnedMessages = _updatePinnedMessages(message);

// Apply the updated lists to the channel state.
_channelState = _channelState.copyWith(
messages: newMessages.sorted(_sortByCreatedAt),
pinnedMessages: newPinnedMessages,
Expand All @@ -2160,12 +2163,36 @@ class ChannelClientState {
);
}

// Thread messages, which are shown in thread page.
// If the message is part of a thread, update thread information.
if (message.parentId != null) {
updateThreadInfo(message.parentId!, [message]);
}
}

/// Updates the list of pinned messages based on the current message's
/// pinned status.
List<Message> _updatePinnedMessages(Message message) {
final newPinnedMessages = [...pinnedMessages];
final oldPinnedIndex =
newPinnedMessages.indexWhere((m) => m.id == message.id);

if (message.pinned) {
// If the message is pinned, add or update it in the list of pinned
// messages.
if (oldPinnedIndex != -1) {
newPinnedMessages[oldPinnedIndex] = message;
} else {
newPinnedMessages.add(message);
}
} else {
// If the message is not pinned, remove it from the list of pinned
// messages.
newPinnedMessages.removeWhere((m) => m.id == message.id);
}

return newPinnedMessages;
}

/// Remove a [message] from this [channelState].
void removeMessage(Message message) async {
await _channel._client.chatPersistenceClient?.deleteMessageById(message.id);
Expand Down
Loading