[NEW] Stream to get individual presence updates (#3606)
Co-authored-by: Gerzon Z <gerzonzcanario@gmail.com>
This commit is contained in:
parent
7d23385555
commit
ab9d568528
|
@ -58,7 +58,7 @@ export const SNIPPETED_MESSAGES = createRequestTypes('SNIPPETED_MESSAGES', ['OPE
|
|||
export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN']);
|
||||
export const SORT_PREFERENCES = createRequestTypes('SORT_PREFERENCES', ['SET_ALL', 'SET']);
|
||||
export const SET_CUSTOM_EMOJIS = 'SET_CUSTOM_EMOJIS';
|
||||
export const SET_ACTIVE_USERS = 'SET_ACTIVE_USERS';
|
||||
export const ACTIVE_USERS = createRequestTypes('ACTIVE_USERS', ['SET', 'CLEAR']);
|
||||
export const USERS_TYPING = createRequestTypes('USERS_TYPING', ['ADD', 'REMOVE', 'CLEAR']);
|
||||
export const INVITE_LINKS = createRequestTypes('INVITE_LINKS', [
|
||||
'SET_TOKEN',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { IActiveUsers } from '../reducers/activeUsers';
|
||||
import { SET_ACTIVE_USERS } from './actionsTypes';
|
||||
import { ACTIVE_USERS } from './actionsTypes';
|
||||
|
||||
interface ISetActiveUsers extends Action {
|
||||
activeUsers: IActiveUsers;
|
||||
|
@ -10,6 +10,10 @@ interface ISetActiveUsers extends Action {
|
|||
export type TActionActiveUsers = ISetActiveUsers;
|
||||
|
||||
export const setActiveUsers = (activeUsers: IActiveUsers): ISetActiveUsers => ({
|
||||
type: SET_ACTIVE_USERS,
|
||||
type: ACTIVE_USERS.SET,
|
||||
activeUsers
|
||||
});
|
||||
|
||||
export const clearActiveUsers = (): Action => ({
|
||||
type: ACTIVE_USERS.CLEAR
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@ export function subscribeUsersPresence() {
|
|||
this.activeUsersSubTimeout = setTimeout(() => {
|
||||
this.sdk.subscribe('activeUsers');
|
||||
}, 5000);
|
||||
} else {
|
||||
} else if (compareServerVersion(serverVersion, 'lowerThan', '4.1.0')) {
|
||||
this.sdk.subscribe('stream-notify-logged', 'user-status');
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,11 @@ export default async function getUsersPresence() {
|
|||
try {
|
||||
// RC 1.1.0
|
||||
const result = await this.sdk.get('users.presence', params);
|
||||
|
||||
if (compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '4.1.0')) {
|
||||
this.sdk.subscribeRaw('stream-user-presence', ['', { added: ids }]);
|
||||
}
|
||||
|
||||
if (result.success) {
|
||||
const { users } = result;
|
||||
|
||||
|
@ -100,13 +105,9 @@ export default async function getUsersPresence() {
|
|||
|
||||
let usersTimer = null;
|
||||
export function getUserPresence(uid) {
|
||||
const auth = reduxStore.getState().login.isAuthenticated;
|
||||
|
||||
if (!usersTimer) {
|
||||
usersTimer = setTimeout(() => {
|
||||
if (auth && ids.length) {
|
||||
getUsersPresence.call(this);
|
||||
}
|
||||
getUsersPresence.call(this);
|
||||
usersTimer = null;
|
||||
}, 2000);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import { compareServerVersion } from './utils';
|
|||
import reduxStore from './createStore';
|
||||
import database from './database';
|
||||
import subscribeRooms from './methods/subscriptions/rooms';
|
||||
import getUsersPresence, { getUserPresence, subscribeUsersPresence } from './methods/getUsersPresence';
|
||||
import { getUserPresence, subscribeUsersPresence } from './methods/getUsersPresence';
|
||||
import protectedFunction from './methods/helpers/protectedFunction';
|
||||
import readMessages from './methods/readMessages';
|
||||
import getSettings, { getLoginSettings, setSettings, subscribeSettings } from './methods/getSettings';
|
||||
|
@ -308,10 +308,26 @@ const RocketChat = {
|
|||
protectedFunction(ddpMessage => onRolesChanged(ddpMessage))
|
||||
);
|
||||
|
||||
// RC 4.1
|
||||
this.sdk.onStreamData('stream-user-presence', ddpMessage => {
|
||||
const userStatus = ddpMessage.fields.args[0];
|
||||
const { uid } = ddpMessage.fields;
|
||||
const [, status, statusText] = userStatus;
|
||||
const newStatus = { status: STATUSES[status], statusText };
|
||||
reduxStore.dispatch(setActiveUsers({ [uid]: newStatus }));
|
||||
|
||||
const { user: loggedUser } = reduxStore.getState().login;
|
||||
if (loggedUser && loggedUser.id === uid) {
|
||||
reduxStore.dispatch(setUser(newStatus));
|
||||
}
|
||||
});
|
||||
|
||||
this.notifyLoggedListener = this.sdk.onStreamData(
|
||||
'stream-notify-logged',
|
||||
protectedFunction(async ddpMessage => {
|
||||
const { eventName } = ddpMessage.fields;
|
||||
|
||||
// `user-status` event is deprecated after RC 4.1 in favor of `stream-user-presence/${uid}`
|
||||
if (/user-status/.test(eventName)) {
|
||||
this.activeUsers = this.activeUsers || {};
|
||||
if (!this._setUserTimer) {
|
||||
|
@ -1633,15 +1649,18 @@ const RocketChat = {
|
|||
reduxStore.dispatch(setUser({ status: { status: 'offline' } }));
|
||||
}
|
||||
|
||||
if (!this._setUserTimer) {
|
||||
this._setUserTimer = setTimeout(() => {
|
||||
const activeUsersBatch = this.activeUsers;
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
reduxStore.dispatch(setActiveUsers(activeUsersBatch));
|
||||
});
|
||||
this._setUserTimer = null;
|
||||
return (this.activeUsers = {});
|
||||
}, 10000);
|
||||
const serverVersion = reduxStore.getState().server.version;
|
||||
if (compareServerVersion(serverVersion, 'lowerThan', '4.1.0')) {
|
||||
if (!this._setUserTimer) {
|
||||
this._setUserTimer = setTimeout(() => {
|
||||
const activeUsersBatch = this.activeUsers;
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
reduxStore.dispatch(setActiveUsers(activeUsersBatch));
|
||||
});
|
||||
this._setUserTimer = null;
|
||||
return (this.activeUsers = {});
|
||||
}, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ddpMessage.fields) {
|
||||
|
@ -1650,7 +1669,6 @@ const RocketChat = {
|
|||
this.activeUsers[ddpMessage.id] = { status: ddpMessage.fields.status };
|
||||
}
|
||||
},
|
||||
getUsersPresence,
|
||||
getUserPresence,
|
||||
subscribeUsersPresence,
|
||||
getDirectory({ query, count, offset, sort }) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { setActiveUsers } from '../actions/activeUsers';
|
||||
import { clearActiveUsers, setActiveUsers } from '../actions/activeUsers';
|
||||
import { IActiveUsers, initialState } from './activeUsers';
|
||||
import { mockedStore } from './mockedStore';
|
||||
|
||||
|
@ -13,4 +13,11 @@ describe('test reducer', () => {
|
|||
const state = mockedStore.getState().activeUsers;
|
||||
expect(state).toEqual({ ...activeUsers });
|
||||
});
|
||||
it('should return initial state after dispatching clear', () => {
|
||||
const previousState = mockedStore.getState().activeUsers;
|
||||
expect(previousState).not.toBe(initialState);
|
||||
mockedStore.dispatch(clearActiveUsers());
|
||||
const state = mockedStore.getState().activeUsers;
|
||||
expect(state).toEqual(initialState);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { TApplicationActions } from '../definitions';
|
||||
import { SET_ACTIVE_USERS } from '../actions/actionsTypes';
|
||||
import { ACTIVE_USERS } from '../actions/actionsTypes';
|
||||
|
||||
type TUserStatus = 'online' | 'offline';
|
||||
type TUserStatus = 'online' | 'offline' | 'away' | 'busy';
|
||||
export interface IActiveUser {
|
||||
status: TUserStatus;
|
||||
statusText: string;
|
||||
|
@ -15,11 +15,13 @@ export const initialState: IActiveUsers = {};
|
|||
|
||||
export default function activeUsers(state = initialState, action: TApplicationActions): IActiveUsers {
|
||||
switch (action.type) {
|
||||
case SET_ACTIVE_USERS:
|
||||
case ACTIVE_USERS.SET:
|
||||
return {
|
||||
...state,
|
||||
...action.activeUsers
|
||||
};
|
||||
case ACTIVE_USERS.CLEAR:
|
||||
return initialState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import EventEmitter from '../utils/events';
|
|||
import { inviteLinksRequest } from '../actions/inviteLinks';
|
||||
import { showErrorAlert } from '../utils/info';
|
||||
import { localAuthenticate } from '../utils/localAuthentication';
|
||||
import { setActiveUsers } from '../actions/activeUsers';
|
||||
import { encryptionInit, encryptionStop } from '../actions/encryption';
|
||||
import UserPreferences from '../lib/userPreferences';
|
||||
import { inquiryRequest, inquiryReset } from '../ee/omnichannel/actions/inquiry';
|
||||
|
@ -100,7 +99,6 @@ const registerPushToken = function* registerPushToken() {
|
|||
};
|
||||
|
||||
const fetchUsersPresence = function* fetchUserPresence() {
|
||||
yield RocketChat.getUsersPresence();
|
||||
RocketChat.subscribeUsersPresence();
|
||||
};
|
||||
|
||||
|
@ -222,11 +220,6 @@ const handleLogout = function* handleLogout({ forcedByServer }) {
|
|||
const handleSetUser = function* handleSetUser({ user }) {
|
||||
setLanguage(user?.language);
|
||||
|
||||
if (user && user.status) {
|
||||
const userId = yield select(state => state.login.user.id);
|
||||
yield put(setActiveUsers({ [userId]: user }));
|
||||
}
|
||||
|
||||
if (user?.statusLivechat && RocketChat.isOmnichannelModuleAvailable()) {
|
||||
if (isOmnichannelStatusAvailable(user)) {
|
||||
yield put(inquiryRequest());
|
||||
|
|
|
@ -10,6 +10,7 @@ import { SERVER } from '../actions/actionsTypes';
|
|||
import { selectServerFailure, selectServerRequest, selectServerSuccess, serverFailure } from '../actions/server';
|
||||
import { clearSettings } from '../actions/settings';
|
||||
import { setUser } from '../actions/login';
|
||||
import { clearActiveUsers } from '../actions/activeUsers';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import database from '../lib/database';
|
||||
import log, { logServerVersion } from '../utils/log';
|
||||
|
@ -73,6 +74,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch
|
|||
|
||||
yield put(inquiryReset());
|
||||
yield put(encryptionStop());
|
||||
yield put(clearActiveUsers());
|
||||
const serversDB = database.servers;
|
||||
yield UserPreferences.setStringAsync(RocketChat.CURRENT_SERVER, server);
|
||||
const userId = yield UserPreferences.getStringAsync(`${RocketChat.TOKEN_KEY}-${server}`);
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
"@react-navigation/stack": "5.14.5",
|
||||
"@rocket.chat/message-parser": "0.30.0",
|
||||
"@rocket.chat/react-native-fast-image": "^8.2.0",
|
||||
"@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile",
|
||||
"@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#subscribe-raw",
|
||||
"@rocket.chat/ui-kit": "0.13.0",
|
||||
"bytebuffer": "^5.0.1",
|
||||
"color2k": "1.2.4",
|
||||
|
|
|
@ -3758,9 +3758,9 @@
|
|||
resolved "https://registry.yarnpkg.com/@rocket.chat/react-native-fast-image/-/react-native-fast-image-8.2.0.tgz#4f48858f95f40afcb10b39cee9b1239c150d6c51"
|
||||
integrity sha512-NF5KlFt642ZucP/KHnYGBNYLD6O7bcrZMKfRQlH5Y3/1xpnPX1g4wuygtiV7XArMU1FopQT+qmCUPPj8IMDTcw==
|
||||
|
||||
"@rocket.chat/sdk@RocketChat/Rocket.Chat.js.SDK#mobile":
|
||||
version "1.1.0-mobile"
|
||||
resolved "https://codeload.github.com/RocketChat/Rocket.Chat.js.SDK/tar.gz/c64e69ea22514ae3bbe24e36ca77868fdae76157"
|
||||
"@rocket.chat/sdk@RocketChat/Rocket.Chat.js.SDK#subscribe-raw":
|
||||
version "1.2.0-mobile"
|
||||
resolved "https://codeload.github.com/RocketChat/Rocket.Chat.js.SDK/tar.gz/6eb97d265d2e2054eced23fc78145ab179e3a1f3"
|
||||
dependencies:
|
||||
js-sha256 "^0.9.0"
|
||||
lru-cache "^4.1.1"
|
||||
|
|
Loading…
Reference in New Issue