@whereby.com/browser-sdk 3.31.2 → 3.33.0
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/cdn/v3-embed.js +5 -5
- package/dist/cdn/v3-react.js +10 -10
- package/dist/embed/index.cjs +3 -0
- package/dist/embed/index.d.ts +6 -0
- package/dist/embed/index.esm.js +3 -0
- package/dist/react/index.cjs +528 -87
- package/dist/react/index.d.ts +198 -5
- package/dist/react/index.esm.js +511 -90
- package/package.json +3 -3
package/dist/react/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { WherebyClient, CURRENT_SPEAKER_CHANGED, debounce } from '@whereby.com/core';
|
|
3
|
-
export { ACCEPTED_FILE_TYPES, MAX_FILES_PER_UPLOAD, MAX_FILE_SIZE, getUsableCameraEffectPresets, isAudioDenoiserSupported } from '@whereby.com/core';
|
|
2
|
+
import { WherebyClient, CURRENT_SPEAKER_CHANGED, debounce, ROOM_INTEGRATION_PICKER_MESSAGES, roomIntegrationPickerUrl } from '@whereby.com/core';
|
|
3
|
+
export { ACCEPTED_FILE_TYPES, MAX_FILES_PER_UPLOAD, MAX_FILE_SIZE, ROOM_INTEGRATION_PICKER_MESSAGES, getUsableCameraEffectPresets, isAudioDenoiserSupported, roomIntegrationContent, roomIntegrationContentTagName, roomIntegrationPickerUrl } from '@whereby.com/core';
|
|
4
4
|
import runes from 'runes';
|
|
5
5
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
6
6
|
|
|
@@ -151,7 +151,7 @@ const VideoView = React.forwardRef((_a, ref) => {
|
|
|
151
151
|
});
|
|
152
152
|
VideoView.displayName = "VideoView";
|
|
153
153
|
|
|
154
|
-
const browserSdkVersion = "3.
|
|
154
|
+
const browserSdkVersion = "3.33.0";
|
|
155
155
|
|
|
156
156
|
const initialState$1 = {
|
|
157
157
|
chatMessages: [],
|
|
@@ -178,10 +178,19 @@ const initialState$1 = {
|
|
|
178
178
|
participantsInCurrentGroup: [],
|
|
179
179
|
broadcastingParticipants: [],
|
|
180
180
|
},
|
|
181
|
+
isAudioOnlyModeEnabled: false,
|
|
181
182
|
isCameraEnabled: false,
|
|
182
183
|
isMicrophoneEnabled: false,
|
|
183
184
|
localParticipant: undefined,
|
|
184
185
|
remoteParticipants: [],
|
|
186
|
+
roomIntegrations: {
|
|
187
|
+
hasFetched: false,
|
|
188
|
+
isFetching: false,
|
|
189
|
+
error: null,
|
|
190
|
+
embeddable: [],
|
|
191
|
+
enabled: [],
|
|
192
|
+
running: [],
|
|
193
|
+
},
|
|
185
194
|
screenshares: [],
|
|
186
195
|
connectionStatus: "ready",
|
|
187
196
|
connectionError: null,
|
|
@@ -243,6 +252,7 @@ function useRoomConnection(roomUrl, roomConnectionOptions = defaultRoomConnectio
|
|
|
243
252
|
const toggleMicrophone = React.useCallback((enabled) => client.toggleMicrophone(enabled), [client]);
|
|
244
253
|
const toggleHdMode = React.useCallback((enabled) => client.toggleHdMode(enabled), [client]);
|
|
245
254
|
const toggleLowDataMode = React.useCallback((enabled) => client.toggleLowDataMode(enabled), [client]);
|
|
255
|
+
const toggleAudioOnlyMode = React.useCallback((enabled, options) => client.toggleAudioOnlyMode(enabled, options), [client]);
|
|
246
256
|
const toggleWidescreenMode = React.useCallback((enabled) => client.toggleWidescreenMode(enabled), [client]);
|
|
247
257
|
const toggleRaiseHand = React.useCallback((enabled) => client.toggleRaiseHand(enabled), [client]);
|
|
248
258
|
const askToSpeak = React.useCallback((participantId) => client.askToSpeak(participantId), [client]);
|
|
@@ -268,6 +278,9 @@ function useRoomConnection(roomUrl, roomConnectionOptions = defaultRoomConnectio
|
|
|
268
278
|
const endMeeting = React.useCallback((stayBehind) => client.endMeeting(stayBehind), [client]);
|
|
269
279
|
const joinBreakoutGroup = React.useCallback((group) => client.joinBreakoutGroup(group), [client]);
|
|
270
280
|
const joinBreakoutMainRoom = React.useCallback(() => client.joinBreakoutMainRoom(), [client]);
|
|
281
|
+
const startRoomIntegration = React.useCallback((options) => client.startRoomIntegration(options), [client]);
|
|
282
|
+
const stopRoomIntegration = React.useCallback((options) => client.stopRoomIntegration(options), [client]);
|
|
283
|
+
const updateRoomIntegrationProps = React.useCallback((options) => client.updateRoomIntegrationProps(options), [client]);
|
|
271
284
|
const startBreakoutSession = React.useCallback((options) => client.startBreakoutSession(options), [client]);
|
|
272
285
|
const updateBreakoutSession = React.useCallback((options) => client.updateBreakoutSession(options), [client]);
|
|
273
286
|
const stopBreakoutSession = React.useCallback(() => client.stopBreakoutSession(), [client]);
|
|
@@ -333,11 +346,15 @@ function useRoomConnection(roomUrl, roomConnectionOptions = defaultRoomConnectio
|
|
|
333
346
|
toggleRaiseHand,
|
|
334
347
|
toggleHdMode,
|
|
335
348
|
toggleLowDataMode,
|
|
349
|
+
toggleAudioOnlyMode,
|
|
336
350
|
toggleWidescreenMode,
|
|
337
351
|
spotlightParticipant,
|
|
338
352
|
removeSpotlight,
|
|
339
353
|
joinBreakoutGroup,
|
|
340
354
|
joinBreakoutMainRoom,
|
|
355
|
+
startRoomIntegration,
|
|
356
|
+
stopRoomIntegration,
|
|
357
|
+
updateRoomIntegrationProps,
|
|
341
358
|
startBreakoutSession,
|
|
342
359
|
updateBreakoutSession,
|
|
343
360
|
stopBreakoutSession,
|
|
@@ -534,6 +551,9 @@ function VideoCell(_a) {
|
|
|
534
551
|
React.createElement("div", Object.assign({ style: contentStyle }, rest), React.cloneElement(children, { contentWidth, contentHeight, withRoundedCorners, withShadow }))));
|
|
535
552
|
}
|
|
536
553
|
|
|
554
|
+
const IntegrationCell = ({ cellId, children, isHiddenCell = false }) => (React.createElement("div", { "data-cell-id": cellId, "aria-hidden": isHiddenCell || undefined, style: { height: "100%", width: "100%" } }, children));
|
|
555
|
+
IntegrationCell.displayName = "IntegrationCell";
|
|
556
|
+
|
|
537
557
|
function generateStylesFromFrame({ origin, bounds }) {
|
|
538
558
|
return {
|
|
539
559
|
top: Math.round(origin.top),
|
|
@@ -549,7 +569,10 @@ function renderVideoCell({ cell, child, clientId, style = {}, withRoundedCorners
|
|
|
549
569
|
function renderSubgridVideoCells({ content, stageLayout, withRoundedCorners, withShadow, }) {
|
|
550
570
|
const cells = stageLayout.subgrid.cells;
|
|
551
571
|
return content.map((child, index) => {
|
|
552
|
-
var _a, _b, _c, _d;
|
|
572
|
+
var _a, _b, _c, _d, _e;
|
|
573
|
+
if (!child) {
|
|
574
|
+
return null;
|
|
575
|
+
}
|
|
553
576
|
const cell = cells[index];
|
|
554
577
|
const style = { height: Math.round(cell.bounds.height), width: Math.round(cell.bounds.width), transform: "" };
|
|
555
578
|
const origin = {
|
|
@@ -557,9 +580,9 @@ function renderSubgridVideoCells({ content, stageLayout, withRoundedCorners, wit
|
|
|
557
580
|
left: stageLayout.subgrid.origin.left + cell.origin.left,
|
|
558
581
|
};
|
|
559
582
|
style.transform = `translate3d(${Math.round(origin.left)}px, ${Math.round(origin.top)}px, 0)`;
|
|
560
|
-
const clientId = (
|
|
561
|
-
const leftPaddings = ((
|
|
562
|
-
const rightPaddings = ((
|
|
583
|
+
const clientId = ((_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.cellId) || ((_c = (_b = child === null || child === void 0 ? void 0 : child.props) === null || _b === void 0 ? void 0 : _b.participant) === null || _c === void 0 ? void 0 : _c.id);
|
|
584
|
+
const leftPaddings = ((_d = cell.paddings) === null || _d === void 0 ? void 0 : _d.left) || 0;
|
|
585
|
+
const rightPaddings = ((_e = cell.paddings) === null || _e === void 0 ? void 0 : _e.right) || 0;
|
|
563
586
|
const childWithProps = React.cloneElement(child, {
|
|
564
587
|
avatarSize: cell.bounds.width - leftPaddings - rightPaddings,
|
|
565
588
|
canZoom: false,
|
|
@@ -583,8 +606,8 @@ function renderPresentationGridVideoCells({ content, isConstrained, stageLayout,
|
|
|
583
606
|
var _a;
|
|
584
607
|
const cells = ((_a = stageLayout.presentationGrid) === null || _a === void 0 ? void 0 : _a.cells) || [];
|
|
585
608
|
return content.map((child, index) => {
|
|
586
|
-
var _a, _b;
|
|
587
|
-
if (!stageLayout.presentationGrid) {
|
|
609
|
+
var _a, _b, _c, _d;
|
|
610
|
+
if (!child || !stageLayout.presentationGrid) {
|
|
588
611
|
return null;
|
|
589
612
|
}
|
|
590
613
|
const cell = cells[index];
|
|
@@ -599,10 +622,10 @@ function renderPresentationGridVideoCells({ content, isConstrained, stageLayout,
|
|
|
599
622
|
height: Math.round(cell.bounds.height),
|
|
600
623
|
transform: `translate3d(${Math.round(origin.left)}px, ${Math.round(origin.top)}px, 0)`,
|
|
601
624
|
};
|
|
602
|
-
const clientId = (
|
|
625
|
+
const clientId = ((_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.cellId) || ((_c = (_b = child === null || child === void 0 ? void 0 : child.props) === null || _b === void 0 ? void 0 : _b.participant) === null || _c === void 0 ? void 0 : _c.id);
|
|
603
626
|
const childWithProps = React.cloneElement(child, {
|
|
604
627
|
isSmallCell: cell.isSmallCell,
|
|
605
|
-
isZoomedByDefault: !!isConstrained &&
|
|
628
|
+
isZoomedByDefault: !!isConstrained && !!((_d = child === null || child === void 0 ? void 0 : child.props) === null || _d === void 0 ? void 0 : _d.participant) && !child.props.participant.isPresentation,
|
|
606
629
|
canZoom: !!isConstrained,
|
|
607
630
|
key: clientId || `presentation-${index}`,
|
|
608
631
|
});
|
|
@@ -620,8 +643,8 @@ function renderGridVideoCells({ content, isConstrained, stageLayout, withRounded
|
|
|
620
643
|
var _a;
|
|
621
644
|
const cells = ((_a = stageLayout.videoGrid) === null || _a === void 0 ? void 0 : _a.cells) || [];
|
|
622
645
|
const gridVideoCells = content.map((child, index) => {
|
|
623
|
-
var _a, _b;
|
|
624
|
-
if (!stageLayout.videoGrid) {
|
|
646
|
+
var _a, _b, _c, _d;
|
|
647
|
+
if (!child || !stageLayout.videoGrid) {
|
|
625
648
|
return null;
|
|
626
649
|
}
|
|
627
650
|
const cell = cells[index];
|
|
@@ -634,10 +657,10 @@ function renderGridVideoCells({ content, isConstrained, stageLayout, withRounded
|
|
|
634
657
|
height: Math.round(cell.bounds.height),
|
|
635
658
|
transform: `translate3d(${Math.round(origin.left)}px, ${Math.round(origin.top)}px, 0)`,
|
|
636
659
|
};
|
|
637
|
-
const clientId = (
|
|
660
|
+
const clientId = ((_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.cellId) || ((_c = (_b = child === null || child === void 0 ? void 0 : child.props) === null || _b === void 0 ? void 0 : _b.participant) === null || _c === void 0 ? void 0 : _c.id);
|
|
638
661
|
const childWithProps = React.cloneElement(child, {
|
|
639
662
|
isSmallCell: cell.isSmallCell,
|
|
640
|
-
isZoomedByDefault: !!isConstrained &&
|
|
663
|
+
isZoomedByDefault: !!isConstrained && !!((_d = child === null || child === void 0 ? void 0 : child.props) === null || _d === void 0 ? void 0 : _d.participant) && !child.props.participant.isPresentation,
|
|
641
664
|
canZoom: !!isConstrained,
|
|
642
665
|
key: clientId || `video-${index}`,
|
|
643
666
|
});
|
|
@@ -685,7 +708,33 @@ function renderFloatingVideoCell({ content, containerFrame, stageLayout, withRou
|
|
|
685
708
|
withShadow: false,
|
|
686
709
|
});
|
|
687
710
|
}
|
|
688
|
-
|
|
711
|
+
const HIDDEN_CELL_STYLE = {
|
|
712
|
+
width: 1,
|
|
713
|
+
height: 1,
|
|
714
|
+
opacity: 0,
|
|
715
|
+
overflow: "hidden",
|
|
716
|
+
pointerEvents: "none",
|
|
717
|
+
};
|
|
718
|
+
function renderHiddenCells({ content }) {
|
|
719
|
+
const cell = { bounds: { width: 1, height: 1 }, aspectRatio: 1 };
|
|
720
|
+
return content.map((child, index) => {
|
|
721
|
+
var _a;
|
|
722
|
+
if (!child) {
|
|
723
|
+
return null;
|
|
724
|
+
}
|
|
725
|
+
const clientId = ((_a = child.props) === null || _a === void 0 ? void 0 : _a.cellId) || `hidden-${index}`;
|
|
726
|
+
const childWithProps = React.cloneElement(child, { isHiddenCell: true, key: clientId });
|
|
727
|
+
return renderVideoCell({ cell, child: childWithProps, clientId, style: HIDDEN_CELL_STYLE });
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
function withIntegrationCellsFirst(cells) {
|
|
731
|
+
const isIntegrationCell = (cell) => { var _a, _b; return ((_b = (_a = cell === null || cell === void 0 ? void 0 : cell.props) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.type) === IntegrationCell; };
|
|
732
|
+
const integrationCells = cells
|
|
733
|
+
.filter(isIntegrationCell)
|
|
734
|
+
.sort((a, b) => String(a === null || a === void 0 ? void 0 : a.key).localeCompare(String(b === null || b === void 0 ? void 0 : b.key)));
|
|
735
|
+
return [...integrationCells, ...cells.filter((cell) => !isIntegrationCell(cell))];
|
|
736
|
+
}
|
|
737
|
+
function VideoStageLayout({ containerFrame, debug = false, featureRoundedCornersOff = false, floatingContent, gridContent = [], isConstrained = false, layoutOverflowBackdropFrame = makeFrame(), layoutVideoStage: stageLayout, presentationGridContent = [], subgridContent = [], hiddenContent = [], }) {
|
|
689
738
|
const withRoundedCorners = !featureRoundedCornersOff && !isConstrained;
|
|
690
739
|
const cells = [];
|
|
691
740
|
if (gridContent.length) {
|
|
@@ -722,16 +771,221 @@ function VideoStageLayout({ containerFrame, debug = false, featureRoundedCorners
|
|
|
722
771
|
withShadow: true,
|
|
723
772
|
}));
|
|
724
773
|
}
|
|
774
|
+
if (hiddenContent.length) {
|
|
775
|
+
cells.push(...renderHiddenCells({ content: hiddenContent }));
|
|
776
|
+
}
|
|
725
777
|
return (React.createElement("div", { key: "video-stage-layout", style: {
|
|
726
778
|
width: "100%",
|
|
727
779
|
height: "100%",
|
|
728
780
|
position: "relative",
|
|
729
781
|
} },
|
|
730
782
|
hasBounds(layoutOverflowBackdropFrame.bounds) && (React.createElement("div", { style: generateStylesFromFrame(layoutOverflowBackdropFrame) })),
|
|
731
|
-
cells,
|
|
783
|
+
withIntegrationCellsFirst(cells),
|
|
732
784
|
debug && (React.createElement(React.Fragment, null))));
|
|
733
785
|
}
|
|
734
786
|
|
|
787
|
+
function useIframeContract(ref, hookName, enabled) {
|
|
788
|
+
React.useEffect(() => {
|
|
789
|
+
if (!enabled) {
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
const timer = setTimeout(() => {
|
|
793
|
+
const frame = ref.current;
|
|
794
|
+
if (!frame) {
|
|
795
|
+
console.warn(`${hookName}: iframeProps.ref was never attached. Spread iframeProps onto the ` +
|
|
796
|
+
`<iframe> you render — without the ref the hook cannot tell which window is ` +
|
|
797
|
+
`answering, so nothing will ever arrive.`);
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
if (frame.hasAttribute("sandbox")) {
|
|
801
|
+
console.warn(`${hookName}: the iframe has a sandbox attribute. Some integrations open their ` +
|
|
802
|
+
`own window to sign in, which a sandbox without allow-popups blocks silently.`);
|
|
803
|
+
}
|
|
804
|
+
}, 0);
|
|
805
|
+
return () => clearTimeout(timer);
|
|
806
|
+
}, [ref, hookName, enabled]);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
const HOST_TO_FRAME = {
|
|
810
|
+
PROPS: "whereby:props",
|
|
811
|
+
SET_VOLUME: "whereby:setVolume",
|
|
812
|
+
GET_VOLUME: "whereby:getVolume",
|
|
813
|
+
};
|
|
814
|
+
const FRAME_TO_HOST = {
|
|
815
|
+
FRAME_READY: "whereby:frameReady",
|
|
816
|
+
UPDATE_PROPS: "whereby:updateProps",
|
|
817
|
+
CONTENT_READY: "whereby:contentReady",
|
|
818
|
+
CLOSE: "whereby:close",
|
|
819
|
+
AUDIO_OVERRIDE: "whereby:audioOverride",
|
|
820
|
+
VOLUME: "whereby:volume",
|
|
821
|
+
};
|
|
822
|
+
const DEFAULT_ALLOW$1 = "autoplay; fullscreen; encrypted-media; picture-in-picture";
|
|
823
|
+
const VOLUME_REQUEST_TIMEOUT = 2000;
|
|
824
|
+
function outboundProps(session) {
|
|
825
|
+
return Object.assign(Object.assign({}, session.props), { ispresenter: session.isPresenter, presenterdisplayname: session.presenterDisplayName, roomintegrationsessionid: session.roomIntegrationSessionId, breakoutgroupid: session.breakoutGroupId });
|
|
826
|
+
}
|
|
827
|
+
function diffProps(next, previous) {
|
|
828
|
+
if (!previous) {
|
|
829
|
+
return next;
|
|
830
|
+
}
|
|
831
|
+
return Object.keys(next).reduce((patch, key) => {
|
|
832
|
+
if (previous[key] !== next[key]) {
|
|
833
|
+
patch[key] = next[key];
|
|
834
|
+
}
|
|
835
|
+
return patch;
|
|
836
|
+
}, {});
|
|
837
|
+
}
|
|
838
|
+
function useRoomIntegrationView({ session, onAudioOverride, onContentReady, allow = DEFAULT_ALLOW$1, title, }) {
|
|
839
|
+
var _a;
|
|
840
|
+
const client = (_a = React.useContext(WherebyContext)) === null || _a === void 0 ? void 0 : _a.getRoomConnection();
|
|
841
|
+
const iframeRef = React.useRef(null);
|
|
842
|
+
const lastSentRef = React.useRef(null);
|
|
843
|
+
const isFrameReadyRef = React.useRef(false);
|
|
844
|
+
const volumeRequestsRef = React.useRef(new Map());
|
|
845
|
+
const nextRequestIdRef = React.useRef(0);
|
|
846
|
+
const sessionRef = React.useRef(session);
|
|
847
|
+
const onAudioOverrideRef = React.useRef(onAudioOverride);
|
|
848
|
+
const onContentReadyRef = React.useRef(onContentReady);
|
|
849
|
+
sessionRef.current = session;
|
|
850
|
+
onAudioOverrideRef.current = onAudioOverride;
|
|
851
|
+
onContentReadyRef.current = onContentReady;
|
|
852
|
+
const { webview } = session.integration;
|
|
853
|
+
const { roomIntegrationSessionId } = session;
|
|
854
|
+
const frameOrigin = React.useMemo(() => {
|
|
855
|
+
try {
|
|
856
|
+
return new URL(webview).origin;
|
|
857
|
+
}
|
|
858
|
+
catch (_a) {
|
|
859
|
+
console.warn(`useRoomIntegrationView: unusable webview url ${webview}`);
|
|
860
|
+
return null;
|
|
861
|
+
}
|
|
862
|
+
}, [webview]);
|
|
863
|
+
const src = React.useMemo(() => {
|
|
864
|
+
if (!frameOrigin) {
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
const url = new URL(webview);
|
|
868
|
+
url.searchParams.set("parentOrigin", window.location.origin);
|
|
869
|
+
url.searchParams.set("roomintegrationsessionid", roomIntegrationSessionId);
|
|
870
|
+
return url.href;
|
|
871
|
+
}, [webview, frameOrigin, roomIntegrationSessionId]);
|
|
872
|
+
const post = React.useCallback((type, payload) => {
|
|
873
|
+
var _a;
|
|
874
|
+
const frameWindow = (_a = iframeRef.current) === null || _a === void 0 ? void 0 : _a.contentWindow;
|
|
875
|
+
if (!frameWindow || !frameOrigin) {
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
frameWindow.postMessage({ type, payload }, frameOrigin);
|
|
879
|
+
}, [frameOrigin]);
|
|
880
|
+
React.useEffect(() => {
|
|
881
|
+
isFrameReadyRef.current = false;
|
|
882
|
+
lastSentRef.current = null;
|
|
883
|
+
}, [src]);
|
|
884
|
+
React.useEffect(() => {
|
|
885
|
+
if (!frameOrigin) {
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
const handleMessage = (event) => {
|
|
889
|
+
var _a, _b, _c, _d;
|
|
890
|
+
if (event.origin !== frameOrigin || event.source !== ((_a = iframeRef.current) === null || _a === void 0 ? void 0 : _a.contentWindow)) {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
const { type, payload } = event.data || {};
|
|
894
|
+
const currentSession = sessionRef.current;
|
|
895
|
+
switch (type) {
|
|
896
|
+
case FRAME_TO_HOST.FRAME_READY: {
|
|
897
|
+
const props = outboundProps(currentSession);
|
|
898
|
+
isFrameReadyRef.current = true;
|
|
899
|
+
lastSentRef.current = props;
|
|
900
|
+
post(HOST_TO_FRAME.PROPS, props);
|
|
901
|
+
break;
|
|
902
|
+
}
|
|
903
|
+
case FRAME_TO_HOST.UPDATE_PROPS: {
|
|
904
|
+
if (payload === null || payload === void 0 ? void 0 : payload.props) {
|
|
905
|
+
client === null || client === void 0 ? void 0 : client.updateRoomIntegrationProps({
|
|
906
|
+
roomIntegrationSessionId: currentSession.roomIntegrationSessionId,
|
|
907
|
+
props: payload.props,
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
break;
|
|
911
|
+
}
|
|
912
|
+
case FRAME_TO_HOST.CLOSE: {
|
|
913
|
+
if (currentSession.canStop) {
|
|
914
|
+
client === null || client === void 0 ? void 0 : client.stopRoomIntegration({
|
|
915
|
+
roomIntegrationSessionId: currentSession.roomIntegrationSessionId,
|
|
916
|
+
intent: "end",
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
break;
|
|
920
|
+
}
|
|
921
|
+
case FRAME_TO_HOST.AUDIO_OVERRIDE: {
|
|
922
|
+
(_b = onAudioOverrideRef.current) === null || _b === void 0 ? void 0 : _b.call(onAudioOverrideRef, (_c = payload === null || payload === void 0 ? void 0 : payload.enabled) !== null && _c !== void 0 ? _c : null);
|
|
923
|
+
break;
|
|
924
|
+
}
|
|
925
|
+
case FRAME_TO_HOST.CONTENT_READY: {
|
|
926
|
+
(_d = onContentReadyRef.current) === null || _d === void 0 ? void 0 : _d.call(onContentReadyRef);
|
|
927
|
+
break;
|
|
928
|
+
}
|
|
929
|
+
case FRAME_TO_HOST.VOLUME: {
|
|
930
|
+
const resolve = volumeRequestsRef.current.get(payload === null || payload === void 0 ? void 0 : payload.requestId);
|
|
931
|
+
if (resolve) {
|
|
932
|
+
volumeRequestsRef.current.delete(payload.requestId);
|
|
933
|
+
resolve(payload.volume);
|
|
934
|
+
}
|
|
935
|
+
break;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
window.addEventListener("message", handleMessage);
|
|
940
|
+
return () => window.removeEventListener("message", handleMessage);
|
|
941
|
+
}, [frameOrigin, client, post]);
|
|
942
|
+
const serializedProps = JSON.stringify(outboundProps(session));
|
|
943
|
+
React.useEffect(() => {
|
|
944
|
+
if (!isFrameReadyRef.current) {
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
const props = outboundProps(sessionRef.current);
|
|
948
|
+
const patch = diffProps(props, lastSentRef.current);
|
|
949
|
+
lastSentRef.current = props;
|
|
950
|
+
if (Object.keys(patch).length) {
|
|
951
|
+
post(HOST_TO_FRAME.PROPS, patch);
|
|
952
|
+
}
|
|
953
|
+
}, [serializedProps, post]);
|
|
954
|
+
const setVolume = React.useCallback((volume) => post(HOST_TO_FRAME.SET_VOLUME, { volume }), [post]);
|
|
955
|
+
const getVolume = React.useCallback(() => new Promise((resolve, reject) => {
|
|
956
|
+
const requestId = ++nextRequestIdRef.current;
|
|
957
|
+
const requests = volumeRequestsRef.current;
|
|
958
|
+
const timer = setTimeout(() => {
|
|
959
|
+
requests.delete(requestId);
|
|
960
|
+
reject(new Error("Timed out reading volume from the room integration"));
|
|
961
|
+
}, VOLUME_REQUEST_TIMEOUT);
|
|
962
|
+
requests.set(requestId, (volume) => {
|
|
963
|
+
clearTimeout(timer);
|
|
964
|
+
resolve(volume);
|
|
965
|
+
});
|
|
966
|
+
post(HOST_TO_FRAME.GET_VOLUME, { requestId });
|
|
967
|
+
}), [post]);
|
|
968
|
+
useIframeContract(iframeRef, "useRoomIntegrationView", !!src);
|
|
969
|
+
return {
|
|
970
|
+
iframeProps: src
|
|
971
|
+
? {
|
|
972
|
+
ref: iframeRef,
|
|
973
|
+
src,
|
|
974
|
+
title: title || session.integration.title,
|
|
975
|
+
allow,
|
|
976
|
+
}
|
|
977
|
+
: null,
|
|
978
|
+
getVolume,
|
|
979
|
+
setVolume,
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
const IFRAME_STYLE = { border: "none", width: "100%", height: "100%" };
|
|
984
|
+
function DefaultIntegrationView({ session }) {
|
|
985
|
+
const { iframeProps } = useRoomIntegrationView({ session });
|
|
986
|
+
return iframeProps ? React.createElement("iframe", Object.assign({}, iframeProps, { allowFullScreen: true, style: IFRAME_STYLE })) : null;
|
|
987
|
+
}
|
|
988
|
+
|
|
735
989
|
const WIDE_AR = 16 / 9;
|
|
736
990
|
const NORMAL_AR = 4 / 3;
|
|
737
991
|
const clamp = ({ value, min, max }) => Math.min(Math.max(value, min), max);
|
|
@@ -1787,6 +2041,7 @@ function makeVideoCellView({ aspectRatio, avatarSize, cellPaddings, client = und
|
|
|
1787
2041
|
avatarSize,
|
|
1788
2042
|
cellPaddings,
|
|
1789
2043
|
client,
|
|
2044
|
+
cellId: (client === null || client === void 0 ? void 0 : client.id) || "",
|
|
1790
2045
|
clientId: (client === null || client === void 0 ? void 0 : client.id) || "",
|
|
1791
2046
|
isDraggable,
|
|
1792
2047
|
isPlaceholder,
|
|
@@ -1794,20 +2049,38 @@ function makeVideoCellView({ aspectRatio, avatarSize, cellPaddings, client = und
|
|
|
1794
2049
|
type: "video",
|
|
1795
2050
|
};
|
|
1796
2051
|
}
|
|
2052
|
+
function integrationAspectRatio(session) {
|
|
2053
|
+
var _a;
|
|
2054
|
+
const reported = Number((_a = session.props) === null || _a === void 0 ? void 0 : _a.aspectratio);
|
|
2055
|
+
return isFinite(reported) && reported > 0 ? reported : undefined;
|
|
2056
|
+
}
|
|
2057
|
+
function roomIntegrationCellId(session) {
|
|
2058
|
+
return `room-integration:${session.roomIntegrationSessionId}`;
|
|
2059
|
+
}
|
|
2060
|
+
function makeIntegrationCellView({ session, isDraggable = false, isSubgrid = false, }) {
|
|
2061
|
+
const cellId = roomIntegrationCellId(session);
|
|
2062
|
+
return {
|
|
2063
|
+
aspectRatio: integrationAspectRatio(session) || 16 / 9,
|
|
2064
|
+
cellId,
|
|
2065
|
+
clientId: cellId,
|
|
2066
|
+
isDraggable,
|
|
2067
|
+
isSubgrid,
|
|
2068
|
+
session,
|
|
2069
|
+
type: "integration",
|
|
2070
|
+
};
|
|
2071
|
+
}
|
|
1797
2072
|
|
|
1798
2073
|
const STAGE_PARTICIPANT_LIMIT = 12;
|
|
1799
2074
|
const ACTIVE_VIDEO_SUBGRID_TRIGGER = 12;
|
|
1800
2075
|
const ACTIVE_VIDEOS_PHONE_LIMIT = 24;
|
|
1801
2076
|
|
|
1802
|
-
function calculateSubgridViews({ clientViews, activeVideosSubgridTrigger, shouldShowSubgrid, spotlightedParticipants,
|
|
2077
|
+
function calculateSubgridViews({ clientViews, activeVideosSubgridTrigger, shouldShowSubgrid, spotlightedParticipants, maximizedCellId, hasStagedIntegration = false, isPhoneResolution, }) {
|
|
1803
2078
|
if (!shouldShowSubgrid) {
|
|
1804
2079
|
return [];
|
|
1805
2080
|
}
|
|
1806
2081
|
const hasSpotlights = spotlightedParticipants.length > 0;
|
|
1807
|
-
const hasPresentationStage = hasSpotlights;
|
|
1808
|
-
const notMaximized =
|
|
1809
|
-
? clientViews.filter((client) => client.id !== maximizedParticipant.id)
|
|
1810
|
-
: clientViews;
|
|
2082
|
+
const hasPresentationStage = hasSpotlights || hasStagedIntegration;
|
|
2083
|
+
const notMaximized = maximizedCellId ? clientViews.filter((client) => client.id !== maximizedCellId) : clientViews;
|
|
1811
2084
|
const notSpotlighted = notMaximized.filter((client) => !client.isPresentation && !spotlightedParticipants.includes(client));
|
|
1812
2085
|
const noVideoViews = notSpotlighted.filter((client) => !client.isVideoEnabled);
|
|
1813
2086
|
const videoLimitReached = notSpotlighted.filter((client) => client.isVideoEnabled).length > activeVideosSubgridTrigger;
|
|
@@ -1838,7 +2111,8 @@ function calculateSubgridViews({ clientViews, activeVideosSubgridTrigger, should
|
|
|
1838
2111
|
}
|
|
1839
2112
|
return noVideoViews;
|
|
1840
2113
|
}
|
|
1841
|
-
|
|
2114
|
+
const NO_INTEGRATIONS = [];
|
|
2115
|
+
function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID_TRIGGER, stageParticipantLimit = STAGE_PARTICIPANT_LIMIT, forceSubgrid = true, enableSubgrid = true, maximizedCellId, floatingCellId, isConstrained = false, includeIntegrations = false, } = {}) {
|
|
1842
2116
|
var _a;
|
|
1843
2117
|
const client = (_a = React.useContext(WherebyContext)) === null || _a === void 0 ? void 0 : _a.getGrid();
|
|
1844
2118
|
if (!client) {
|
|
@@ -1851,6 +2125,9 @@ function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID
|
|
|
1851
2125
|
const handleSpotlightedParticipantsChanged = React.useCallback((spotlighted) => {
|
|
1852
2126
|
setState((prevState) => (Object.assign(Object.assign({}, prevState), { spotlightedParticipants: spotlighted })));
|
|
1853
2127
|
}, [setState]);
|
|
2128
|
+
const handleRunningRoomIntegrationsChanged = React.useCallback((runningRoomIntegrations) => {
|
|
2129
|
+
setState((prevState) => (Object.assign(Object.assign({}, prevState), { runningRoomIntegrations })));
|
|
2130
|
+
}, [setState]);
|
|
1854
2131
|
const handleNumParticipantsChanged = React.useCallback((num) => {
|
|
1855
2132
|
setState((prevState) => (Object.assign(Object.assign({}, prevState), { numParticipants: num })));
|
|
1856
2133
|
}, [setState]);
|
|
@@ -1858,19 +2135,21 @@ function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID
|
|
|
1858
2135
|
const unsubscribeClientViews = client.subscribeClientViews(handleClientViewChanged);
|
|
1859
2136
|
const unsubscribeSpotlighted = client.subscribeSpotlightedParticipants(handleSpotlightedParticipantsChanged);
|
|
1860
2137
|
const unsubscribeNumParticipants = client.subscribeNumberOfClientViews(handleNumParticipantsChanged);
|
|
2138
|
+
const unsubscribeRunningRoomIntegrations = client.subscribeRunningRoomIntegrations(handleRunningRoomIntegrationsChanged);
|
|
1861
2139
|
setState(client.getState());
|
|
1862
2140
|
return () => {
|
|
1863
2141
|
unsubscribeClientViews();
|
|
1864
2142
|
unsubscribeSpotlighted();
|
|
1865
2143
|
unsubscribeNumParticipants();
|
|
2144
|
+
unsubscribeRunningRoomIntegrations();
|
|
1866
2145
|
};
|
|
1867
2146
|
}, [client]);
|
|
1868
2147
|
const allClientViews = React.useMemo(() => state.allClientViews, [state.allClientViews]);
|
|
1869
2148
|
const spotlightedParticipants = React.useMemo(() => state.spotlightedParticipants, [state.spotlightedParticipants]);
|
|
1870
2149
|
const numParticipants = React.useMemo(() => state.numParticipants, [state.numParticipants]);
|
|
1871
|
-
const
|
|
1872
|
-
|
|
1873
|
-
|
|
2150
|
+
const runningRoomIntegrations = React.useMemo(() => (includeIntegrations ? state.runningRoomIntegrations : NO_INTEGRATIONS), [includeIntegrations, state.runningRoomIntegrations]);
|
|
2151
|
+
const maximizedClientView = React.useMemo(() => (maximizedCellId ? allClientViews.find((client) => client.id === maximizedCellId) || null : null), [allClientViews, maximizedCellId]);
|
|
2152
|
+
const floatingClientView = React.useMemo(() => (floatingCellId ? allClientViews.find((client) => client.id === floatingCellId) || null : null), [allClientViews, floatingCellId]);
|
|
1874
2153
|
const clientViewsNotFloating = React.useMemo(() => {
|
|
1875
2154
|
if (floatingClientView) {
|
|
1876
2155
|
return allClientViews.filter((c) => c.id !== floatingClientView.id);
|
|
@@ -1883,51 +2162,84 @@ function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID
|
|
|
1883
2162
|
}
|
|
1884
2163
|
return forceSubgrid ? true : numParticipants > stageParticipantLimit;
|
|
1885
2164
|
}, [forceSubgrid, numParticipants, stageParticipantLimit, enableSubgrid]);
|
|
2165
|
+
const integrationsInPresentationGrid = React.useMemo(() => {
|
|
2166
|
+
if (!runningRoomIntegrations.length || maximizedClientView) {
|
|
2167
|
+
return [];
|
|
2168
|
+
}
|
|
2169
|
+
return [runningRoomIntegrations[0]];
|
|
2170
|
+
}, [runningRoomIntegrations, maximizedClientView]);
|
|
2171
|
+
const integrationsInSubgrid = React.useMemo(() => {
|
|
2172
|
+
if (!shouldShowSubgrid) {
|
|
2173
|
+
return [];
|
|
2174
|
+
}
|
|
2175
|
+
return runningRoomIntegrations.filter((session) => !integrationsInPresentationGrid.some((staged) => staged.roomIntegrationSessionId === session.roomIntegrationSessionId));
|
|
2176
|
+
}, [runningRoomIntegrations, integrationsInPresentationGrid, shouldShowSubgrid]);
|
|
2177
|
+
const integrationsHidden = React.useMemo(() => {
|
|
2178
|
+
const visible = [...integrationsInPresentationGrid, ...integrationsInSubgrid];
|
|
2179
|
+
return runningRoomIntegrations.filter((session) => !visible.some((shown) => shown.roomIntegrationSessionId === session.roomIntegrationSessionId));
|
|
2180
|
+
}, [runningRoomIntegrations, integrationsInPresentationGrid, integrationsInSubgrid]);
|
|
1886
2181
|
const clientViewsInSubgrid = React.useMemo(() => {
|
|
1887
2182
|
return calculateSubgridViews({
|
|
1888
2183
|
clientViews: clientViewsNotFloating,
|
|
1889
2184
|
activeVideosSubgridTrigger,
|
|
1890
2185
|
shouldShowSubgrid,
|
|
1891
2186
|
spotlightedParticipants,
|
|
1892
|
-
|
|
2187
|
+
maximizedCellId,
|
|
2188
|
+
hasStagedIntegration: integrationsInPresentationGrid.length > 0,
|
|
1893
2189
|
isPhoneResolution: isConstrained,
|
|
1894
2190
|
});
|
|
1895
|
-
}, [
|
|
2191
|
+
}, [
|
|
2192
|
+
clientViewsNotFloating,
|
|
2193
|
+
shouldShowSubgrid,
|
|
2194
|
+
activeVideosSubgridTrigger,
|
|
2195
|
+
spotlightedParticipants,
|
|
2196
|
+
maximizedCellId,
|
|
2197
|
+
integrationsInPresentationGrid,
|
|
2198
|
+
isConstrained,
|
|
2199
|
+
]);
|
|
1896
2200
|
const clientViewsOnStage = React.useMemo(() => {
|
|
1897
2201
|
return clientViewsNotFloating.filter((client) => !clientViewsInSubgrid.includes(client));
|
|
1898
2202
|
}, [clientViewsNotFloating, clientViewsInSubgrid]);
|
|
1899
2203
|
const clientViewsInPresentationGrid = React.useMemo(() => {
|
|
1900
|
-
if (
|
|
1901
|
-
return [
|
|
2204
|
+
if (maximizedClientView) {
|
|
2205
|
+
return [maximizedClientView];
|
|
2206
|
+
}
|
|
2207
|
+
if (integrationsInPresentationGrid.length) {
|
|
2208
|
+
return [];
|
|
1902
2209
|
}
|
|
1903
|
-
return spotlightedParticipants;
|
|
1904
|
-
}, [spotlightedParticipants,
|
|
2210
|
+
return spotlightedParticipants.filter((client) => clientViewsOnStage.includes(client));
|
|
2211
|
+
}, [spotlightedParticipants, maximizedClientView, integrationsInPresentationGrid, clientViewsOnStage]);
|
|
1905
2212
|
const clientViewsInGrid = React.useMemo(() => {
|
|
1906
2213
|
return clientViewsOnStage.filter((client) => !clientViewsInPresentationGrid.includes(client));
|
|
1907
2214
|
}, [clientViewsOnStage, clientViewsInPresentationGrid]);
|
|
1908
2215
|
return {
|
|
1909
2216
|
floatingClientView,
|
|
2217
|
+
maximizedClientView,
|
|
1910
2218
|
clientViewsInGrid,
|
|
1911
2219
|
clientViewsInPresentationGrid,
|
|
1912
2220
|
clientViewsInSubgrid,
|
|
2221
|
+
integrationsInPresentationGrid,
|
|
2222
|
+
integrationsInSubgrid,
|
|
2223
|
+
integrationsHidden,
|
|
1913
2224
|
spotlightedParticipants,
|
|
1914
2225
|
};
|
|
1915
2226
|
}
|
|
1916
2227
|
|
|
1917
|
-
function useGrid({ activeVideosSubgridTrigger, forceSubgrid, stageParticipantLimit = STAGE_PARTICIPANT_LIMIT, gridGap = 8, videoGridGap = 8, enableSubgrid = true, enableConstrainedGrid = true, } = {}) {
|
|
2228
|
+
function useGrid({ activeVideosSubgridTrigger, forceSubgrid, stageParticipantLimit = STAGE_PARTICIPANT_LIMIT, gridGap = 8, videoGridGap = 8, enableSubgrid = true, enableConstrainedGrid = true, includeIntegrations = false, } = {}) {
|
|
1918
2229
|
const [containerBounds, setContainerBounds] = React.useState({ width: 0, height: 0 });
|
|
1919
2230
|
const [isConstrained, setIsConstrained] = React.useState(false);
|
|
1920
2231
|
const [clientAspectRatios, setClientAspectRatios] = React.useState({});
|
|
1921
|
-
const [
|
|
1922
|
-
const [
|
|
1923
|
-
const { clientViewsInGrid, clientViewsInPresentationGrid, clientViewsInSubgrid, floatingClientView } = useGridParticipants({
|
|
2232
|
+
const [maximizedCellId, setMaximizedCellId] = React.useState(null);
|
|
2233
|
+
const [floatingCellId, setFloatingCellId] = React.useState(null);
|
|
2234
|
+
const { clientViewsInGrid, clientViewsInPresentationGrid, clientViewsInSubgrid, floatingClientView, maximizedClientView, integrationsInPresentationGrid, integrationsInSubgrid, integrationsHidden, } = useGridParticipants({
|
|
1924
2235
|
activeVideosSubgridTrigger,
|
|
1925
2236
|
forceSubgrid,
|
|
1926
2237
|
stageParticipantLimit,
|
|
1927
2238
|
enableSubgrid,
|
|
1928
|
-
|
|
1929
|
-
|
|
2239
|
+
maximizedCellId,
|
|
2240
|
+
floatingCellId,
|
|
1930
2241
|
isConstrained: !!enableConstrainedGrid && !!isConstrained,
|
|
2242
|
+
includeIntegrations,
|
|
1931
2243
|
});
|
|
1932
2244
|
const cellViewsFloating = React.useMemo(() => {
|
|
1933
2245
|
return floatingClientView
|
|
@@ -1952,26 +2264,35 @@ function useGrid({ activeVideosSubgridTrigger, forceSubgrid, stageParticipantLim
|
|
|
1952
2264
|
});
|
|
1953
2265
|
}, [clientViewsInGrid, clientAspectRatios]);
|
|
1954
2266
|
const cellViewsInPresentationGrid = React.useMemo(() => {
|
|
1955
|
-
return
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2267
|
+
return [
|
|
2268
|
+
...integrationsInPresentationGrid.map((session) => makeIntegrationCellView({ session })),
|
|
2269
|
+
...clientViewsInPresentationGrid.map((client) => {
|
|
2270
|
+
return makeVideoCellView({
|
|
2271
|
+
client,
|
|
2272
|
+
aspectRatio: clientAspectRatios[client.id],
|
|
2273
|
+
avatarSize: 0,
|
|
2274
|
+
cellPaddings: { top: 0, right: 0 },
|
|
2275
|
+
});
|
|
2276
|
+
}),
|
|
2277
|
+
];
|
|
2278
|
+
}, [clientViewsInPresentationGrid, integrationsInPresentationGrid, clientAspectRatios]);
|
|
1964
2279
|
const cellViewsInSubgrid = React.useMemo(() => {
|
|
1965
|
-
return
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
2280
|
+
return [
|
|
2281
|
+
...clientViewsInSubgrid.map((client) => {
|
|
2282
|
+
return makeVideoCellView({
|
|
2283
|
+
client,
|
|
2284
|
+
aspectRatio: clientAspectRatios[client.id],
|
|
2285
|
+
avatarSize: 0,
|
|
2286
|
+
cellPaddings: { top: 0, right: 0 },
|
|
2287
|
+
isSubgrid: true,
|
|
2288
|
+
});
|
|
2289
|
+
}),
|
|
2290
|
+
...integrationsInSubgrid.map((session) => makeIntegrationCellView({ session, isSubgrid: true })),
|
|
2291
|
+
];
|
|
2292
|
+
}, [clientViewsInSubgrid, integrationsInSubgrid, clientAspectRatios]);
|
|
2293
|
+
const cellViewsHidden = React.useMemo(() => {
|
|
2294
|
+
return integrationsHidden.map((session) => makeIntegrationCellView({ session }));
|
|
2295
|
+
}, [integrationsHidden]);
|
|
1975
2296
|
const containerFrame = React.useMemo(() => {
|
|
1976
2297
|
return makeFrame(containerBounds);
|
|
1977
2298
|
}, [containerBounds]);
|
|
@@ -2008,14 +2329,17 @@ function useGrid({ activeVideosSubgridTrigger, forceSubgrid, stageParticipantLim
|
|
|
2008
2329
|
cellViewsVideoGrid,
|
|
2009
2330
|
cellViewsInPresentationGrid,
|
|
2010
2331
|
cellViewsInSubgrid,
|
|
2332
|
+
cellViewsHidden,
|
|
2011
2333
|
clientAspectRatios,
|
|
2012
2334
|
videoStage,
|
|
2013
2335
|
setContainerBounds,
|
|
2014
2336
|
setClientAspectRatios,
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2337
|
+
maximizedCellId,
|
|
2338
|
+
setMaximizedCellId,
|
|
2339
|
+
maximizedParticipant: maximizedClientView,
|
|
2340
|
+
floatingCellId,
|
|
2341
|
+
setFloatingCellId,
|
|
2342
|
+
floatingParticipant: floatingClientView,
|
|
2019
2343
|
isConstrained,
|
|
2020
2344
|
};
|
|
2021
2345
|
}
|
|
@@ -2129,22 +2453,17 @@ ParticipantMenuTrigger.displayName = PopoverTrigger.displayName;
|
|
|
2129
2453
|
const ParticipantMenuItem = React.forwardRef((_a, ref) => {
|
|
2130
2454
|
var _b;
|
|
2131
2455
|
var { children, style, participantAction } = _a, props = __rest(_a, ["children", "style", "participantAction"]);
|
|
2132
|
-
const { participant, setOpen,
|
|
2456
|
+
const { participant, setOpen, maximizedCellId, setMaximizedCellId, floatingCellId, setFloatingCellId } = useParticipantMenu();
|
|
2133
2457
|
const client = (_b = React.useContext(WherebyContext)) === null || _b === void 0 ? void 0 : _b.getGrid();
|
|
2134
2458
|
const { spotlightedParticipants } = useGridParticipants();
|
|
2135
2459
|
const isSpotlighted = spotlightedParticipants.find((p) => p.id === participant.id);
|
|
2136
|
-
const isMaximized =
|
|
2137
|
-
const isFloating =
|
|
2460
|
+
const isMaximized = maximizedCellId === participant.id;
|
|
2461
|
+
const isFloating = floatingCellId === participant.id;
|
|
2138
2462
|
let onClick;
|
|
2139
2463
|
switch (participantAction) {
|
|
2140
2464
|
case "maximize":
|
|
2141
2465
|
onClick = () => {
|
|
2142
|
-
|
|
2143
|
-
setMaximizedParticipant(null);
|
|
2144
|
-
}
|
|
2145
|
-
else {
|
|
2146
|
-
setMaximizedParticipant(participant);
|
|
2147
|
-
}
|
|
2466
|
+
setMaximizedCellId(isMaximized ? null : participant.id);
|
|
2148
2467
|
setOpen(false);
|
|
2149
2468
|
};
|
|
2150
2469
|
break;
|
|
@@ -2161,12 +2480,7 @@ const ParticipantMenuItem = React.forwardRef((_a, ref) => {
|
|
|
2161
2480
|
break;
|
|
2162
2481
|
case "float":
|
|
2163
2482
|
onClick = () => {
|
|
2164
|
-
|
|
2165
|
-
setFloatingParticipant(null);
|
|
2166
|
-
}
|
|
2167
|
-
else {
|
|
2168
|
-
setFloatingParticipant(participant);
|
|
2169
|
-
}
|
|
2483
|
+
setFloatingCellId(isFloating ? null : participant.id);
|
|
2170
2484
|
setOpen(false);
|
|
2171
2485
|
};
|
|
2172
2486
|
break;
|
|
@@ -2283,28 +2597,35 @@ const GridVideoView = React.forwardRef((_a, ref) => {
|
|
|
2283
2597
|
return (React.createElement(VideoView, Object.assign({ ref: videoEl, style: Object.assign(Object.assign({ borderRadius: isConstrained ? 0 : "8px" }, (isConstrained ? { objectFit: "cover" } : {})), style), muted: participant.isLocalClient }, rest, { stream: s, onVideoResize: handleResize })));
|
|
2284
2598
|
});
|
|
2285
2599
|
GridVideoView.displayName = "GridVideoView";
|
|
2286
|
-
function renderCellView({ cellView, enableParticipantMenu, render }) {
|
|
2287
|
-
|
|
2288
|
-
if (!participant) {
|
|
2600
|
+
function renderCellView({ cellView, enableParticipantMenu, render, renderIntegration }) {
|
|
2601
|
+
if (!cellView) {
|
|
2289
2602
|
return undefined;
|
|
2290
2603
|
}
|
|
2291
2604
|
switch (cellView.type) {
|
|
2292
|
-
case "video":
|
|
2293
|
-
|
|
2605
|
+
case "video": {
|
|
2606
|
+
const participant = cellView.client;
|
|
2607
|
+
if (!participant) {
|
|
2608
|
+
return undefined;
|
|
2609
|
+
}
|
|
2610
|
+
return (React.createElement(GridCell, { participant: participant, cellId: cellView.cellId },
|
|
2294
2611
|
React.createElement(React.Fragment, null, render ? (render({ participant })) : (React.createElement(React.Fragment, null,
|
|
2295
2612
|
React.createElement(GridVideoView, null),
|
|
2296
2613
|
enableParticipantMenu ? React.createElement(DefaultParticipantMenu, { participant: participant }) : null)))));
|
|
2614
|
+
}
|
|
2615
|
+
case "integration":
|
|
2616
|
+
return (React.createElement(IntegrationCell, { cellId: cellView.cellId }, renderIntegration ? (renderIntegration({ session: cellView.session })) : (React.createElement(DefaultIntegrationView, { session: cellView.session }))));
|
|
2297
2617
|
}
|
|
2298
2618
|
}
|
|
2299
|
-
function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParticipant, stageParticipantLimit, gridGap, videoGridGap, enableSubgrid, enableParticipantMenu, enableConstrainedGrid, }) {
|
|
2619
|
+
function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParticipant, renderIntegration, stageParticipantLimit, gridGap, videoGridGap, enableSubgrid, enableParticipantMenu, enableConstrainedGrid, enableIntegrations = true, }) {
|
|
2300
2620
|
const gridRef = React.useRef(null);
|
|
2301
|
-
const { containerFrame, cellViewsFloating, cellViewsVideoGrid, cellViewsInPresentationGrid, cellViewsInSubgrid, clientAspectRatios, videoStage, setContainerBounds, setClientAspectRatios,
|
|
2621
|
+
const { containerFrame, cellViewsFloating, cellViewsVideoGrid, cellViewsInPresentationGrid, cellViewsInSubgrid, cellViewsHidden, clientAspectRatios, videoStage, setContainerBounds, setClientAspectRatios, maximizedCellId, setMaximizedCellId, maximizedParticipant, isConstrained, floatingCellId, setFloatingCellId, floatingParticipant, } = useGrid({
|
|
2302
2622
|
activeVideosSubgridTrigger: 12,
|
|
2303
2623
|
stageParticipantLimit,
|
|
2304
2624
|
gridGap,
|
|
2305
2625
|
videoGridGap,
|
|
2306
2626
|
enableSubgrid,
|
|
2307
2627
|
enableConstrainedGrid,
|
|
2628
|
+
includeIntegrations: enableIntegrations,
|
|
2308
2629
|
});
|
|
2309
2630
|
const handleSetClientAspectRatio = React.useCallback(({ aspectRatio, clientId }) => {
|
|
2310
2631
|
setClientAspectRatios((prev) => (Object.assign(Object.assign({}, prev), { [clientId]: aspectRatio })));
|
|
@@ -2315,13 +2636,16 @@ function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParti
|
|
|
2315
2636
|
: {})));
|
|
2316
2637
|
}, [cellViewsFloating]);
|
|
2317
2638
|
const presentationGridContent = React.useMemo(() => cellViewsInPresentationGrid.map((cellView) => renderCellView(Object.assign({ cellView,
|
|
2318
|
-
enableParticipantMenu
|
|
2639
|
+
enableParticipantMenu,
|
|
2640
|
+
renderIntegration }, (renderParticipant ? { render: ({ participant }) => renderParticipant({ participant }) } : {})))), [cellViewsInPresentationGrid, renderIntegration]);
|
|
2319
2641
|
const gridContent = React.useMemo(() => cellViewsVideoGrid.map((cellView) => renderCellView(Object.assign({ cellView,
|
|
2320
2642
|
enableParticipantMenu }, (renderParticipant ? { render: ({ participant }) => renderParticipant({ participant }) } : {})))), [cellViewsVideoGrid]);
|
|
2321
2643
|
const subgridContent = React.useMemo(() => cellViewsInSubgrid.map((cellView) => renderCellView(Object.assign({ cellView,
|
|
2322
|
-
enableParticipantMenu
|
|
2644
|
+
enableParticipantMenu,
|
|
2645
|
+
renderIntegration }, (renderSubgridParticipant
|
|
2323
2646
|
? { render: ({ participant }) => renderSubgridParticipant({ participant }) }
|
|
2324
|
-
: {})))), [cellViewsInSubgrid]);
|
|
2647
|
+
: {})))), [cellViewsInSubgrid, renderIntegration]);
|
|
2648
|
+
const hiddenContent = React.useMemo(() => cellViewsHidden.map((cellView) => renderCellView({ cellView, renderIntegration })), [cellViewsHidden, renderIntegration]);
|
|
2325
2649
|
React.useEffect(() => {
|
|
2326
2650
|
if (!gridRef.current) {
|
|
2327
2651
|
return;
|
|
@@ -2344,10 +2668,12 @@ function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParti
|
|
|
2344
2668
|
cellViewsInPresentationGrid,
|
|
2345
2669
|
cellViewsInSubgrid,
|
|
2346
2670
|
clientAspectRatios,
|
|
2671
|
+
maximizedCellId,
|
|
2672
|
+
setMaximizedCellId,
|
|
2347
2673
|
maximizedParticipant,
|
|
2348
|
-
|
|
2674
|
+
floatingCellId,
|
|
2675
|
+
setFloatingCellId,
|
|
2349
2676
|
floatingParticipant,
|
|
2350
|
-
setFloatingParticipant,
|
|
2351
2677
|
isConstrained,
|
|
2352
2678
|
} },
|
|
2353
2679
|
React.createElement("div", { ref: gridRef, style: {
|
|
@@ -2355,7 +2681,102 @@ function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParti
|
|
|
2355
2681
|
height: "100%",
|
|
2356
2682
|
position: "relative",
|
|
2357
2683
|
} },
|
|
2358
|
-
React.createElement(VideoStageLayout, { containerFrame: containerFrame, floatingContent: floatingContent, layoutVideoStage: videoStage, presentationGridContent: presentationGridContent, gridContent: gridContent, subgridContent: subgridContent }))));
|
|
2684
|
+
React.createElement(VideoStageLayout, { containerFrame: containerFrame, floatingContent: floatingContent, layoutVideoStage: videoStage, presentationGridContent: presentationGridContent, gridContent: gridContent, subgridContent: subgridContent, hiddenContent: hiddenContent }))));
|
|
2685
|
+
}
|
|
2686
|
+
|
|
2687
|
+
function subscribeToRoomIntegrationPicker({ pickerOrigin, getSource, onOutcome, }) {
|
|
2688
|
+
let settled = false;
|
|
2689
|
+
function handleMessage(event) {
|
|
2690
|
+
if (settled || event.origin !== pickerOrigin || !event.source || event.source !== getSource()) {
|
|
2691
|
+
return;
|
|
2692
|
+
}
|
|
2693
|
+
const { type, payload } = event.data || {};
|
|
2694
|
+
if (type === ROOM_INTEGRATION_PICKER_MESSAGES.FORM_SUBMIT) {
|
|
2695
|
+
settle({ type: "submitted", content: payload });
|
|
2696
|
+
}
|
|
2697
|
+
else if (type === ROOM_INTEGRATION_PICKER_MESSAGES.FORM_CLOSE) {
|
|
2698
|
+
settle({ type: "cancelled" });
|
|
2699
|
+
}
|
|
2700
|
+
else if (type === ROOM_INTEGRATION_PICKER_MESSAGES.ERROR) {
|
|
2701
|
+
settle({
|
|
2702
|
+
type: "error",
|
|
2703
|
+
error: new Error((payload === null || payload === void 0 ? void 0 : payload.message) || "The room integration picker failed"),
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
const unsubscribe = () => {
|
|
2708
|
+
settled = true;
|
|
2709
|
+
window.removeEventListener("message", handleMessage);
|
|
2710
|
+
};
|
|
2711
|
+
const settle = (outcome) => {
|
|
2712
|
+
unsubscribe();
|
|
2713
|
+
onOutcome(outcome);
|
|
2714
|
+
};
|
|
2715
|
+
window.addEventListener("message", handleMessage);
|
|
2716
|
+
return unsubscribe;
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2719
|
+
const DEFAULT_ALLOW = "clipboard-read; clipboard-write; fullscreen";
|
|
2720
|
+
function useRoomIntegrationPicker({ integration, onPicked, onCancel, onError, featureSource, allow = DEFAULT_ALLOW, title, }) {
|
|
2721
|
+
const iframeRef = React.useRef(null);
|
|
2722
|
+
const onPickedRef = React.useRef(onPicked);
|
|
2723
|
+
const onCancelRef = React.useRef(onCancel);
|
|
2724
|
+
const onErrorRef = React.useRef(onError);
|
|
2725
|
+
onPickedRef.current = onPicked;
|
|
2726
|
+
onCancelRef.current = onCancel;
|
|
2727
|
+
onErrorRef.current = onError;
|
|
2728
|
+
const { webview } = integration;
|
|
2729
|
+
const pickerOrigin = React.useMemo(() => {
|
|
2730
|
+
try {
|
|
2731
|
+
return new URL(webview).origin;
|
|
2732
|
+
}
|
|
2733
|
+
catch (_a) {
|
|
2734
|
+
console.warn(`useRoomIntegrationPicker: unusable webview url ${webview}`);
|
|
2735
|
+
return null;
|
|
2736
|
+
}
|
|
2737
|
+
}, [webview]);
|
|
2738
|
+
const src = React.useMemo(() => {
|
|
2739
|
+
if (!pickerOrigin) {
|
|
2740
|
+
return null;
|
|
2741
|
+
}
|
|
2742
|
+
return roomIntegrationPickerUrl({
|
|
2743
|
+
integration: { webview },
|
|
2744
|
+
parentOrigin: window.location.origin,
|
|
2745
|
+
featureSource,
|
|
2746
|
+
});
|
|
2747
|
+
}, [pickerOrigin, webview, featureSource]);
|
|
2748
|
+
React.useEffect(() => {
|
|
2749
|
+
if (!pickerOrigin) {
|
|
2750
|
+
return;
|
|
2751
|
+
}
|
|
2752
|
+
return subscribeToRoomIntegrationPicker({
|
|
2753
|
+
pickerOrigin,
|
|
2754
|
+
getSource: () => { var _a; return (_a = iframeRef.current) === null || _a === void 0 ? void 0 : _a.contentWindow; },
|
|
2755
|
+
onOutcome: (outcome) => {
|
|
2756
|
+
var _a, _b;
|
|
2757
|
+
if (outcome.type === "submitted") {
|
|
2758
|
+
onPickedRef.current(outcome.content || {});
|
|
2759
|
+
return;
|
|
2760
|
+
}
|
|
2761
|
+
if (outcome.type === "cancelled") {
|
|
2762
|
+
(_a = onCancelRef.current) === null || _a === void 0 ? void 0 : _a.call(onCancelRef);
|
|
2763
|
+
return;
|
|
2764
|
+
}
|
|
2765
|
+
(_b = onErrorRef.current) === null || _b === void 0 ? void 0 : _b.call(onErrorRef, outcome.error);
|
|
2766
|
+
},
|
|
2767
|
+
});
|
|
2768
|
+
}, [pickerOrigin, src]);
|
|
2769
|
+
useIframeContract(iframeRef, "useRoomIntegrationPicker", !!src);
|
|
2770
|
+
return {
|
|
2771
|
+
iframeProps: src
|
|
2772
|
+
? {
|
|
2773
|
+
ref: iframeRef,
|
|
2774
|
+
src,
|
|
2775
|
+
title: title || `${integration.title} picker`,
|
|
2776
|
+
allow,
|
|
2777
|
+
}
|
|
2778
|
+
: null,
|
|
2779
|
+
};
|
|
2359
2780
|
}
|
|
2360
2781
|
|
|
2361
|
-
export { GridCell, GridVideoView, ParticipantMenu, ParticipantMenuContent, ParticipantMenuItem, ParticipantMenuTrigger, Grid as VideoGrid, VideoView, Provider as WherebyProvider, useLocalMedia, useRoomConnection };
|
|
2782
|
+
export { GridCell, GridVideoView, ParticipantMenu, ParticipantMenuContent, ParticipantMenuItem, ParticipantMenuTrigger, Grid as VideoGrid, VideoView, Provider as WherebyProvider, subscribeToRoomIntegrationPicker, useGrid, useLocalMedia, useRoomConnection, useRoomIntegrationPicker, useRoomIntegrationView };
|