mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-02 03:57:52 +00:00
The disconnect threshold is added to account for delays in identifying disconnections (for example, the websocket disconnection takes up to 3 seconds) while fetching the latest updated conversations or messages. In this case, the cable disconnection event takes about 3 seconds to fire. If there was a conversation which was created in this 3 second, it would not be displayed in the UI until the refresh. Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
147 lines
4.6 KiB
JavaScript
147 lines
4.6 KiB
JavaScript
import { emitter } from 'shared/helpers/mitt';
|
|
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
|
import { differenceInSeconds } from 'date-fns';
|
|
import {
|
|
isAConversationRoute,
|
|
isAInboxViewRoute,
|
|
isNotificationRoute,
|
|
} from 'dashboard/helper/routeHelpers';
|
|
|
|
const MAX_DISCONNECT_SECONDS = 10800;
|
|
|
|
// The disconnect delay threshold is added to account for delays in identifying
|
|
// disconnections (for example, the websocket disconnection takes up to 3 seconds)
|
|
// while fetching the latest updated conversations or messages.
|
|
const DISCONNECT_DELAY_THRESHOLD = 15;
|
|
|
|
class ReconnectService {
|
|
constructor(store, router) {
|
|
this.store = store;
|
|
this.router = router;
|
|
this.disconnectTime = null;
|
|
|
|
this.setupEventListeners();
|
|
}
|
|
|
|
disconnect = () => this.removeEventListeners();
|
|
|
|
setupEventListeners = () => {
|
|
window.addEventListener('online', this.handleOnlineEvent);
|
|
emitter.on(BUS_EVENTS.WEBSOCKET_RECONNECT, this.onReconnect);
|
|
emitter.on(BUS_EVENTS.WEBSOCKET_DISCONNECT, this.onDisconnect);
|
|
};
|
|
|
|
removeEventListeners = () => {
|
|
window.removeEventListener('online', this.handleOnlineEvent);
|
|
emitter.off(BUS_EVENTS.WEBSOCKET_RECONNECT, this.onReconnect);
|
|
emitter.off(BUS_EVENTS.WEBSOCKET_DISCONNECT, this.onDisconnect);
|
|
};
|
|
|
|
getSecondsSinceDisconnect = () =>
|
|
this.disconnectTime
|
|
? Math.max(differenceInSeconds(new Date(), this.disconnectTime), 0)
|
|
: 0;
|
|
|
|
// Force reload if the user is disconnected for more than 3 hours
|
|
handleOnlineEvent = () => {
|
|
if (this.getSecondsSinceDisconnect() >= MAX_DISCONNECT_SECONDS) {
|
|
window.location.reload();
|
|
}
|
|
};
|
|
|
|
fetchConversations = async () => {
|
|
await this.store.dispatch('updateChatListFilters', {
|
|
page: null,
|
|
updatedWithin:
|
|
this.getSecondsSinceDisconnect() + DISCONNECT_DELAY_THRESHOLD,
|
|
});
|
|
await this.store.dispatch('fetchAllConversations');
|
|
// Reset the updatedWithin in the store chat list filter after fetching conversations when the user is reconnected
|
|
await this.store.dispatch('updateChatListFilters', {
|
|
updatedWithin: null,
|
|
});
|
|
};
|
|
|
|
fetchFilteredOrSavedConversations = async queryData => {
|
|
await this.store.dispatch('fetchFilteredConversations', {
|
|
queryData,
|
|
page: 1,
|
|
});
|
|
};
|
|
|
|
fetchConversationsOnReconnect = async () => {
|
|
const {
|
|
getAppliedConversationFiltersQuery,
|
|
'customViews/getActiveConversationFolder': activeFolder,
|
|
} = this.store.getters;
|
|
const query = getAppliedConversationFiltersQuery?.payload?.length
|
|
? getAppliedConversationFiltersQuery
|
|
: activeFolder?.query;
|
|
if (query) {
|
|
await this.fetchFilteredOrSavedConversations(query);
|
|
} else {
|
|
await this.fetchConversations();
|
|
}
|
|
};
|
|
|
|
fetchConversationMessagesOnReconnect = async () => {
|
|
const { conversation_id: conversationId } = this.router.currentRoute.params;
|
|
if (conversationId) {
|
|
await this.store.dispatch('syncActiveConversationMessages', {
|
|
conversationId: Number(conversationId),
|
|
});
|
|
}
|
|
};
|
|
|
|
fetchNotificationsOnReconnect = async filter => {
|
|
await this.store.dispatch('notifications/index', { ...filter, page: 1 });
|
|
};
|
|
|
|
revalidateCaches = async () => {
|
|
const { label, inbox, team } = await this.store.dispatch(
|
|
'accounts/getCacheKeys'
|
|
);
|
|
await Promise.all([
|
|
this.store.dispatch('labels/revalidate', { newKey: label }),
|
|
this.store.dispatch('inboxes/revalidate', { newKey: inbox }),
|
|
this.store.dispatch('teams/revalidate', { newKey: team }),
|
|
]);
|
|
};
|
|
|
|
handleRouteSpecificFetch = async () => {
|
|
const currentRoute = this.router.currentRoute.name;
|
|
if (isAConversationRoute(currentRoute, true)) {
|
|
await this.fetchConversationsOnReconnect();
|
|
await this.fetchConversationMessagesOnReconnect();
|
|
} else if (isAInboxViewRoute(currentRoute, true)) {
|
|
await this.fetchNotificationsOnReconnect(
|
|
this.store.getters['notifications/getNotificationFilters']
|
|
);
|
|
} else if (isNotificationRoute(currentRoute)) {
|
|
await this.fetchNotificationsOnReconnect();
|
|
}
|
|
};
|
|
|
|
setConversationLastMessageId = async () => {
|
|
const { conversation_id: conversationId } = this.router.currentRoute.params;
|
|
if (conversationId) {
|
|
await this.store.dispatch('setConversationLastMessageId', {
|
|
conversationId: Number(conversationId),
|
|
});
|
|
}
|
|
};
|
|
|
|
onDisconnect = () => {
|
|
this.disconnectTime = new Date();
|
|
this.setConversationLastMessageId();
|
|
};
|
|
|
|
onReconnect = async () => {
|
|
await this.handleRouteSpecificFetch();
|
|
await this.revalidateCaches();
|
|
emitter.emit(BUS_EVENTS.WEBSOCKET_RECONNECT_COMPLETED);
|
|
};
|
|
}
|
|
|
|
export default ReconnectService;
|