Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 5 additions & 1 deletion packages/realtime_client/lib/src/realtime_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,14 @@ class RealtimeChannel {
if (callback != null) callback(RealtimeSubscribeStatus.closed, null);
});

final presenceEnabled =
(_bindings['presence']?.isNotEmpty == true) ||
(params['config']['presence']['enabled'] == true);

final accessTokenPayload = <String, String>{};
final config = <String, dynamic>{
'broadcast': broadcast,
'presence': presence,
'presence': {...presence, 'enabled': presenceEnabled},
'postgres_changes':
_bindings['postgres_changes']?.map((r) => r.filter).toList() ?? [],
'private': isPrivate == true,
Expand Down
5 changes: 5 additions & 0 deletions packages/realtime_client/lib/src/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,17 @@ class RealtimeChannelConfig {
/// [key] option is used to track presence payload across clients
final String key;

/// Enables presence even without presence bindings
final bool enabled;

/// Defines if the channel is private or not and if RLS policies will be used to check data
final bool private;

const RealtimeChannelConfig({
this.ack = false,
this.self = false,
this.key = '',
this.enabled = false,
this.private = false,
});

Expand All @@ -167,6 +171,7 @@ class RealtimeChannelConfig {
},
'presence': {
'key': key,
'enabled': enabled,
},
'private': private,
}
Expand Down
92 changes: 90 additions & 2 deletions packages/realtime_client/test/channel_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void main() {
expect(channel.params, {
'config': {
'broadcast': {'ack': false, 'self': false},
'presence': {'key': ''},
'presence': {'key': '', 'enabled': false},
'private': false,
}
});
Expand All @@ -54,7 +54,7 @@ void main() {
expect(joinPush.payload, {
'config': {
'broadcast': {'ack': false, 'self': false},
'presence': {'key': ''},
'presence': {'key': '', 'enabled': false},
'private': true,
},
});
Expand Down Expand Up @@ -386,4 +386,92 @@ void main() {
expect(leaveCalled, isTrue);
});
});

group('presence enabled', () {
setUp(() {
socket = RealtimeClient('', timeout: const Duration(milliseconds: 1234));
});

test('should enable presence when config.presence.enabled is true even without bindings', () {
channel = RealtimeChannel(
'topic',
socket,
params: const RealtimeChannelConfig(enabled: true),
);

channel.subscribe();

final joinPayload = channel.joinPush.payload;
expect(joinPayload['config']['presence']['enabled'], isTrue);
});

test('should enable presence when presence listeners exist', () {
channel = RealtimeChannel(
'topic',
socket,
params: const RealtimeChannelConfig(),
);

channel.onPresenceSync((payload) {});
channel.subscribe();

final joinPayload = channel.joinPush.payload;
expect(joinPayload['config']['presence']['enabled'], isTrue);
});

test('should enable presence when both bindings exist and config.presence.enabled is true', () {
channel = RealtimeChannel(
'topic',
socket,
params: const RealtimeChannelConfig(enabled: true),
);

channel.onPresenceSync((payload) {});
channel.subscribe();

final joinPayload = channel.joinPush.payload;
expect(joinPayload['config']['presence']['enabled'], isTrue);
});

test('should not enable presence when neither bindings exist nor config.presence.enabled is true', () {
channel = RealtimeChannel(
'topic',
socket,
params: const RealtimeChannelConfig(),
);

channel.subscribe();

final joinPayload = channel.joinPush.payload;
expect(joinPayload['config']['presence']['enabled'], isFalse);
});

test('should enable presence when join listener exists', () {
channel = RealtimeChannel(
'topic',
socket,
params: const RealtimeChannelConfig(),
);

channel.onPresenceJoin((payload) {});
channel.subscribe();

final joinPayload = channel.joinPush.payload;
expect(joinPayload['config']['presence']['enabled'], isTrue);
});

test('should enable presence when leave listener exists', () {
channel = RealtimeChannel(
'topic',
socket,
params: const RealtimeChannelConfig(),
);

channel.onPresenceLeave((payload) {});
channel.subscribe();

final joinPayload = channel.joinPush.payload;
expect(joinPayload['config']['presence']['enabled'], isTrue);
});
});
}
Loading