Skip to content
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
1 change: 1 addition & 0 deletions packages/stream_chat/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
✅ Added

- Added an `upsert` flag to `ChannelClientState.updateMessage` (defaults to `true`). Pass `false` to update a message only if it's already loaded in the state, skipping unknown messages instead of adding them.
- Added `EventType.userPresenceChanged` (`user.presence.changed`) constant.

🔄 Changed

Expand Down
3 changes: 3 additions & 0 deletions packages/stream_chat/lib/src/event_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class EventType {
/// Event sent when a user is updated
static const String userUpdated = 'user.updated';

/// Event sent when a user's presence changes
static const String userPresenceChanged = 'user.presence.changed';

/// Event sent when a member is added to a channel
static const String memberAdded = 'member.added';

Expand Down
1 change: 1 addition & 0 deletions packages/stream_chat_flutter_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Fixed `StreamChannelListController` not handling `notification.channel_deleted` event.
- Fixed backwards pagination not working if channel was never opened.
- Guarded `StreamChannelListController`'s `channel.updated`, `member.updated`, and `user.presence.changed`/`user.updated` event handlers to skip the full list re-sort when the event doesn't affect any listed channel.

## 10.1.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
_eventHandler.onNotificationMessageNew(event, this);
} else if (eventType == EventType.notificationRemovedFromChannel) {
_eventHandler.onNotificationRemovedFromChannel(event, this);
} else if (eventType == 'user.presence.changed' || eventType == EventType.userUpdated) {
} else if (eventType == EventType.userPresenceChanged || eventType == EventType.userUpdated) {
_eventHandler.onUserPresenceChanged(event, this);
} else if (eventType == EventType.memberUpdated) {
_eventHandler.onMemberUpdated(event, this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,27 @@ mixin class StreamChannelListEventHandler {
///
/// This event is fired when a channel is updated.
///
/// By default, this updates the channel received in the event.
/// By default, this re-sorts the list when the updated channel is present in
/// it, and does nothing otherwise.
void onChannelUpdated(Event event, StreamChannelListController controller) {
controller.channels = [...controller.currentItems];
final cid = event.cid ?? event.channel?.cid;
final channels = controller.currentItems;
if (!channels.any((it) => it.cid == cid)) return;
controller.channels = [...channels];
}

/// Function which gets called for the event
/// [EventType.memberUpdated].
///
/// This event is fired when a member is updated.
///
/// By default, this sorts the channels.
/// By default, this re-sorts the list when the member's channel is present in
/// it, and does nothing otherwise.
void onMemberUpdated(Event event, StreamChannelListController controller) {
controller.channels = [...controller.currentItems];
final cid = event.cid ?? event.channel?.cid;
final channels = controller.currentItems;
if (!channels.any((it) => it.cid == cid)) return;
controller.channels = [...channels];
}

/// Function which gets called for the event
Expand Down Expand Up @@ -180,11 +188,14 @@ mixin class StreamChannelListEventHandler {
}

/// Function which gets called for the event
/// 'user.presence.changed' and [EventType.userUpdated].
/// [EventType.userPresenceChanged] and [EventType.userUpdated].
///
/// This event is fired when a user's presence changes or gets updated.
///
/// By default, this updates the channel member with the event user.
/// By default, this updates the event user in every listed channel where they
/// appear — either among the loaded members, or, when the event is about the
/// current user, as the channel membership — then re-sorts the list.
/// Does nothing when no listed channel references the user.
void onUserPresenceChanged(
Event event,
StreamChannelListController controller,
Expand All @@ -194,12 +205,14 @@ mixin class StreamChannelListEventHandler {

final channels = [...controller.currentItems];

final updatedChannels = channels.map((channel) {
var updated = false;
for (final channel in channels) {
final existingMembership = channel.membership;
final existingMembers = [...channel.state!.members];

// Return if the user is not a existing member of the channel.
if (!existingMembers.any((m) => m.userId == user.id)) return channel;
// Leave channels untouched where the user is not an existing member.
final containsUser = existingMembership?.userId == user.id || existingMembers.any((m) => m.userId == user.id);
if (!containsUser) continue;

Member? maybeUpdateMemberUser(Member? existingMember) {
if (existingMember == null) return null;
Expand All @@ -216,9 +229,12 @@ mixin class StreamChannelListEventHandler {
),
);

return channel;
});
updated = true;
}

// Skip the re-sort when no listed channel contained the user.
if (!updated) return;

controller.channels = [...updatedChannels];
controller.channels = [...channels];
}
}
6 changes: 6 additions & 0 deletions packages/stream_chat_flutter_core/test/mocks.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter_core/src/stream_channel_list_controller.dart';
import 'package:stream_chat_flutter_core/src/stream_channel_list_event_handler.dart';

class MockLogger extends Mock implements Logger {}

class MockStreamChannelListController extends Mock implements StreamChannelListController {}

class MockStreamChannelListEventHandler extends Mock implements StreamChannelListEventHandler {}

class MockClient extends Mock implements StreamChatClient {
MockClient() {
when(() => wsConnectionStatus).thenReturn(ConnectionStatus.connected);
Expand Down
Loading
Loading