Skip to content

Commit

Permalink
chore: replace use-subscription -> use-sync-external-store (Rocke…
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo authored Oct 24, 2024
1 parent bec7cf6 commit 72182ba
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 91 deletions.
38 changes: 26 additions & 12 deletions apps/meteor/client/contexts/VideoConfContext.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -22,11 +21,26 @@ type VideoConfContextValue = {
rejectIncomingCall: (callId: string) => void;
abortCall: () => void;
setPreferences: (prefs: { mic?: boolean; cam?: boolean }) => void;
queryIncomingCalls: Subscription<DirectCallData[]>;
queryRinging: Subscription<boolean>;
queryCalling: Subscription<boolean>;
queryCapabilities: Subscription<ProviderCapabilities>;
queryPreferences: Subscription<CallPreferences>;
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<VideoConfContextValue | undefined>(undefined);
Expand All @@ -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;
16 changes: 10 additions & 6 deletions apps/meteor/client/lib/VideoConfManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ export const VideoConfManager = new (class VideoConfManager extends Emitter<Vide

private incomingDirectCalls: Map<string, IncomingDirectCall>;

private directCalls: DirectCallData[] = [];

private dismissedCalls: Set<string>;

private _preferences: CallPreferences;
Expand All @@ -124,6 +126,13 @@ export const VideoConfManager = new (class VideoConfManager extends Emitter<Vide
this.dismissedCalls = new Set<string>();
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 {
Expand All @@ -147,12 +156,7 @@ export const VideoConfManager = new (class VideoConfManager extends Emitter<Vide
}

public getIncomingDirectCalls(): DirectCallData[] {
return (
[...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) }))
);
return this.directCalls;
}

public async startCall(roomId: IRoom['_id'], title?: string): Promise<void> {
Expand Down
21 changes: 10 additions & 11 deletions apps/meteor/client/providers/VideoConfProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { IRoom } from '@rocket.chat/core-typings';
import type { ReactElement, ReactNode } from 'react';
import React, { useState, useMemo, useEffect } from 'react';
import type { Unsubscribe } from 'use-subscription';

import type { VideoConfPopupPayload } from '../contexts/VideoConfContext';
import { VideoConfContext } from '../contexts/VideoConfContext';
Expand Down Expand Up @@ -42,24 +41,24 @@ const VideoConfContextProvider = ({ children }: { children: ReactNode }): ReactE
abortCall: (): void => VideoConfManager.abortCall(),
setPreferences: (prefs: Partial<(typeof VideoConfManager)['preferences']>): void => VideoConfManager.setPreferences(prefs),
queryIncomingCalls: {
getCurrentValue: (): DirectCallData[] => VideoConfManager.getIncomingDirectCalls(),
subscribe: (cb: () => void): Unsubscribe => VideoConfManager.on('incoming/changed', cb),
getSnapshot: (): DirectCallData[] => VideoConfManager.getIncomingDirectCalls(),
subscribe: (cb: () => void) => VideoConfManager.on('incoming/changed', cb),
},
queryRinging: {
getCurrentValue: (): boolean => VideoConfManager.isRinging(),
subscribe: (cb: () => void): Unsubscribe => VideoConfManager.on('ringing/changed', cb),
getSnapshot: (): boolean => VideoConfManager.isRinging(),
subscribe: (cb: () => void) => VideoConfManager.on('ringing/changed', cb),
},
queryCalling: {
getCurrentValue: (): boolean => VideoConfManager.isCalling(),
subscribe: (cb: () => void): Unsubscribe => VideoConfManager.on('calling/changed', cb),
getSnapshot: (): boolean => VideoConfManager.isCalling(),
subscribe: (cb: () => void) => VideoConfManager.on('calling/changed', cb),
},
queryCapabilities: {
getCurrentValue: (): ProviderCapabilities => VideoConfManager.capabilities,
subscribe: (cb: () => void): Unsubscribe => VideoConfManager.on('capabilities/changed', cb),
getSnapshot: (): ProviderCapabilities => VideoConfManager.capabilities,
subscribe: (cb: () => void) => VideoConfManager.on('capabilities/changed', cb),
},
queryPreferences: {
getCurrentValue: (): CallPreferences => VideoConfManager.preferences,
subscribe: (cb: () => void): Unsubscribe => VideoConfManager.on('preference/changed', cb),
getSnapshot: (): CallPreferences => VideoConfManager.preferences,
subscribe: (cb: () => void) => VideoConfManager.on('preference/changed', cb),
},
}),
[],
Expand Down
39 changes: 18 additions & 21 deletions apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useTranslation, useUserPreference, useLayout, useSetting } from '@rocke
import { useMutation } from '@tanstack/react-query';
import type { ReactElement, MouseEventHandler, FormEvent, ClipboardEventHandler, MouseEvent } from 'react';
import React, { memo, useRef, useReducer, useCallback } from 'react';
import { useSubscription } from 'use-subscription';
import { useSyncExternalStore } from 'use-sync-external-store/shim';

