import { ConnectionMonitor, Consumer, createConsumer } from '@rails/actioncable' import { BASE_WSS_URL } from '../api/fetch' import { fromBfCache } from '../lib/from-bfcache' let client: Consumer | undefined let project: string let profile: string // Tweak ActionCable's internal settings to make it more resilient to network issues (more aggressive backoff) // @ts-expect-error we are modifying an internal property ConnectionMonitor.staleThreshold = 10 // @ts-expect-error we are modifying an internal property ConnectionMonitor.reconnectionBackoffRate = 0.2 export const consumer = (profileId: string, projectSlug: string) => { if (project !== projectSlug || profile !== profileId) { client?.disconnect() client = undefined } if (!client) { const url = `${BASE_WSS_URL.replace('https', 'wss')}/cable?profile_id=${profileId}&project_slug=${projectSlug}` client = createConsumer(url) project = projectSlug profile = profileId } return client } window.addEventListener( 'pagehide', () => { if (client) { client.disconnect() // @ts-expect-error this isn't typed client.connection?.webSocket?.close() } }, { capture: true } ) window.addEventListener( 'pageshow', (e) => { // we can't use client.connect() because its internal state gets out of sync with the websocket // `client.connection.reopen()` will force reopening the connection as needed if (client && fromBfCache(e)) { client.connection.reopen() } }, { capture: true } )