Skip to content

Commit 30692a9

Browse files
author
riccardocucia
committed
Wip fix online users status stream
1 parent 05cb266 commit 30692a9

File tree

2 files changed

+44
-35
lines changed

2 files changed

+44
-35
lines changed

example/lib/src/pages/auth.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:flutter_login/flutter_login.dart';
55
import 'package:flutter_supabase_chat_core/flutter_supabase_chat_core.dart';
66
import 'package:supabase_flutter/supabase_flutter.dart';
77

8-
import 'rooms.dart';
8+
import 'home.dart';
99

1010
class AuthScreen extends StatefulWidget {
1111
const AuthScreen({
@@ -83,7 +83,7 @@ class _AuthScreenState extends State<AuthScreen> {
8383
onSubmitAnimationCompleted: () {
8484
Navigator.of(context).pushReplacement(
8585
MaterialPageRoute(
86-
builder: (context) => const RoomsPage(),
86+
builder: (context) => const HomePage(),
8787
),
8888
);
8989
},

lib/src/class/supabase_chat_core.dart

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,25 @@ class SupabaseChatCore {
1515
Supabase.instance.client.auth.onAuthStateChange.listen((data) async {
1616
if (loggedSupabaseUser != null) {
1717
_loggedUser = await user(uid: loggedSupabaseUser!.id);
18-
_currentUserOnlineStatusChannel =
19-
getUserOnlineStatusChannel(loggedSupabaseUser!.id);
18+
if (_currentUserOnlineStatusChannel == null) {
19+
_currentUserOnlineStatusChannel ??=
20+
_getUserOnlineStatusChannel(loggedSupabaseUser!.id);
21+
_currentUserOnlineStatusChannel?.subscribe(
22+
(status, error) async {
23+
_userStatusSubscribed =
24+
status == RealtimeSubscribeStatus.subscribed;
25+
if (_lastOnlineStatus == UserOnlineStatus.online) {
26+
await _trackUserStatus();
27+
} else {
28+
await _currentUserOnlineStatusChannel?.untrack();
29+
}
30+
},
31+
);
32+
}
2033
} else {
2134
_loggedUser = null;
35+
await _currentUserOnlineStatusChannel?.unsubscribe();
36+
_userStatusSubscribed = false;
2237
_currentUserOnlineStatusChannel = null;
2338
}
2439
});
@@ -57,15 +72,14 @@ class SupabaseChatCore {
5772
/// Current logged in user. Is update automatically.
5873
types.User? get loggedUser => _loggedUser;
5974

60-
/// Returns user online status realtime channel .
61-
RealtimeChannel getUserOnlineStatusChannel(String uid) =>
75+
RealtimeChannel _getUserOnlineStatusChannel(String uid) =>
6276
client.channel('${config.realtimeOnlineUserPrefixChannel}$uid');
6377

64-
/// Returns a current user online status realtime channel .
78+
UserOnlineStatus _lastOnlineStatus = UserOnlineStatus.offline;
79+
6580
RealtimeChannel? _currentUserOnlineStatusChannel;
6681

6782
bool _userStatusSubscribed = false;
68-
bool _userStatusSubscribing = false;
6983

7084
Future<void> _trackUserStatus() async {
7185
final userStatus = {
@@ -76,18 +90,7 @@ class SupabaseChatCore {
7690
}
7791

7892
Future<void> setPresenceStatus(UserOnlineStatus status) async {
79-
if (!_userStatusSubscribed && !_userStatusSubscribing) {
80-
_userStatusSubscribing = true;
81-
_currentUserOnlineStatusChannel?.subscribe(
82-
(status, error) async {
83-
if (status != RealtimeSubscribeStatus.subscribed) return;
84-
_userStatusSubscribed = true;
85-
_userStatusSubscribing = false;
86-
await _trackUserStatus();
87-
},
88-
);
89-
}
90-
93+
_lastOnlineStatus = status;
9194
switch (status) {
9295
case UserOnlineStatus.online:
9396
if (_userStatusSubscribed) {
@@ -102,6 +105,27 @@ class SupabaseChatCore {
102105
}
103106
}
104107

108+
final Map<String, RealtimeChannel> _onlineUserChannels = {};
109+
110+
UserOnlineStatus _userStatus(List<Presence> presences, String uid) =>
111+
presences.map((e) => e.payload['uid']).contains(uid)
112+
? UserOnlineStatus.online
113+
: UserOnlineStatus.offline;
114+
115+
/// Returns a stream of online user state from Supabase Realtime.
116+
Stream<UserOnlineStatus> userOnlineStatus(String uid) {
117+
final controller = StreamController<UserOnlineStatus>();
118+
if(_onlineUserChannels[uid]==null) {
119+
_onlineUserChannels[uid] = _getUserOnlineStatusChannel(uid);
120+
_onlineUserChannels[uid]!.onPresenceJoin((payload) {
121+
controller.sink.add(_userStatus(payload.newPresences, uid));
122+
}).onPresenceLeave((payload) {
123+
controller.sink.add(_userStatus(payload.currentPresences, uid));
124+
}).subscribe();
125+
}
126+
return controller.stream;
127+
}
128+
105129
/// Returns the URL of an asset path in the bucket
106130
String getAssetUrl(String path) =>
107131
'${client.storage.url}/object/authenticated/${config.chatAssetsBucket}/$path';
@@ -324,21 +348,6 @@ class SupabaseChatCore {
324348
);
325349
}
326350

327-
/// Returns a stream of online user state from Supabase Realtime.
328-
Stream<UserOnlineStatus> userOnlineStatus(String uid) {
329-
final controller = StreamController<UserOnlineStatus>();
330-
UserOnlineStatus userStatus(List<Presence> presences, String uid) =>
331-
presences.map((e) => e.payload['uid']).contains(uid)
332-
? UserOnlineStatus.online
333-
: UserOnlineStatus.offline;
334-
getUserOnlineStatusChannel(uid).onPresenceJoin((payload) {
335-
controller.sink.add(userStatus(payload.newPresences, uid));
336-
}).onPresenceLeave((payload) {
337-
controller.sink.add(userStatus(payload.currentPresences, uid));
338-
}).subscribe();
339-
return controller.stream;
340-
}
341-
342351
/// Returns a paginated list of rooms from Supabase. Only rooms where current
343352
/// logged in user exist are returned.
344353
Future<List<types.Room>> rooms({

0 commit comments

Comments
 (0)