import { createComposerAPI } from '../../../../../app/ui-message/client/messageBox/createComposerAPI';
import type { FormattingButton } from '../../../../../app/ui-message/client/messageBox/messageBoxFormatting';
Expand Down Expand Up @@ -248,30 +248,27 @@ const MessageBox = ({
onTyping?.();
});

const isEditing = useSubscription({
getCurrentValue: chat.composer?.editing.get ?? getEmptyFalse,
subscribe: chat.composer?.editing.subscribe ?? emptySubscribe,
});
const isEditing = useSyncExternalStore(chat.composer?.editing.subscribe ?? emptySubscribe, chat.composer?.editing.get ?? getEmptyFalse);

const isRecordingAudio = useSubscription({
getCurrentValue: chat.composer?.recording.get ?? getEmptyFalse,
subscribe: chat.composer?.recording.subscribe ?? emptySubscribe,
});
const isRecordingAudio = useSyncExternalStore(
chat.composer?.recording.subscribe ?? emptySubscribe,
chat.composer?.recording.get ?? getEmptyFalse,
);

const isMicrophoneDenied = useSubscription({
getCurrentValue: chat.composer?.isMicrophoneDenied.get ?? getEmptyFalse,
subscribe: chat.composer?.isMicrophoneDenied.subscribe ?? emptySubscribe,
});
const isMicrophoneDenied = useSyncExternalStore(
chat.composer?.isMicrophoneDenied.subscribe ?? emptySubscribe,
chat.composer?.isMicrophoneDenied.get ?? getEmptyFalse,
);

const isRecordingVideo = useSubscription({
getCurrentValue: chat.composer?.recordingVideo.get ?? getEmptyFalse,
subscribe: chat.composer?.recordingVideo.subscribe ?? emptySubscribe,
});
const isRecordingVideo = useSyncExternalStore(
chat.composer?.recordingVideo.subscribe ?? emptySubscribe,
chat.composer?.recordingVideo.get ?? getEmptyFalse,
);

const formatters = useSubscription({
getCurrentValue: chat.composer?.formatters.get ?? getEmptyArray,
subscribe: chat.composer?.formatters.subscribe ?? emptySubscribe,
});
const formatters = useSyncExternalStore(
chat.composer?.formatters.subscribe ?? emptySubscribe,
chat.composer?.formatters.get ?? getEmptyArray,
);

const isRecording = isRecordingAudio || isRecordingVideo;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { IconButton, Box, Margins } from '@rocket.chat/fuselage';
import { useSetting } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React, { memo } from 'react';
import { useSubscription } from 'use-subscription';
import { useSyncExternalStore } from 'use-sync-external-store/shim';

import { getUserDisplayName } from '../../../../../lib/getUserDisplayName';
import { QuoteAttachment } from '../../../../components/message/content/attachments/QuoteAttachment';
Expand All @@ -18,10 +18,7 @@ const MessageBoxReplies = (): ReactElement | null => {
throw new Error('Chat context not found');
}

const replies = useSubscription({
getCurrentValue: chat.composer.quotedMessages.get,
subscribe: chat.composer.quotedMessages.subscribe,
});
const replies = useSyncExternalStore(chat.composer.quotedMessages.subscribe, chat.composer.quotedMessages.get);

const useRealName = Boolean(useSetting('UI_Use_Real_Name'));

