Skip to content

fix: [Flutter Web] TypeError JSArray #2224

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
47 changes: 28 additions & 19 deletions packages/stream_chat/lib/src/client/channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,11 @@ class Channel {
// update or remove attachment from message.
final List<Attachment> newAttachments;
if (remove) {
newAttachments = [...message!.attachments]..removeAt(index);
newAttachments = <Attachment>[...message!.attachments]
..removeAt(index);
} else {
newAttachments = [...message!.attachments]..[index] = attachment;
newAttachments = <Attachment>[...message!.attachments]..[index] =
attachment;
}

final updatedMessage = message!.copyWith(attachments: newAttachments);
Expand Down Expand Up @@ -1307,7 +1309,9 @@ class Channel {
final now = DateTime.now();
final user = _client.state.currentUser;

var latestReactions = [...message.latestReactions ?? <Reaction>[]];
var latestReactions = <Reaction>[
...message.latestReactions ?? <Reaction>[]
];
if (enforceUnique) {
latestReactions.removeWhere((it) => it.userId == user!.id);
}
Expand Down Expand Up @@ -1382,15 +1386,17 @@ class Channel {
reactionScores.update(type, (value) => value - 1);
}

final latestReactions = [...?message.latestReactions]..removeWhere((r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);
final latestReactions = <Reaction>[...?message.latestReactions]
..removeWhere((r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);

final ownReactions = [...?message.ownReactions]..removeWhere((r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);
final ownReactions = <Reaction>[...?message.ownReactions]..removeWhere(
(r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);

final newMessage = message.copyWith(
reactionCounts: reactionCounts..removeWhere((_, value) => value == 0),
Expand Down Expand Up @@ -2235,7 +2241,7 @@ class ChannelClientState {
final user = event.user;
if (user == null) return;

final existingMembers = [...?channelState.members];
final existingMembers = <Member>[...?channelState.members];
final existingMembership = channelState.membership;

// Return if the user is not a existing member of the channel.
Expand Down Expand Up @@ -2371,7 +2377,7 @@ class ChannelClientState {
}

void _updateMember(Member member) {
final currentMembers = [...members];
final currentMembers = <Member>[...members];
final memberIndex = currentMembers.indexWhere(
(m) => m.userId == member.userId,
);
Expand Down Expand Up @@ -2405,8 +2411,10 @@ class ChannelClientState {

/// Retry failed message.
Future<void> retryFailedMessages() async {
final failedMessages = [...messages, ...threads.values.expand((v) => v)]
.where((it) => it.state.isFailed);
final failedMessages = <Message>[
...messages,
...threads.values.expand((v) => v)
].where((it) => it.state.isFailed);
_retryQueue.add(failedMessages);
}

Expand Down Expand Up @@ -2787,7 +2795,7 @@ class ChannelClientState {
if (message.parentId == null || message.showInChannel == true) {
// Create a new list of messages to avoid modifying the original
// list directly.
var newMessages = [...messages];
var newMessages = <Message>[...messages];
final oldIndex = newMessages.indexWhere((m) => m.id == message.id);

if (oldIndex != -1) {
Expand Down Expand Up @@ -2869,7 +2877,7 @@ class ChannelClientState {
/// Updates the list of pinned messages based on the current message's
/// pinned status.
List<Message> _updatePinnedMessages(Message message) {
final newPinnedMessages = [...pinnedMessages];
final newPinnedMessages = <Message>[...pinnedMessages];
final oldPinnedIndex =
newPinnedMessages.indexWhere((m) => m.id == message.id);

Expand Down Expand Up @@ -2914,10 +2922,11 @@ class ChannelClientState {
}

// Remove regular message, thread message shown in channel
var updatedMessages = [...messages]..removeWhere((e) => e.id == message.id);
var updatedMessages = <Message>[...messages]
..removeWhere((e) => e.id == message.id);

// Remove quoted message reference from every message if available.
updatedMessages = [...updatedMessages].map((it) {
updatedMessages = <Message>[...updatedMessages].map((it) {
Copy link
Preview

Copilot AI May 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mapping over the list returns an Iterable rather than a List. To ensure type consistency, consider appending .toList() after the map operation.

Copilot uses AI. Check for mistakes.

// Early return if the message doesn't have a quoted message.
if (it.quotedMessageId != message.id) return it;

Expand Down
9 changes: 8 additions & 1 deletion packages/stream_chat/lib/src/core/api/channel_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:stream_chat/src/core/models/channel_state.dart';
import 'package:stream_chat/src/core/models/event.dart';
import 'package:stream_chat/src/core/models/filter.dart';
import 'package:stream_chat/src/core/models/message.dart';
import 'package:flutter/foundation.dart';

/// Defines the api dedicated to channel operations
class ChannelApi {
Expand Down Expand Up @@ -79,7 +80,13 @@ class ChannelApi {
}),
},
);
return QueryChannelsResponse.fromJson(response.data);

try {
return QueryChannelsResponse.fromJson(response.data);
} catch (e) {
debugPrint('queryChannels error: $e');
return QueryChannelsResponse.fromJson({});
Comment on lines +86 to +88
Copy link
Preview

Copilot AI May 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning an empty QueryChannelsResponse in the catch block may mask issues during JSON parsing. Consider handling the error more explicitly, such as propagating the error or providing a detailed error message.

Suggested change
} catch (e) {
debugPrint('queryChannels error: $e');
return QueryChannelsResponse.fromJson({});
} catch (e, stackTrace) {
debugPrint('queryChannels error: $e');
throw QueryChannelsException(
'Failed to parse QueryChannelsResponse: $e',
stackTrace,
);

Copilot uses AI. Check for mistakes.

}
}

/// Mark all channels for this user as read
Expand Down
Loading