User Presence

LAST EDIT Mar 05 2021

User presence allows you to show when a user was last active and if they are online right now. Whenever you read a user the data will look like this:

1
2
3
4
5
6
{ 
    id: 'unique_user_id', 
    online: true, 
    status: 'Eating a veggie burger...', 
    last_active: '2019-01-07T13:17:42.375Z' 
}
The online field indicates if the user is online. The status field stores text indicating the current user status.

Invisible

Copied!

To mark a user invisible simply set the invisible property to true. You can also set a custom status message at the same time:

1
2
3
4
5
// mark a user as invisible 
await client.connectUser({ 
    id: 'unique_user_id', 
    invisible: true 
});
1
2
3
4
5
6
7
8
9
10
11
val user = User( 
    id = "user-id", 
    invisible = true, 
) 
client.connectUser(user, "CHAT_USER_TOKEN").enqueue { result -> 
    if (result.isSuccess) { 
        val user: ConnectionData = result.data() 
    } else { 
        // Handle result.error() 
    } 
}
1
2
3
4
5
6
7
8
9
await client.connectUser( 
    User( 
      id: 'super-band-9', 
      extraData: { 
        'invisible': true, 
      }, 
    ), 
    'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A', 
  );
1
2
3
4
5
6
7
8
9
10
User user = new User(); 
user.setId("user-id"); 
user.setInvisible(true); 
client.connectUser(user, "CHAT_USER_TOKEN").enqueue(result -> { 
    if (result.isSuccess()) { 
        User userRes = result.data().getUser(); 
    } else { 
        // Handle result.error() 
    } 
});
When invisible is set to true, the current user will appear as offline to other users.

Listening to Presence Changes

Copied!

Of course, you want to listen to the user presence changes. This allows you to show a user as offline when they leave and update their status in real time. These 3 endpoints allow you to watch user presence:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// If you pass presence: true to channel.watch it will watch the list of user presence changes. 
// Note that you can listen to at most 10 users using this API call 
const channel = client.channel('messaging', 'my-conversation-123', { 
    members: ['john', 'jack'], 
    color: 'green' 
}); 
 
const state = await channel.watch({ presence: true }); 
 
// queryChannels allows you to listen to the members of the channels that are returned 
// so this does the same thing as above and listens to online status changes for john and jack 
const channels = await client.queryChannels( 
    { color: 'green' }, 
    { last_message_at: -1 }, 
    { presence: true } 
); 
 
// queryUsers allows you to listen to user presence changes for john and jack 
const users = await client.queryUsers({ 
    id: { 
      $in: [ 
        'john',  
        'jack' 
       ] 
    }},  
    { id: -1 },  
    { presence: true } 
 );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// You need to be watching some channels/queries to be able to get presence events. 
// Here are three different ways of doing that: 
 
// 1. Watch a single channel with presence = true set 
val watchRequest = WatchChannelRequest().apply { 
    data["members"] = listOf("john", "jack") 
    presence = true 
} 
channelClient.watch(watchRequest).enqueue { result -> 
    if (result.isSuccess) { 
        val channel: Channel = result.data() 
    } else { 
        // Handle result.error() 
    } 
} 
 
// 2. Query some channels with presence = true set 
val channelsRequest = QueryChannelsRequest( 
    filter = Filters.and( 
        Filters.eq("type", "messaging"), 
        Filters.`in`("members", listOf("john", "jack")), 
    ), 
    offset = 0, 
    limit = 10, 
).apply { 
    presence = true 
} 
client.queryChannels(channelsRequest).enqueue { result -> 
    if (result.isSuccess) { 
        val channels: List<Channel> = result.data() 
    } else { 
        // Handle result.error() 
    } 
} 
 
// 3. Query some users with presence = true set 
val usersQuery = QueryUsersRequest( 
    filter = Filters.`in`("id", listOf("john", "jack")), 
    offset = 0, 
    limit = 2, 
    presence = true, 
) 
client.queryUsers(usersQuery).enqueue { result -> 
    if (result.isSuccess) { 
        val users: List<User> = result.data() 
    } else { 
        // Handle result.error() 
    } 
} 
 