Expand Down
2 changes: 0 additions & 2 deletions apps/meteor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@
"@types/supports-color": "~7.2.1",
"@types/textarea-caret": "^3.0.3",
"@types/ua-parser-js": "^0.7.39",
"@types/use-subscription": "^1.0.2",
"@types/use-sync-external-store": "^0.0.6",
"@types/uuid": "^8.3.4",
"@types/xml-crypto": "~1.4.6",
Expand Down Expand Up @@ -436,7 +435,6 @@
"underscore": "^1.13.7",
"universal-perf-hooks": "^1.0.1",
"url-polyfill": "^1.1.12",
"use-subscription": "~1.6.0",
"use-sync-external-store": "^1.2.2",
"uuid": "^8.3.2",
"webdav": "^4.11.4",
Expand Down
4 changes: 1 addition & 3 deletions apps/uikit-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,12 @@
"react-router-dom": "^6.11.2",
"react-split-pane": "^0.1.92",
"react-virtuoso": "^4.7.1",
"reactflow": "^11.7.2",
"use-subscription": "^1.8.2"
"reactflow": "^11.7.2"
},
"devDependencies": {
"@types/react": "~17.0.80",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-dom": "~17.0.25",
"@types/use-subscription": "^1.0.2",
"@typescript-eslint/eslint-plugin": "~5.60.1",
"@typescript-eslint/parser": "~5.60.1",
"@vitejs/plugin-react": "^4.0.0",
Expand Down
31 changes: 0 additions & 31 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9063,7 +9063,6 @@ __metadata:
"@types/supports-color": "npm:~7.2.1"
"@types/textarea-caret": "npm:^3.0.3"
"@types/ua-parser-js": "npm:^0.7.39"
"@types/use-subscription": "npm:^1.0.2"
"@types/use-sync-external-store": "npm:^0.0.6"
"@types/uuid": "npm:^8.3.4"
"@types/xml-crypto": "npm:~1.4.6"
Expand Down Expand Up @@ -9264,7 +9263,6 @@ __metadata:
underscore: "npm:^1.13.7"
universal-perf-hooks: "npm:^1.0.1"
url-polyfill: "npm:^1.1.12"
use-subscription: "npm:~1.6.0"
use-sync-external-store: "npm:^1.2.2"
uuid: "npm:^8.3.2"
webdav: "npm:^4.11.4"
Expand Down Expand Up @@ -10169,7 +10167,6 @@ __metadata:
"@types/react": "npm:~17.0.80"
"@types/react-beautiful-dnd": "npm:^13.1.8"
"@types/react-dom": "npm:~17.0.25"
"@types/use-subscription": "npm:^1.0.2"
"@typescript-eslint/eslint-plugin": "npm:~5.60.1"
"@typescript-eslint/parser": "npm:~5.60.1"
"@vitejs/plugin-react": "npm:^4.0.0"
Expand All @@ -10188,7 +10185,6 @@ __metadata:
react-virtuoso: "npm:^4.7.1"
reactflow: "npm:^11.7.2"
typescript: "npm:~5.6.3"
use-subscription: "npm:^1.8.2"
vite: "npm:^4.5.5"
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -13323,13 +13319,6 @@ __metadata:
languageName: node
linkType: hard

"@types/use-subscription@npm:^1.0.2":
version: 1.0.2
resolution: "@types/use-subscription@npm:1.0.2"
checksum: 10/e547d8ffdf8410c985c271a30903cd754687a6514a67192378213590f707a0f516e0c11930cba10bd7e98dc4f7917e066b3b8d37a622d02b6fcf3c5df530e467
languageName: node
linkType: hard

"@types/use-sync-external-store@npm:^0.0.6":
version: 0.0.6
resolution: "@types/use-sync-external-store@npm:0.0.6"
Expand Down Expand Up @@ -38012,26 +38001,6 @@ __metadata:
languageName: node
linkType: hard

"use-subscription@npm:^1.8.2":
version: 1.8.2
resolution: "use-subscription@npm:1.8.2"
dependencies:
use-sync-external-store: "npm:^1.2.2"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: 10/6b17f92a75405a4e6015d7762b459a43435f34d0bb9a72e512e305d6d3a61bd170e6666c3a62c2c3c7af1b7ba0b45c5a597b7eeea54c46e1cabf8ef0f971d44e
languageName: node
linkType: hard

"use-subscription@npm:~1.6.0":
version: 1.6.0
resolution: "use-subscription@npm:1.6.0"
peerDependencies:
react: ^18.0.0
checksum: 10/afce4295e439069d6139079c7c3a12ac3e6c4e81cd9b1622e62934e007d8cf2885f6aae5bd8de4f031d3eb5bd3cea2fd83d9be8c3da9542d4ba0a9de170be274
languageName: node
linkType: hard

"use-sync-external-store@npm:1.2.0":
version: 1.2.0
resolution: "use-sync-external-store@npm:1.2.0"
Expand Down

0 comments on commit 72182ba

Please sign in to comment.