{ id: 'unique_user_id', online: true, status: 'Eating a veggie burger...', last_active: '2019-01-07T13:17:42.375Z' }User Presence
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:
// Get a channel var channel = await Client.GetOrCreateChannelWithIdAsync(ChannelType.Messaging, "my-channel-id"); // Members are users belonging to this channel var member = channel.Members.First(); // Each member object contains a user object. A single user can be a member of many channels var user = member.User; var message = channel.Messages.First(); // Each message contains the author user object var user2 = message.User; // Presence related fields on a user object var isOnline = user.Online; var lastActive = user.LastActive;guard let member = channelController.channel?.lastActiveMembers.first else { return } let isOnline = member.isOnline let lastActiveAt = member.lastActiveAtThe online field indicates if the user is online. The status field stores text indicating the current user status.
The last_active field is updated when a user connects and then refreshed every 15 minutes.
Invisible
To mark your user as invisible, you can update your user to set the invisible property to true. Your user will remain invisible even if you disconnect and reconnect. You must explicitly set invisible to false in order to become visible again.
// become invisible await client.upsertUser({ id: "unique_user_id", invisible: true, }); // become visible await client.upsertUser({ id: "unique_user_id", invisible: false, });// Get local user object var localUserData = await Client.ConnectUserAsync("api-key", "user-id", "user-token"); // Or like this var localUserData2 = Client.LocalUserData; // Get local user object var localUser = localUserData.User; // Check local user invisibility status var isInvisible = localUser.Invisible; // Mark invisible await localUser.MarkInvisibleAsync(); // Mark visible await localUser.MarkVisibleAsync();You can also set your user to invisible when connecting by setting the invisible property to true. You can also set a custom status message at the same time:
// mark a user as invisible await client.connectUser({ id: "unique_user_id", invisible: true, });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() } }await client.connectUser( User( id: 'super-band-9', extraData: { 'invisible': true, }, ), 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A', );FUser User{TEXT("user-id")}; User.bInvisible = true; const FString Token{TEXT("{{ chat_user_token }}")}; Client->ConnectUser( User, Token);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() } });// Will be implemented soon, please send a support ticket if you need this featurechatClient.connectUser( userInfo: .init( id: userID, isInvisible: true ), token: token ) { error in // … }When invisibleis set to true, the current user will appear as offline to other users.
Listening to Presence Changes
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:
// 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 }, );// 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 }class PresenceObservingChannelVC: ChatChannelVC, EventsControllerDelegate { let eventsController: EventsController! override func viewDidLoad() { super.viewDidLoad() eventsController.delegate = self } func eventsController(_ controller: EventsController, didReceiveEvent event: Event) { if let event = event as? UserPresenceChangedEvent { showUser(event.user, isOnline: event.user.isOnline) } } }// 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, } );// 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 constexpr EChannelFlags AllFlags = EChannelFlags::Watch | EChannelFlags::State | EChannelFlags::Presence; const FChannelProperties Properties{TEXT("messaging"), TEXT("unrealdevs")}; Client->QueryChannel(Properties, AllFlags); // 2. Query some channels with 'presence' set Client->QueryChannels( FFilter::Equal(TEXT("type"), TEXT("messaging")), // Channel filter {}, // Sort options AllFlags // Flags ); // 3. Query some users with presence = true set Client->QueryUsers( FFilter::In(TEXT("id"), {TEXT("john"), TEXT("jack")}), {}, // Sort options true, // Presence {{0, 2}} // Pagination options ); // Finally, subscribe to presence to events Client->On<FUserPresenceChangedEvent>( [](const FUserPresenceChangedEvent& Event) { // Handle change });// 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")) ); QuerySorter<Channel> channelsSort = new QuerySortByField<>(); 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 } );// Get a channel var channel = await Client.GetOrCreateChannelWithIdAsync(ChannelType.Messaging, "my-channel-id"); // Members are users belonging to this channel var member = channel.Members.First(); // Each member object contains a user object. A single user can be a member of many channels var user = member.User; // Each user object exposes the PresenceChange event that will trigger when Online status changes user.PresenceChanged += (userObj, isOnline, isActive) => { };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.