@@ -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