diff --git a/apps/meteor/client/contexts/VideoConfContext.ts b/apps/meteor/client/contexts/VideoConfContext.ts index 2a4b2bd736fd..49a9006a1a81 100644 --- a/apps/meteor/client/contexts/VideoConfContext.ts +++ b/apps/meteor/client/contexts/VideoConfContext.ts @@ -1,7 +1,6 @@ import type { IRoom } from '@rocket.chat/core-typings'; import { createContext, useContext } from 'react'; -import type { Subscription } from 'use-subscription'; -import { useSubscription } from 'use-subscription'; +import { useSyncExternalStore } from 'use-sync-external-store/shim'; import type { DirectCallData, ProviderCapabilities, CallPreferences, VideoConfManager } from '../lib/VideoConfManager'; @@ -22,11 +21,26 @@ type VideoConfContextValue = { rejectIncomingCall: (callId: string) => void; abortCall: () => void; setPreferences: (prefs: { mic?: boolean; cam?: boolean }) => void; - queryIncomingCalls: Subscription; - queryRinging: Subscription; - queryCalling: Subscription; - queryCapabilities: Subscription; - queryPreferences: Subscription; + queryIncomingCalls: { + subscribe: (cb: () => void) => () => void; + getSnapshot: () => DirectCallData[]; + }; + queryRinging: { + subscribe: (cb: () => void) => () => void; + getSnapshot: () => boolean; + }; + queryCalling: { + subscribe: (cb: () => void) => () => void; + getSnapshot: () => boolean; + }; + queryCapabilities: { + subscribe: (cb: () => void) => () => void; + getSnapshot: () => ProviderCapabilities; + }; + queryPreferences: { + subscribe: (cb: () => void) => () => void; + getSnapshot: () => CallPreferences; + }; }; export const VideoConfContext = createContext(undefined); @@ -49,24 +63,24 @@ export const useVideoConfAbortCall = (): VideoConfContextValue['abortCall'] => u export const useVideoConfRejectIncomingCall = (): VideoConfContextValue['rejectIncomingCall'] => useVideoConfContext().rejectIncomingCall; export const useVideoConfIncomingCalls = (): DirectCallData[] => { const { queryIncomingCalls } = useVideoConfContext(); - return useSubscription(queryIncomingCalls); + return useSyncExternalStore(queryIncomingCalls.subscribe, queryIncomingCalls.getSnapshot); }; export const useVideoConfSetPreferences = (): VideoConfContextValue['setPreferences'] => useVideoConfContext().setPreferences; export const useVideoConfIsRinging = (): boolean => { const { queryRinging } = useVideoConfContext(); - return useSubscription(queryRinging); + return useSyncExternalStore(queryRinging.subscribe, queryRinging.getSnapshot); }; export const useVideoConfIsCalling = (): boolean => { const { queryCalling } = useVideoConfContext(); - return useSubscription(queryCalling); + return useSyncExternalStore(queryCalling.subscribe, queryCalling.getSnapshot); }; export const useVideoConfCapabilities = (): ProviderCapabilities => { const { queryCapabilities } = useVideoConfContext(); - return useSubscription(queryCapabilities); + return useSyncExternalStore(queryCapabilities.subscribe, queryCapabilities.getSnapshot); }; export const useVideoConfPreferences = (): CallPreferences => { const { queryPreferences } = useVideoConfContext(); - return useSubscription(queryPreferences); + return useSyncExternalStore(queryPreferences.subscribe, queryPreferences.getSnapshot); }; export const useVideoConfManager = (): typeof VideoConfManager | undefined => useContext(VideoConfContext)?.manager; diff --git a/apps/meteor/client/lib/VideoConfManager.ts b/apps/meteor/client/lib/VideoConfManager.ts index 7ae1c04db6df..2ee480925d6d 100644 --- a/apps/meteor/client/lib/VideoConfManager.ts +++ b/apps/meteor/client/lib/VideoConfManager.ts @@ -104,6 +104,8 @@ export const VideoConfManager = new (class VideoConfManager extends Emitter; + private directCalls: DirectCallData[] = []; + private dismissedCalls: Set; private _preferences: CallPreferences; @@ -124,6 +126,13 @@ export const VideoConfManager = new (class VideoConfManager extends Emitter(); this._preferences = { mic: true, cam: false }; this._capabilities = {}; + + this.on('incoming/changed', () => { + this.directCalls = [...this.incomingDirectCalls.values()] + // Filter out any calls that we're in the process of accepting, so they're already hidden from the UI + .filter((call) => !call.acceptTimeout) + .map(({ timeout: _, acceptTimeout: _t, ...call }) => ({ ...call, dismissed: this.isCallDismissed(call.callId) })); + }); } public isBusy(): boolean { @@ -147,12 +156,7 @@ export const VideoConfManager = new (class VideoConfManager extends Emitter