-
Notifications
You must be signed in to change notification settings - Fork 78
Expand file tree
/
Copy pathModalLocalAndRemotePIP.tsx
More file actions
112 lines (103 loc) · 3.5 KB
/
ModalLocalAndRemotePIP.tsx
File metadata and controls
112 lines (103 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import {
concatStyleSets,
ContextualMenu,
IDragOptions,
IModalStyleProps,
IModalStyles,
IStackStyles,
IStyleFunctionOrObject,
Modal,
Stack
} from '@fluentui/react';
import React, { useMemo } from 'react';
import { CallAdapter } from '../CallComposite';
import { CallAdapterProvider } from '../CallComposite/adapter/CallAdapterProvider';
import { LocalAndRemotePIP } from '../CallComposite/components/LocalAndRemotePIP';
import { useHandlers } from '../CallComposite/hooks/useHandlers';
import { useSelector } from '../CallComposite/hooks/useSelector';
import { localAndRemotePIPSelector } from '../CallComposite/selectors/localAndRemotePIPSelector';
/**
* Drag options for Modal in {@link ModalLocalAndRemotePIP} component
*/
const DRAG_OPTIONS: IDragOptions = {
moveMenuItemText: 'Move',
closeMenuItemText: 'Close',
menu: ContextualMenu,
keepInBounds: true
};
/**
* Styles for {@link ModalLocalAndRemotePIP} component
*/
export type ModalLocalAndRemotePIPStyles = { modal?: Partial<IModalStyles> };
const _ModalLocalAndRemotePIP = (props: {
hidden: boolean;
modalLayerHostId: string;
styles?: ModalLocalAndRemotePIPStyles;
}): JSX.Element => {
const rootStyles = props.hidden ? hiddenStyle : PIPContainerStyle;
const pictureInPictureProps = useSelector(localAndRemotePIPSelector);
const pictureInPictureHandlers = useHandlers(LocalAndRemotePIP);
const localAndRemotePIP = useMemo(
() => <LocalAndRemotePIP {...pictureInPictureProps} {...pictureInPictureHandlers} />,
[pictureInPictureProps, pictureInPictureHandlers]
);
const modalStylesThemed = concatStyleSets(modalStyle, props.styles?.modal);
return (
<Stack styles={rootStyles}>
<Modal
isOpen={true}
isModeless={true}
dragOptions={DRAG_OPTIONS}
styles={modalStylesThemed}
layerProps={{ hostId: props.modalLayerHostId }}
>
{
// Only render LocalAndRemotePIP when this component is NOT hidden because VideoGallery needs to have
// possession of the dominant remote participant video stream
!props.hidden && localAndRemotePIP
}
</Modal>
</Stack>
);
};
/**
* A wrapping component with a draggable {@link LocalAndRemotePIP} component that is bound to a LayerHost component with id
* specified by `modalLayerHostId` prop
* @private
*/
export const ModalLocalAndRemotePIP = (props: {
callAdapter: CallAdapter;
hidden: boolean;
modalLayerHostId: string;
children?: React.ReactNode;
styles?: ModalLocalAndRemotePIPStyles;
}): JSX.Element => {
return (
<CallAdapterProvider adapter={props.callAdapter}>
<_ModalLocalAndRemotePIP {...props}>{props.children}</_ModalLocalAndRemotePIP>
</CallAdapterProvider>
);
};
const PIPContainerStyle: IStackStyles = {
root: { position: 'absolute', width: '100%', height: '100%', pointerEvents: 'none' }
};
const hiddenStyle: IStackStyles = concatStyleSets(PIPContainerStyle, { root: { display: 'none' } });
const modalStyle: IStyleFunctionOrObject<IModalStyleProps, IModalStyles> = {
main: {
minWidth: 'min-content',
minHeight: 'min-content',
position: 'absolute',
overflow: 'hidden',
// pointer events for root Modal div set to auto to make LocalAndRemotePIP interactive
pointerEvents: 'auto',
touchAction: 'none'
},
root: {
width: '100%',
height: '100%',
// pointer events for root Modal div set to none to make descendants interactive
pointerEvents: 'none'
}
};