Skip to content

Commit 4a32a14

Browse files
committed
fix: add presence flag
1 parent ae2d12d commit 4a32a14

File tree

3 files changed

+100
-3
lines changed

3 files changed

+100
-3
lines changed

packages/realtime_client/lib/src/realtime_channel.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,14 @@ class RealtimeChannel {
130130
if (callback != null) callback(RealtimeSubscribeStatus.closed, null);
131131
});
132132

133+
final presenceEnabled =
134+
(_bindings['presence']?.isNotEmpty == true) ||
135+
(params['config']['presence']['enabled'] == true);
136+
133137
final accessTokenPayload = <String, String>{};
134138
final config = <String, dynamic>{
135139
'broadcast': broadcast,
136-
'presence': presence,
140+
'presence': {...presence, 'enabled': presenceEnabled},
137141
'postgres_changes':
138142
_bindings['postgres_changes']?.map((r) => r.filter).toList() ?? [],
139143
'private': isPrivate == true,

packages/realtime_client/lib/src/types.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,17 @@ class RealtimeChannelConfig {
148148
/// [key] option is used to track presence payload across clients
149149
final String key;
150150

151+
/// Enables presence even without presence bindings
152+
final bool enabled;
153+
151154
/// Defines if the channel is private or not and if RLS policies will be used to check data
152155
final bool private;
153156

154157
const RealtimeChannelConfig({
155158
this.ack = false,
156159
this.self = false,
157160
this.key = '',
161+
this.enabled = false,
158162
this.private = false,
159163
});
160164

@@ -167,6 +171,7 @@ class RealtimeChannelConfig {
167171
},
168172
'presence': {
169173
'key': key,
174+
'enabled': enabled,
170175
},
171176
'private': private,
172177
}

packages/realtime_client/test/channel_test.dart

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void main() {
3434
expect(channel.params, {
3535
'config': {
3636
'broadcast': {'ack': false, 'self': false},
37-
'presence': {'key': ''},
37+
'presence': {'key': '', 'enabled': false},
3838
'private': false,
3939
}
4040
});
@@ -54,7 +54,7 @@ void main() {
5454
expect(joinPush.payload, {
5555
'config': {
5656
'broadcast': {'ack': false, 'self': false},
57-
'presence': {'key': ''},
57+
'presence': {'key': '', 'enabled': false},
5858
'private': true,
5959
},
6060
});
@@ -386,4 +386,92 @@ void main() {
386386
expect(leaveCalled, isTrue);
387387
});
388388
});
389+
390+
group('presence enabled', () {
391+
setUp(() {
392+
socket = RealtimeClient('', timeout: const Duration(milliseconds: 1234));
393+
});
394+
395+
test('should enable presence when config.presence.enabled is true even without bindings', () {
396+
channel = RealtimeChannel(
397+
'topic',
398+
socket,
399+
params: const RealtimeChannelConfig(enabled: true),
400+
);
401+
402+
channel.subscribe();
403+
404+
final joinPayload = channel.joinPush.payload;
405+
expect(joinPayload['config']['presence']['enabled'], isTrue);
406+
});
407+
408+
test('should enable presence when presence listeners exist', () {
409+
channel = RealtimeChannel(
410+
'topic',
411+
socket,
412+
params: const RealtimeChannelConfig(),
413+
);
414+
415+
channel.onPresenceSync((payload) {});
416+
channel.subscribe();
417+
418+
final joinPayload = channel.joinPush.payload;
419+
expect(joinPayload['config']['presence']['enabled'], isTrue);
420+
});
421+
422+
test('should enable presence when both bindings exist and config.presence.enabled is true', () {
423+
channel = RealtimeChannel(
424+
'topic',
425+
socket,
426+
params: const RealtimeChannelConfig(enabled: true),
427+
);
428+
429+
channel.onPresenceSync((payload) {});
430+
channel.subscribe();
431+
432+
final joinPayload = channel.joinPush.payload;
433+
expect(joinPayload['config']['presence']['enabled'], isTrue);
434+
});
435+
436+
test('should not enable presence when neither bindings exist nor config.presence.enabled is true', () {
437+
channel = RealtimeChannel(
438+
'topic',
439+
socket,
440+
params: const RealtimeChannelConfig(),
441+
);
442+
443+
channel.subscribe();
444+
445+
final joinPayload = channel.joinPush.payload;
446+
expect(joinPayload['config']['presence']['enabled'], isFalse);
447+
});
448+
449+
test('should enable presence when join listener exists', () {
450+
channel = RealtimeChannel(
451+
'topic',
452+
socket,
453+
params: const RealtimeChannelConfig(),
454+
);
455+
456+
channel.onPresenceJoin((payload) {});
457+
channel.subscribe();
458+
459+
final joinPayload = channel.joinPush.payload;
460+
expect(joinPayload['config']['presence']['enabled'], isTrue);
461+
});
462+
463+
test('should enable presence when leave listener exists', () {
464+
channel = RealtimeChannel(
465+
'topic',
466+
socket,
467+
params: const RealtimeChannelConfig(),
468+
);
469+
470+
channel.onPresenceLeave((payload) {});
471+
channel.subscribe();
472+
473+
final joinPayload = channel.joinPush.payload;
474+
expect(joinPayload['config']['presence']['enabled'], isTrue);
475+
});
476+
});
389477
}

0 commit comments

Comments
 (0)