@100mslive/react-sdk 0.11.3-alpha.2 → 0.11.3-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/types.d.ts +1 -1
- package/dist/hooks/useDevices.d.ts +1 -1
- package/dist/hooks/usePaginatedParticipants.d.ts +1 -1
- package/dist/hooks/useParticipants.d.ts +1 -1
- package/dist/index.cjs.js +2 -1
- package/dist/index.cjs.js.map +7 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +7 -1
- package/dist/primitives/HmsRoomProvider.d.ts +2 -2
- package/dist/primitives/store.d.ts +3 -1
- package/dist/utils/layout.d.ts +2 -2
- package/package.json +8 -15
- package/dist/hooks/useAVToggle.js +0 -2
- package/dist/hooks/useAVToggle.js.map +0 -1
- package/dist/hooks/useAudioLevelStyles.js +0 -2
- package/dist/hooks/useAudioLevelStyles.js.map +0 -1
- package/dist/hooks/useAudioMode.js +0 -2
- package/dist/hooks/useAudioMode.js.map +0 -1
- package/dist/hooks/useAutoplayError.js +0 -2
- package/dist/hooks/useAutoplayError.js.map +0 -1
- package/dist/hooks/useAwayNotifications.js +0 -2
- package/dist/hooks/useAwayNotifications.js.map +0 -1
- package/dist/hooks/useCustomEvent.js +0 -2
- package/dist/hooks/useCustomEvent.js.map +0 -1
- package/dist/hooks/useDevices.js +0 -2
- package/dist/hooks/useDevices.js.map +0 -1
- package/dist/hooks/useEmbedShare.js +0 -2
- package/dist/hooks/useEmbedShare.js.map +0 -1
- package/dist/hooks/usePDFShare.js +0 -2
- package/dist/hooks/usePDFShare.js.map +0 -1
- package/dist/hooks/usePaginatedParticipants.js +0 -2
- package/dist/hooks/usePaginatedParticipants.js.map +0 -1
- package/dist/hooks/useParticipantList.js +0 -2
- package/dist/hooks/useParticipantList.js.map +0 -1
- package/dist/hooks/useParticipants.js +0 -2
- package/dist/hooks/useParticipants.js.map +0 -1
- package/dist/hooks/usePreviewJoin.js +0 -2
- package/dist/hooks/usePreviewJoin.js.map +0 -1
- package/dist/hooks/useRecordingStreaming.js +0 -2
- package/dist/hooks/useRecordingStreaming.js.map +0 -1
- package/dist/hooks/useRemoteAVToggle.js +0 -2
- package/dist/hooks/useRemoteAVToggle.js.map +0 -1
- package/dist/hooks/useScreenShare.js +0 -2
- package/dist/hooks/useScreenShare.js.map +0 -1
- package/dist/hooks/useTranscript.js +0 -2
- package/dist/hooks/useTranscript.js.map +0 -1
- package/dist/hooks/useVideo.js +0 -2
- package/dist/hooks/useVideo.js.map +0 -1
- package/dist/hooks/useVideoList.js +0 -2
- package/dist/hooks/useVideoList.js.map +0 -1
- package/dist/hooks/useWhiteboard.js +0 -2
- package/dist/hooks/useWhiteboard.js.map +0 -1
- package/dist/node_modules/tslib/tslib.es6.mjs.js +0 -2
- package/dist/node_modules/tslib/tslib.es6.mjs.js.map +0 -1
- package/dist/packages/react-sdk/node_modules/zustand/esm/shallow.js +0 -2
- package/dist/packages/react-sdk/node_modules/zustand/esm/shallow.js.map +0 -1
- package/dist/primitives/HmsRoomProvider.js +0 -2
- package/dist/primitives/HmsRoomProvider.js.map +0 -1
- package/dist/primitives/store.js +0 -2
- package/dist/primitives/store.js.map +0 -1
- package/dist/utils/commons.js +0 -2
- package/dist/utils/commons.js.map +0 -1
- package/dist/utils/groupBy.js +0 -2
- package/dist/utils/groupBy.js.map +0 -1
- package/dist/utils/isBrowser.js +0 -2
- package/dist/utils/isBrowser.js.map +0 -1
- package/dist/utils/layout.js +0 -2
- package/dist/utils/layout.js.map +0 -1
- package/dist/utils/logger.js +0 -2
- package/dist/utils/logger.js.map +0 -1
- package/src/hooks/types.ts +0 -6
- package/src/hooks/useAVToggle.ts +0 -66
- package/src/hooks/useAudioLevelStyles.ts +0 -37
- package/src/hooks/useAudioMode.tsx +0 -11
- package/src/hooks/useAutoplayError.ts +0 -41
- package/src/hooks/useAwayNotifications.ts +0 -55
- package/src/hooks/useCustomEvent.ts +0 -121
- package/src/hooks/useDevices.ts +0 -96
- package/src/hooks/useEmbedShare.ts +0 -97
- package/src/hooks/usePDFShare.ts +0 -117
- package/src/hooks/usePaginatedParticipants.ts +0 -56
- package/src/hooks/useParticipantList.ts +0 -27
- package/src/hooks/useParticipants.ts +0 -72
- package/src/hooks/usePreviewJoin.ts +0 -166
- package/src/hooks/useRecordingStreaming.ts +0 -34
- package/src/hooks/useRemoteAVToggle.ts +0 -102
- package/src/hooks/useScreenShare.ts +0 -77
- package/src/hooks/useTranscript.ts +0 -50
- package/src/hooks/useVideo.ts +0 -87
- package/src/hooks/useVideoList.ts +0 -162
- package/src/hooks/useWhiteboard.ts +0 -50
- package/src/index.ts +0 -56
- package/src/primitives/HmsRoomProvider.ts +0 -221
- package/src/primitives/store.ts +0 -59
- package/src/primitives/types.ts +0 -6
- package/src/utils/commons.ts +0 -34
- package/src/utils/groupBy.ts +0 -29
- package/src/utils/isBrowser.ts +0 -1
- package/src/utils/layout.ts +0 -473
- package/src/utils/logger.ts +0 -62
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect } from 'react';
|
|
2
|
-
import { HMSNotificationTypes, HMSPeerID, HMSRoleName } from '@100mslive/hms-video-store';
|
|
3
|
-
import { hooksErrHandler } from './types';
|
|
4
|
-
import { useHMSActions, useHMSVanillaNotifications } from '../primitives/HmsRoomProvider';
|
|
5
|
-
import { logErrorHandler } from '../utils/commons';
|
|
6
|
-
|
|
7
|
-
export interface useCustomEventInput<T> {
|
|
8
|
-
/**
|
|
9
|
-
* type of the event, for example, MODERATOR_EVENT, EMOJI_REACTIONS etc.
|
|
10
|
-
*/
|
|
11
|
-
type: string;
|
|
12
|
-
/**
|
|
13
|
-
* the handler function for when the custom event comes. It's recommended
|
|
14
|
-
* to use `useCallback` for the function passed in here for performance
|
|
15
|
-
* reasons.
|
|
16
|
-
* The callback is optional in case you want to decouple sending event and
|
|
17
|
-
* handling event in the UI.
|
|
18
|
-
*/
|
|
19
|
-
onEvent?: (data: T) => void;
|
|
20
|
-
/**
|
|
21
|
-
* flag to treat event payload as json.
|
|
22
|
-
* If true, the payload will be stringified before sending and
|
|
23
|
-
* parsed before calling the onEvent handler function.
|
|
24
|
-
*
|
|
25
|
-
* Set it to `false` if you want to send/receive only string messages
|
|
26
|
-
*
|
|
27
|
-
* Set it to `true` if you want to send/receive objects
|
|
28
|
-
*
|
|
29
|
-
* default value is true
|
|
30
|
-
*/
|
|
31
|
-
json?: boolean;
|
|
32
|
-
/**
|
|
33
|
-
* function to handle errors happening during sending the event
|
|
34
|
-
*/
|
|
35
|
-
handleError?: hooksErrHandler;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface EventReceiver {
|
|
39
|
-
peerId?: HMSPeerID;
|
|
40
|
-
roleNames?: HMSRoleName[];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface useCustomEventResult<T> {
|
|
44
|
-
/**
|
|
45
|
-
* sends the event data to others in the room who will receive it in onEvent
|
|
46
|
-
*
|
|
47
|
-
* @example to send message to peers of specific roles
|
|
48
|
-
* ```js
|
|
49
|
-
* sendEvent(data, {roleNames: ['host','guest']})
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
* @example to send message to single peer
|
|
53
|
-
* ```js
|
|
54
|
-
* sendEvent(data, {peerId})
|
|
55
|
-
* ```
|
|
56
|
-
*/
|
|
57
|
-
sendEvent: (data: T, receiver?: EventReceiver) => void;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const stringifyData = <T>(data: T, json: boolean) => (json ? JSON.stringify(data || '') : (data as unknown as string));
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* A generic function to implement [custom events](https://www.100ms.live/docs/javascript/v2/features/chat#custom-events) in your UI.
|
|
64
|
-
* The data to be sent to remote is expected to be a serializable JSON. The serialization
|
|
65
|
-
* and deserialization is taken care of by the hook.
|
|
66
|
-
*/
|
|
67
|
-
export const useCustomEvent = <T>({
|
|
68
|
-
type,
|
|
69
|
-
json = true,
|
|
70
|
-
onEvent,
|
|
71
|
-
handleError = logErrorHandler,
|
|
72
|
-
}: useCustomEventInput<T>): useCustomEventResult<T> => {
|
|
73
|
-
const actions = useHMSActions();
|
|
74
|
-
const notifications = useHMSVanillaNotifications();
|
|
75
|
-
|
|
76
|
-
useEffect(() => {
|
|
77
|
-
// we don't want these messages to be stored in store reserving that for chat messages
|
|
78
|
-
actions.ignoreMessageTypes([type]);
|
|
79
|
-
}, [actions, type]);
|
|
80
|
-
|
|
81
|
-
// this is to handle messages from remote peers
|
|
82
|
-
useEffect(() => {
|
|
83
|
-
if (!notifications) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
const unsubscribe = notifications.onNotification(notification => {
|
|
87
|
-
const msg = notification.data;
|
|
88
|
-
if (msg && msg.type === type) {
|
|
89
|
-
try {
|
|
90
|
-
const data = json ? JSON.parse(msg.message) : msg.message;
|
|
91
|
-
onEvent?.(data as T);
|
|
92
|
-
} catch (err) {
|
|
93
|
-
handleError(err as Error, 'handleCustomEvent');
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}, HMSNotificationTypes.NEW_MESSAGE);
|
|
97
|
-
return unsubscribe;
|
|
98
|
-
}, [notifications, type, json, onEvent, handleError]);
|
|
99
|
-
|
|
100
|
-
// this is to send message to remote peers, peers of specific role or single peer, and call onEvent
|
|
101
|
-
const sendEvent = useCallback(
|
|
102
|
-
async (data: T, receiver?: EventReceiver) => {
|
|
103
|
-
try {
|
|
104
|
-
const dataStr = stringifyData<T>(data, json);
|
|
105
|
-
if (receiver && Array.isArray(receiver?.roleNames)) {
|
|
106
|
-
await actions.sendGroupMessage(dataStr, receiver.roleNames, type);
|
|
107
|
-
} else if (typeof receiver?.peerId === 'string') {
|
|
108
|
-
await actions.sendDirectMessage(dataStr, receiver.peerId, type);
|
|
109
|
-
} else {
|
|
110
|
-
await actions.sendBroadcastMessage(dataStr, type);
|
|
111
|
-
}
|
|
112
|
-
onEvent?.(data);
|
|
113
|
-
} catch (err) {
|
|
114
|
-
handleError(err as Error, 'sendCustomEvent');
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
[actions, handleError, onEvent, type, json],
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
return { sendEvent };
|
|
121
|
-
};
|
package/src/hooks/useDevices.ts
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
DeviceType,
|
|
4
|
-
selectDevices,
|
|
5
|
-
selectIsAllowedToPreviewMedia,
|
|
6
|
-
selectIsAllowedToPublish,
|
|
7
|
-
selectIsInPreview,
|
|
8
|
-
selectLocalMediaSettings,
|
|
9
|
-
} from '@100mslive/hms-video-store';
|
|
10
|
-
import { hooksErrHandler } from '../hooks/types';
|
|
11
|
-
import { useHMSActions, useHMSStore } from '../primitives/HmsRoomProvider';
|
|
12
|
-
import { logErrorHandler } from '../utils/commons';
|
|
13
|
-
|
|
14
|
-
export type DeviceTypeAndInfo<T> = {
|
|
15
|
-
[key in DeviceType]?: T;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export interface useDevicesResult {
|
|
19
|
-
/**
|
|
20
|
-
* list of all devices by type
|
|
21
|
-
*/
|
|
22
|
-
allDevices: DeviceTypeAndInfo<MediaDeviceInfo[]>;
|
|
23
|
-
/**
|
|
24
|
-
* selected device ids for all types
|
|
25
|
-
*/
|
|
26
|
-
selectedDeviceIDs: DeviceTypeAndInfo<string>;
|
|
27
|
-
/**
|
|
28
|
-
* function to call to update device
|
|
29
|
-
*/
|
|
30
|
-
updateDevice: ({ deviceType, deviceId }: { deviceType: DeviceType; deviceId: string }) => Promise<void>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* This hook can be used to implement a UI component which allows the user to manually change their
|
|
35
|
-
* audio/video device. It returns the list of all devices as well as the currently selected one. The input
|
|
36
|
-
* devices will be returned based on what the user is allowed to publish, so a audio only user won't get
|
|
37
|
-
* the audioInput field. This can be used to show the UI dropdowns properly.
|
|
38
|
-
*
|
|
39
|
-
* Note:
|
|
40
|
-
* - Browsers give access to the list of devices only if the user has given permission to access them
|
|
41
|
-
* - Changing devices manually work best in combination with remembering the user's selection for the next time, do
|
|
42
|
-
* pass the rememberDeviceSelection flag at time of join for this to happen.
|
|
43
|
-
*
|
|
44
|
-
* @param handleError error handler for any errors during device change
|
|
45
|
-
*/
|
|
46
|
-
export const useDevices = (handleError: hooksErrHandler = logErrorHandler): useDevicesResult => {
|
|
47
|
-
const actions = useHMSActions();
|
|
48
|
-
const sdkAllDevices: DeviceTypeAndInfo<MediaDeviceInfo[]> = useHMSStore(selectDevices);
|
|
49
|
-
const sdkSelectedDevices = useHMSStore(selectLocalMediaSettings);
|
|
50
|
-
const isInPreview = useHMSStore(selectIsInPreview);
|
|
51
|
-
const selectAllowed = isInPreview ? selectIsAllowedToPreviewMedia : selectIsAllowedToPublish;
|
|
52
|
-
const isAllowedToPublish = useHMSStore(selectAllowed);
|
|
53
|
-
|
|
54
|
-
const selectedDeviceIDs: DeviceTypeAndInfo<string> = {
|
|
55
|
-
[DeviceType.audioOutput]: sdkSelectedDevices.audioOutputDeviceId,
|
|
56
|
-
};
|
|
57
|
-
const allDevices: DeviceTypeAndInfo<MediaDeviceInfo[]> = {
|
|
58
|
-
[DeviceType.audioOutput]: sdkAllDevices.audioOutput,
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
if (isAllowedToPublish.video) {
|
|
62
|
-
allDevices[DeviceType.videoInput] = sdkAllDevices.videoInput;
|
|
63
|
-
selectedDeviceIDs[DeviceType.videoInput] = sdkSelectedDevices.videoInputDeviceId;
|
|
64
|
-
}
|
|
65
|
-
if (isAllowedToPublish.audio) {
|
|
66
|
-
allDevices[DeviceType.audioInput] = sdkAllDevices.audioInput;
|
|
67
|
-
selectedDeviceIDs[DeviceType.audioInput] = sdkSelectedDevices.audioInputDeviceId;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const updateDevice = useCallback(
|
|
71
|
-
async ({ deviceType, deviceId }: { deviceType: DeviceType; deviceId: string }) => {
|
|
72
|
-
try {
|
|
73
|
-
switch (deviceType) {
|
|
74
|
-
case DeviceType.audioInput:
|
|
75
|
-
await actions.setAudioSettings({ deviceId });
|
|
76
|
-
break;
|
|
77
|
-
case DeviceType.videoInput:
|
|
78
|
-
await actions.setVideoSettings({ deviceId });
|
|
79
|
-
break;
|
|
80
|
-
case DeviceType.audioOutput:
|
|
81
|
-
await actions.setAudioOutputDevice(deviceId);
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
} catch (err) {
|
|
85
|
-
handleError(err as Error, 'updateDevices');
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
[handleError, actions],
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
allDevices,
|
|
93
|
-
selectedDeviceIDs,
|
|
94
|
-
updateDevice,
|
|
95
|
-
};
|
|
96
|
-
};
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { useScreenShare } from './useScreenShare';
|
|
3
|
-
import usePrevious, { isChromiumBased } from '../utils/commons';
|
|
4
|
-
|
|
5
|
-
export interface useEmbedShareResult {
|
|
6
|
-
/**
|
|
7
|
-
* Embed and start sharing a URL.
|
|
8
|
-
*
|
|
9
|
-
* It will throw an error in the following scenarios:
|
|
10
|
-
* - When the URL has not been passed
|
|
11
|
-
* - When the reference has not been attached to an iframe
|
|
12
|
-
* - When screen share cannot be started
|
|
13
|
-
*/
|
|
14
|
-
startEmbedShare: (value: string) => Promise<void>;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Stop sharing the embed.
|
|
18
|
-
*/
|
|
19
|
-
stopEmbedShare: () => Promise<void>;
|
|
20
|
-
/**
|
|
21
|
-
* Flag to check if an embed is currently being shared.
|
|
22
|
-
*/
|
|
23
|
-
isEmbedShareInProgress: boolean;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Reference to attach to the iframe that is responsible for rendering the URL passed.
|
|
27
|
-
*/
|
|
28
|
-
iframeRef: React.RefObject<HTMLIFrameElement | null>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param resetConfig Callback that implements cleanup after Embed sharing stops. It is an optional parameter.
|
|
33
|
-
* @returns useEmbedShareResult
|
|
34
|
-
*/
|
|
35
|
-
export const useEmbedShare = (resetConfig?: () => void): useEmbedShareResult => {
|
|
36
|
-
const iframeRef = useRef<HTMLIFrameElement | null>(null);
|
|
37
|
-
const [sharing, setSharing] = useState(false);
|
|
38
|
-
|
|
39
|
-
const handleScreenShareError = useCallback(() => {
|
|
40
|
-
throw new Error('unable to start screen share');
|
|
41
|
-
}, []);
|
|
42
|
-
const inProgress = useRef(false);
|
|
43
|
-
const { amIScreenSharing, toggleScreenShare } = useScreenShare(handleScreenShareError);
|
|
44
|
-
// store previous state of screensharing, it will help to reset the config after screensharing stop.
|
|
45
|
-
const previouslySharing = usePrevious(amIScreenSharing);
|
|
46
|
-
|
|
47
|
-
const stopShare = useCallback(async () => {
|
|
48
|
-
if (amIScreenSharing) {
|
|
49
|
-
await toggleScreenShare?.(); // Stop screen sharing
|
|
50
|
-
iframeRef.current = null;
|
|
51
|
-
}
|
|
52
|
-
}, [amIScreenSharing, toggleScreenShare]);
|
|
53
|
-
|
|
54
|
-
const startShare = useCallback(
|
|
55
|
-
async (value: string) => {
|
|
56
|
-
if (inProgress.current) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
if (!value) {
|
|
60
|
-
throw new Error('URL not found');
|
|
61
|
-
}
|
|
62
|
-
if (amIScreenSharing) {
|
|
63
|
-
throw new Error('You are already sharing');
|
|
64
|
-
}
|
|
65
|
-
if (!iframeRef.current) {
|
|
66
|
-
throw new Error('Attach a reference `iframeRef` to iframe for sharing');
|
|
67
|
-
}
|
|
68
|
-
iframeRef.current.src = value;
|
|
69
|
-
inProgress.current = true;
|
|
70
|
-
setSharing(true);
|
|
71
|
-
await toggleScreenShare?.({
|
|
72
|
-
forceCurrentTab: isChromiumBased,
|
|
73
|
-
cropElement: iframeRef.current,
|
|
74
|
-
preferCurrentTab: isChromiumBased,
|
|
75
|
-
});
|
|
76
|
-
},
|
|
77
|
-
[amIScreenSharing, toggleScreenShare],
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
useEffect(() => {
|
|
81
|
-
if (previouslySharing && !amIScreenSharing) {
|
|
82
|
-
resetConfig?.();
|
|
83
|
-
if (iframeRef.current) {
|
|
84
|
-
iframeRef.current.src = '';
|
|
85
|
-
}
|
|
86
|
-
inProgress.current = false;
|
|
87
|
-
setSharing(false);
|
|
88
|
-
}
|
|
89
|
-
}, [amIScreenSharing, previouslySharing, resetConfig]);
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
startEmbedShare: startShare,
|
|
93
|
-
stopEmbedShare: stopShare,
|
|
94
|
-
iframeRef,
|
|
95
|
-
isEmbedShareInProgress: sharing,
|
|
96
|
-
};
|
|
97
|
-
};
|
package/src/hooks/usePDFShare.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { useScreenShare } from './useScreenShare';
|
|
3
|
-
import usePrevious, { isChromiumBased, pdfIframeURL } from '../utils/commons';
|
|
4
|
-
|
|
5
|
-
export interface usePDFShareResult {
|
|
6
|
-
/**
|
|
7
|
-
* Start sharing a PDF file or URL.
|
|
8
|
-
* It will throw an error in the following scenarios:
|
|
9
|
-
* - When file or URL has not been passed, or is invalid
|
|
10
|
-
* - When the reference has not been attached to an iframe
|
|
11
|
-
* - When screen share cannot be started
|
|
12
|
-
*/
|
|
13
|
-
startPDFShare: (value: File | string) => Promise<void>;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Stop sharing the PDF file or URL.
|
|
17
|
-
*/
|
|
18
|
-
stopPDFShare: () => Promise<void>;
|
|
19
|
-
/**
|
|
20
|
-
* Flag to check if PDF sharing is currently in progress.
|
|
21
|
-
*/
|
|
22
|
-
isPDFShareInProgress: boolean;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Reference to attach to the iframe that is responsible for rendering the PDF.
|
|
26
|
-
*/
|
|
27
|
-
iframeRef: React.RefObject<HTMLIFrameElement | null>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @param resetConfig Callback that implements cleanup after PDF sharing stops. Typically used to reset the currently selected PDF file or URL in your state. It is an optional parameter.
|
|
32
|
-
* @returns usePDFShareResult
|
|
33
|
-
*/
|
|
34
|
-
export const usePDFShare = (resetConfig?: () => void): usePDFShareResult => {
|
|
35
|
-
const iframeRef = useRef<HTMLIFrameElement | null>(null);
|
|
36
|
-
const [sharing, setSharing] = useState(false);
|
|
37
|
-
|
|
38
|
-
const handleScreenShareError = useCallback(() => {
|
|
39
|
-
throw new Error('unable to start screen share');
|
|
40
|
-
}, []);
|
|
41
|
-
const inProgress = useRef(false);
|
|
42
|
-
const { amIScreenSharing, toggleScreenShare } = useScreenShare(handleScreenShareError);
|
|
43
|
-
// store previous state of screensharing, it will help to reset the config after screensharing stop.
|
|
44
|
-
const previouslySharing = usePrevious(amIScreenSharing);
|
|
45
|
-
|
|
46
|
-
const sendDataToPDFIframe = useCallback((file?: File) => {
|
|
47
|
-
if (iframeRef.current) {
|
|
48
|
-
iframeRef.current.contentWindow?.postMessage(
|
|
49
|
-
{
|
|
50
|
-
theme: 2, // dark theme -> 2, light theme -> 1
|
|
51
|
-
file,
|
|
52
|
-
},
|
|
53
|
-
'*',
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
}, []);
|
|
57
|
-
|
|
58
|
-
const stopShare = useCallback(async () => {
|
|
59
|
-
if (amIScreenSharing) {
|
|
60
|
-
await toggleScreenShare?.(); // Stop screen sharing
|
|
61
|
-
}
|
|
62
|
-
}, [amIScreenSharing, toggleScreenShare]);
|
|
63
|
-
|
|
64
|
-
const startShare = useCallback(
|
|
65
|
-
// eslint-disable-next-line complexity
|
|
66
|
-
async (value: File | string) => {
|
|
67
|
-
if (inProgress.current) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (!value) {
|
|
71
|
-
throw new Error('File or url not found');
|
|
72
|
-
}
|
|
73
|
-
if (amIScreenSharing) {
|
|
74
|
-
throw new Error('You are already sharing');
|
|
75
|
-
}
|
|
76
|
-
if (!iframeRef.current) {
|
|
77
|
-
throw new Error('Attach a reference `iframeRef` to iframe for sharing');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
iframeRef.current.src = `${pdfIframeURL}${typeof value === 'string' ? `?file=${value}` : ''}`;
|
|
81
|
-
iframeRef.current.onload = () => {
|
|
82
|
-
requestAnimationFrame(() => {
|
|
83
|
-
if (value instanceof File) {
|
|
84
|
-
sendDataToPDFIframe(value);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
};
|
|
88
|
-
inProgress.current = true;
|
|
89
|
-
setSharing(true);
|
|
90
|
-
const isInsideIframe = window.self !== window.top;
|
|
91
|
-
await toggleScreenShare?.({
|
|
92
|
-
forceCurrentTab: isChromiumBased && !isInsideIframe,
|
|
93
|
-
cropElement: iframeRef.current,
|
|
94
|
-
preferCurrentTab: isChromiumBased && !isInsideIframe,
|
|
95
|
-
});
|
|
96
|
-
},
|
|
97
|
-
[amIScreenSharing, sendDataToPDFIframe, toggleScreenShare],
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
useEffect(() => {
|
|
101
|
-
if (previouslySharing && !amIScreenSharing) {
|
|
102
|
-
resetConfig?.();
|
|
103
|
-
if (iframeRef.current) {
|
|
104
|
-
iframeRef.current.removeAttribute('src');
|
|
105
|
-
}
|
|
106
|
-
inProgress.current = false;
|
|
107
|
-
setSharing(false);
|
|
108
|
-
}
|
|
109
|
-
}, [amIScreenSharing, previouslySharing, resetConfig]);
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
startPDFShare: startShare,
|
|
113
|
-
stopPDFShare: stopShare,
|
|
114
|
-
iframeRef,
|
|
115
|
-
isPDFShareInProgress: sharing,
|
|
116
|
-
};
|
|
117
|
-
};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { useRef, useState } from 'react';
|
|
2
|
-
import { HMSPeer, HMSPeerListIteratorOptions } from '@100mslive/hms-video-store';
|
|
3
|
-
import { useHMSActions } from '../primitives/HmsRoomProvider';
|
|
4
|
-
|
|
5
|
-
export interface usePaginatedParticipantsResult {
|
|
6
|
-
/**
|
|
7
|
-
* call this function to load initial peers and also when you want to poll the peers information
|
|
8
|
-
*/
|
|
9
|
-
loadPeers: Promise<void>;
|
|
10
|
-
/**
|
|
11
|
-
* this function is to be called when loadPeers is called at least once. This will fetch the next batch of peers
|
|
12
|
-
*/
|
|
13
|
-
loadMorePeers: Promise<void>;
|
|
14
|
-
hasNext: () => boolean;
|
|
15
|
-
// list of peers loaded
|
|
16
|
-
peers: HMSPeer[];
|
|
17
|
-
// total number of peers matching the input options at the time of the request
|
|
18
|
-
total: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type usePaginatedParticipantsInput = HMSPeerListIteratorOptions;
|
|
22
|
-
|
|
23
|
-
const processPeers = (peers: HMSPeer[]) => {
|
|
24
|
-
return peers.reduce<Record<string, HMSPeer>>((acc, peer) => {
|
|
25
|
-
acc[peer.id] = peer;
|
|
26
|
-
return acc;
|
|
27
|
-
}, {});
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const usePaginatedParticipants = (options: HMSPeerListIteratorOptions) => {
|
|
31
|
-
const actions = useHMSActions();
|
|
32
|
-
const iterator = useRef(actions.getPeerListIterator(options));
|
|
33
|
-
const [peers, setPeers] = useState<Record<string, HMSPeer>>({});
|
|
34
|
-
const [total, setTotal] = useState(0);
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
loadPeers: () =>
|
|
38
|
-
iterator.current.findPeers().then(peers => {
|
|
39
|
-
setPeers(processPeers(peers));
|
|
40
|
-
setTotal(iterator.current.getTotal());
|
|
41
|
-
}),
|
|
42
|
-
loadMorePeers: () =>
|
|
43
|
-
iterator.current.next().then(peers => {
|
|
44
|
-
setPeers(prevPeers => {
|
|
45
|
-
return {
|
|
46
|
-
...prevPeers,
|
|
47
|
-
...processPeers(peers),
|
|
48
|
-
};
|
|
49
|
-
});
|
|
50
|
-
setTotal(iterator.current.getTotal());
|
|
51
|
-
}),
|
|
52
|
-
hasNext: () => iterator.current.hasNext(),
|
|
53
|
-
total,
|
|
54
|
-
peers: Object.values(peers),
|
|
55
|
-
};
|
|
56
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
HMSPeer,
|
|
4
|
-
HMSRoleName,
|
|
5
|
-
selectIsConnectedToRoom,
|
|
6
|
-
selectPeerCount,
|
|
7
|
-
selectPeers,
|
|
8
|
-
selectRemotePeers,
|
|
9
|
-
} from '@100mslive/hms-video-store';
|
|
10
|
-
import { useHMSStore } from '../primitives/HmsRoomProvider';
|
|
11
|
-
import { groupByRoles } from '../utils/groupBy';
|
|
12
|
-
|
|
13
|
-
export interface useParticipantListResult {
|
|
14
|
-
roles: HMSRoleName[];
|
|
15
|
-
participantsByRoles: Record<string, HMSPeer[]>;
|
|
16
|
-
peerCount: number;
|
|
17
|
-
isConnected: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const useParticipantList = () => {
|
|
21
|
-
const isConnected = useHMSStore(selectIsConnectedToRoom);
|
|
22
|
-
const participantList = useHMSStore(isConnected ? selectPeers : selectRemotePeers);
|
|
23
|
-
const peerCount = useHMSStore(selectPeerCount);
|
|
24
|
-
const participantsByRoles = useMemo(() => groupByRoles(participantList), [participantList]);
|
|
25
|
-
const roles = Object.keys(participantsByRoles);
|
|
26
|
-
return { roles, participantsByRoles, peerCount, isConnected };
|
|
27
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
HMSPeer,
|
|
3
|
-
HMSRoleName,
|
|
4
|
-
selectAvailableRoleNames,
|
|
5
|
-
selectIsConnectedToRoom,
|
|
6
|
-
selectPeerCount,
|
|
7
|
-
selectPeerMetadata,
|
|
8
|
-
selectPeers,
|
|
9
|
-
selectRemotePeers,
|
|
10
|
-
} from '@100mslive/hms-video-store';
|
|
11
|
-
import { useHMSStore, useHMSVanillaStore } from '../primitives/HmsRoomProvider';
|
|
12
|
-
|
|
13
|
-
export interface useParticipantsResult {
|
|
14
|
-
/**
|
|
15
|
-
* list of participants that match the given filters
|
|
16
|
-
*/
|
|
17
|
-
participants: HMSPeer[];
|
|
18
|
-
/**
|
|
19
|
-
* Total number of participants in the room
|
|
20
|
-
*/
|
|
21
|
-
peerCount: number;
|
|
22
|
-
/**
|
|
23
|
-
* is joined in the room
|
|
24
|
-
*/
|
|
25
|
-
isConnected: boolean;
|
|
26
|
-
/**
|
|
27
|
-
* role names with at least one participant present with that role
|
|
28
|
-
*/
|
|
29
|
-
rolesWithParticipants: HMSRoleName[];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export type useParticipantsParams = {
|
|
33
|
-
/** To filter by particular role */
|
|
34
|
-
role: HMSRoleName;
|
|
35
|
-
/**
|
|
36
|
-
* To filter by particular by metadata. only supports `{ isHandRaised: true }` for now
|
|
37
|
-
* @beta
|
|
38
|
-
*/
|
|
39
|
-
metadata: Record<string, any>;
|
|
40
|
-
/** To filter by name/role (partial match) */
|
|
41
|
-
search: string;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* This can be used to get the total count of participants in the room, participants
|
|
46
|
-
* filtered by role or metadata with isHandRaised or the entire participants if no params are passed
|
|
47
|
-
* @param {useParticipantsParams} params
|
|
48
|
-
* @returns {useParticipantsResult}
|
|
49
|
-
*/
|
|
50
|
-
export const useParticipants = (params?: useParticipantsParams) => {
|
|
51
|
-
const isConnected = useHMSStore(selectIsConnectedToRoom);
|
|
52
|
-
const peerCount = useHMSStore(selectPeerCount);
|
|
53
|
-
const availableRoles = useHMSStore(selectAvailableRoleNames);
|
|
54
|
-
let participantList = useHMSStore(isConnected ? selectPeers : selectRemotePeers);
|
|
55
|
-
const rolesWithParticipants = Array.from(new Set(participantList.map(peer => peer.roleName)));
|
|
56
|
-
const vanillaStore = useHMSVanillaStore();
|
|
57
|
-
if (params?.metadata?.isHandRaised) {
|
|
58
|
-
participantList = participantList.filter(peer => {
|
|
59
|
-
return vanillaStore.getState(selectPeerMetadata(peer.id)).isHandRaised;
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
if (params?.role && availableRoles.includes(params.role)) {
|
|
63
|
-
participantList = participantList.filter(peer => peer.roleName === params.role);
|
|
64
|
-
}
|
|
65
|
-
if (params?.search) {
|
|
66
|
-
const search = params.search.toLowerCase();
|
|
67
|
-
participantList = participantList.filter(
|
|
68
|
-
peer => peer.roleName?.toLowerCase().includes(search) || peer.name.toLowerCase().includes(search),
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
return { participants: participantList, isConnected, peerCount, rolesWithParticipants };
|
|
72
|
-
};
|