mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-11-04 04:57:51 +00:00 
			
		
		
		
	Fixes https://github.com/chatwoot/chatwoot/issues/8436 Fixes https://github.com/chatwoot/chatwoot/issues/9767 Fixes https://github.com/chatwoot/chatwoot/issues/10156 Fixes https://github.com/chatwoot/chatwoot/issues/6031 Fixes https://github.com/chatwoot/chatwoot/issues/5696 Fixes https://github.com/chatwoot/chatwoot/issues/9250 Fixes https://github.com/chatwoot/chatwoot/issues/9762 --------- Co-authored-by: Pranav <pranavrajs@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
		
			
				
	
	
		
			149 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.7 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.value.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.value.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.value.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;
 |