From 6ada35e4602bf1569496ce44de9beb9fa23971c3 Mon Sep 17 00:00:00 2001 From: Djorkaeff Alexandre Date: Tue, 3 Mar 2020 18:10:39 -0300 Subject: [PATCH] [IMPROVEMENT] Request user presence on demand (#1813) Co-authored-by: Diego Mello --- app/lib/methods/getUsersPresence.js | 72 +++++++++++++++++++++++++++++ app/lib/rocketchat.js | 40 ++-------------- app/presentation/RoomItem/index.js | 15 ++++-- app/sagas/login.js | 7 +-- app/views/RoomsListView/index.js | 3 ++ 5 files changed, 95 insertions(+), 42 deletions(-) create mode 100644 app/lib/methods/getUsersPresence.js diff --git a/app/lib/methods/getUsersPresence.js b/app/lib/methods/getUsersPresence.js new file mode 100644 index 000000000..e4a87856c --- /dev/null +++ b/app/lib/methods/getUsersPresence.js @@ -0,0 +1,72 @@ +import { InteractionManager } from 'react-native'; +import semver from 'semver'; + +import reduxStore from '../createStore'; +import { setActiveUsers } from '../../actions/activeUsers'; + +export function subscribeUsersPresence() { + const serverVersion = reduxStore.getState().server.version; + + // if server is lower than 1.1.0 + if (serverVersion && semver.lt(semver.coerce(serverVersion), '1.1.0')) { + if (this.activeUsersSubTimeout) { + clearTimeout(this.activeUsersSubTimeout); + this.activeUsersSubTimeout = false; + } + this.activeUsersSubTimeout = setTimeout(() => { + this.sdk.subscribe('activeUsers'); + }, 5000); + } else { + this.sdk.subscribe('stream-notify-logged', 'user-status'); + } +} + +let ids = []; + +export default async function getUsersPresence() { + const serverVersion = reduxStore.getState().server.version; + + // if server is greather than or equal 1.1.0 + if (serverVersion && !semver.lt(semver.coerce(serverVersion), '1.1.0')) { + let params = {}; + + // if server is greather than or equal 3.0.0 + if (serverVersion && !semver.lt(semver.coerce(serverVersion), '3.0.0')) { + // if not have any id + if (!ids.length) { + return; + } + // Request userPresence on demand + params = { ids: ids.join(',') }; + ids = []; + } + + // RC 1.1.0 + const result = await this.sdk.get('users.presence', params); + if (result.success) { + const activeUsers = result.users.reduce((ret, item) => { + ret[item._id] = item.status; + return ret; + }, {}); + InteractionManager.runAfterInteractions(() => { + reduxStore.dispatch(setActiveUsers(activeUsers)); + }); + } + } +} + +let usersTimer = null; +export function getUserPresence(uid) { + const auth = reduxStore.getState().login.isAuthenticated; + + if (!usersTimer) { + usersTimer = setTimeout(() => { + if (auth && ids.length) { + getUsersPresence.call(this); + } + usersTimer = null; + }, 2000); + } + + ids.push(uid); +} diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index c0c6b1b8c..884061ef3 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -21,6 +21,7 @@ import { } from '../actions/share'; import subscribeRooms from './methods/subscriptions/rooms'; +import getUsersPresence, { getUserPresence, subscribeUsersPresence } from './methods/getUsersPresence'; import protectedFunction from './methods/helpers/protectedFunction'; import readMessages from './methods/readMessages'; @@ -1065,42 +1066,9 @@ const RocketChat = { this.activeUsers[ddpMessage.id] = ddpMessage.fields.status; } }, - getUserPresence() { - return new Promise(async(resolve) => { - const serverVersion = reduxStore.getState().server.version; - - // if server is lower than 1.1.0 - if (serverVersion && semver.lt(semver.coerce(serverVersion), '1.1.0')) { - if (this.activeUsersSubTimeout) { - clearTimeout(this.activeUsersSubTimeout); - this.activeUsersSubTimeout = false; - } - this.activeUsersSubTimeout = setTimeout(() => { - this.sdk.subscribe('activeUsers'); - }, 5000); - return resolve(); - } else { - const params = {}; - // if (this.lastUserPresenceFetch) { - // params.from = this.lastUserPresenceFetch.toISOString(); - // } - - // RC 1.1.0 - const result = await this.sdk.get('users.presence', params); - if (result.success) { - const activeUsers = result.users.reduce((ret, item) => { - ret[item._id] = item.status; - return ret; - }, {}); - InteractionManager.runAfterInteractions(() => { - reduxStore.dispatch(setActiveUsers(activeUsers)); - }); - this.sdk.subscribe('stream-notify-logged', 'user-status'); - return resolve(); - } - } - }); - }, + getUsersPresence, + getUserPresence, + subscribeUsersPresence, getDirectory({ query, count, offset, sort }) { diff --git a/app/presentation/RoomItem/index.js b/app/presentation/RoomItem/index.js index 601da9ef7..9993220dc 100644 --- a/app/presentation/RoomItem/index.js +++ b/app/presentation/RoomItem/index.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import { View, Text } from 'react-native'; import { connect } from 'react-redux'; @@ -40,8 +40,15 @@ const arePropsEqual = (oldProps, newProps) => { }; const RoomItem = React.memo(({ - onPress, width, favorite, toggleFav, isRead, rid, toggleRead, hideChannel, testID, unread, userMentions, name, _updatedAt, alert, type, avatarSize, baseUrl, userId, username, token, id, prid, showLastMessage, hideUnreadStatus, lastMessage, status, avatar, useRealName, theme + onPress, width, favorite, toggleFav, isRead, rid, toggleRead, hideChannel, testID, unread, userMentions, name, _updatedAt, alert, type, avatarSize, baseUrl, userId, username, token, id, prid, showLastMessage, hideUnreadStatus, lastMessage, status, avatar, useRealName, getUserPresence, theme }) => { + useEffect(() => { + if (type === 'd' && rid) { + const uid = rid.replace(userId, ''); + getUserPresence(uid); + } + }, []); + const date = formatDate(_updatedAt); let accessibilityLabel = name; @@ -190,12 +197,14 @@ RoomItem.propTypes = { avatar: PropTypes.bool, hideUnreadStatus: PropTypes.bool, useRealName: PropTypes.bool, + getUserPresence: PropTypes.func, theme: PropTypes.string }; RoomItem.defaultProps = { avatarSize: 48, - status: 'offline' + status: 'offline', + getUserPresence: () => {} }; const mapStateToProps = (state, ownProps) => ({ diff --git a/app/sagas/login.js b/app/sagas/login.js index 1bc25626d..a5bb8736a 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -71,8 +71,9 @@ const registerPushToken = function* registerPushToken() { yield RocketChat.registerPushToken(); }; -const fetchUserPresence = function* fetchUserPresence() { - yield RocketChat.getUserPresence(); +const fetchUsersPresence = function* fetchUserPresence() { + yield RocketChat.getUsersPresence(); + yield RocketChat.subscribeUsersPresence(); }; const handleLoginSuccess = function* handleLoginSuccess({ user }) { @@ -87,7 +88,7 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) { yield fork(fetchRoles); yield fork(fetchSlashCommands); yield fork(registerPushToken); - yield fork(fetchUserPresence); + yield fork(fetchUsersPresence); I18n.locale = user.language; moment.locale(toMomentLocale(user.language)); diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index 0e1877f76..b4a90165c 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -524,6 +524,8 @@ class RoomsListView extends React.Component { getRoomAvatar = item => RocketChat.getRoomAvatar(item) + getUserPresence = uid => RocketChat.getUserPresence(uid) + goRoom = (item) => { const { navigation } = this.props; this.cancelSearch(); @@ -794,6 +796,7 @@ class RoomsListView extends React.Component { toggleRead={this.toggleRead} hideChannel={this.hideChannel} useRealName={useRealName} + getUserPresence={this.getUserPresence} /> ); };