// Finally, subscribe to presence to events 
client.subscribeFor<UserPresenceChangedEvent> { event -> 
    // Handle change 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// You need to be watching some channels/queries to be able to get presence events. 
// There are multiple ways of doing so: 
 
let channel = Client.shared.channel(type: .messaging, id: "general") 
 
// 1. Query a channel for presence event 
let query = ChannelQuery(channel: channel, options: .presence) 
channel.query(options: .presence) { (result) in /**/ } 
 
// 2. Query all channels with presence events 
let query = ChannelsQuery(options: .presence) 
Client.shared.queryChannels(query: query) { (result) in /**/ } 
 
// 3. Query all users for presence 
let query = UsersQuery(filter: .none, sort: .none, options: .presence) 
Client.shared.queryUsers(query: query) { (result) in /**/ } 
 
// 4. Start watching a specific channel to be able to get notified 
channel.watch(options: .presence) { (result) in 
    // handle result of `watch` call 
    // note that this callback will only be called once, not for each event 
} 
 
// Finally, Subscribe to events 
let subscription = Client.shared.subscribe(forEvents: [.userPresenceChanged]) { event in 
    // handle event 
    // this callback will be called for all user presence change events 
} 
// Cancel subscription when you want to stop receiving events 
subscription.cancel()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// If you pass presence: true to channel.watch it will watch the list of user presence changes. 
// Note that you can listen to at most 10 users using this API call 
final channel = client.channel( 
  'messaging', 
  id: 'flutterdevs', 
  extraData: { 
    'name': 'Flutter devs', 
  }, 
); 
 
 
await channel.watch({ 
  'presence': true, 
}); 
 
// queryChannels allows you to listen to the members of the channels that are returned 
// so this does the same thing as above and listens to online status changes for john and jack 
 
final filter = { 
  "type": "messaging", 
  "members": { 
    "\$in": ["john"] 
  } 
}; 
 
final sort = [SortOption("last_message_at", direction: SortOption.DESC)]; 
 
final channels = await client.queryChannels( 
  filter: filter, 
  sort: sort, 
  options: { 
    'presence': true, 
  } 
); 
 
// queryUsers allows you to listen to user presence changes for john and jack 
final result = await client.queryUsers( 
  filter: { 
    "id": { 
      "\$in": ['john', 'jack', 'jessie'] 
    } 
  }, 
  sort: [SortOption('last_active')], 
  pagination: PaginationParams( 
    offset: 0, 
    limit: 20, 
  ), 
  options: { 
    'presence': true, 
  } 
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// You need to be watching some channels/queries to be able to get presence events. 
// Here are three different ways of doing that: 
 
// 1. Watch a single channel with presence = true set 
WatchChannelRequest watchRequest = new WatchChannelRequest(); 
watchRequest.setPresence(true); 
watchRequest.getData().put("members", Arrays.asList("john", "jack")); 
channelClient.watch(watchRequest).enqueue(result -> { 
    if (result.isSuccess()) { 
        Channel channel = result.data(); 
    } else { 
        // Handle result.error() 
    } 
}); 
 
// 2. Query some channels with presence events 
int channelsOffset = 0; 
int channelsLimit = 10; 
FilterObject channelsFilter = Filters.and( 
        Filters.eq("type", "messaging"),  
        Filters.in("members", Arrays.asList("john", "jack")) 
); 
QuerySort<Channel> channelsSort = new QuerySort<>(); 
int messageLimit = 0; 
int memberLimit = 0; 
QueryChannelsRequest channelsRequest = new QueryChannelsRequest( 
        channelsFilter, 
        channelsOffset, 
        channelsLimit, 
        channelsSort, 
        messageLimit, 
        memberLimit 
); 
client.queryChannels(channelsRequest).enqueue(result -> { 
    if (result.isSuccess()) { 
        List<Channel> channels = result.data(); 
    } else { 
        // Handle result.error() 
    } 
}); 
 
// 3. Query some users with presence = true set 
int usersOffset = 0; 
int usersLimit = 2; 
FilterObject usersFilter = Filters.in("id", Arrays.asList("john", "jack")); 
QueryUsersRequest usersQuery = new QueryUsersRequest(usersFilter, usersOffset, usersLimit); 
usersQuery.setPresence(true); 
client.queryUsers(usersQuery).enqueue(result -> { 
    if (result.isSuccess()) { 
        List<User> users = result.data(); 
    } else { 
        // Handle result.error() 
    } 
}); 
 
// Finally, Subscribe to events 
client.subscribeFor( 
        new Class[]{UserPresenceChangedEvent.class}, 
        event -> { 
            // Handle change 
        } 
);

A users online status change can be handled via event delegation by subscribing to the  user.presence.changed event the same you do for any other event.