Skip to content

Commit eafd800

Browse files
authored
Merge pull request #686 from Lemoncode/feature/#214-Create-videoconference-widget
feature/#214 Create a videoconference widget
2 parents 54e7d18 + e635f1d commit eafd800

File tree

9 files changed

+304
-0
lines changed

9 files changed

+304
-0
lines changed

public/rich-components/videoconference.svg

Lines changed: 18 additions & 0 deletions
Loading

src/common/components/mock-components/front-rich-components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export * from './appBar';
1414
export * from './buttonBar/buttonBar';
1515
export * from './tabsbar';
1616
export * from './audio-player';
17+
export * from './videoconference';
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
import { Group, Rect, Circle, Line, Arc, Path } from 'react-konva';
2+
import { ShapeSizeRestrictions, ShapeType } from '@/core/model';
3+
import { forwardRef, useEffect, useMemo, useState } from 'react';
4+
import { ShapeProps } from '../shape.model';
5+
import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions';
6+
import { useGroupShapeProps } from '../mock-components.utils';
7+
8+
const videoconferenceShapeSizeRestrictions: ShapeSizeRestrictions = {
9+
minWidth: 200,
10+
minHeight: 200,
11+
maxWidth: -1,
12+
maxHeight: -1,
13+
defaultWidth: 600,
14+
defaultHeight: 400,
15+
};
16+
17+
export const getVideoconferenceShapeSizeRestrictions =
18+
(): ShapeSizeRestrictions => videoconferenceShapeSizeRestrictions;
19+
20+
const shapeType: ShapeType = 'videoPlayer';
21+
22+
export const VideoconferenceShape = forwardRef<any, ShapeProps>(
23+
(props, ref) => {
24+
const { x, y, width, height, id, onSelected, ...shapeProps } = props;
25+
const restrictedSize = fitSizeToShapeSizeRestrictions(
26+
videoconferenceShapeSizeRestrictions,
27+
width,
28+
height
29+
);
30+
const { width: restrictedWidth, height: restrictedHeight } = restrictedSize;
31+
32+
const controlBarHeight = 40;
33+
34+
const [avatar1BodyArcRadius, setAvatar1BodyArcRadius] = useState(0);
35+
36+
useEffect(() => {
37+
setAvatar1BodyArcRadius(() => {
38+
const newRadius = Math.min(
39+
restrictedWidth / 2,
40+
(restrictedHeight - controlBarHeight - 20) / 2
41+
);
42+
return newRadius;
43+
});
44+
}, [restrictedWidth, restrictedHeight]);
45+
46+
const avatar2Width = useMemo(() => {
47+
if (restrictedWidth * 0.2 >= restrictedHeight / 2) {
48+
return restrictedHeight / 2;
49+
}
50+
return restrictedWidth * 0.2;
51+
}, [restrictedWidth, restrictedHeight]);
52+
53+
const commonGroupProps = useGroupShapeProps(
54+
props,
55+
restrictedSize,
56+
shapeType,
57+
ref
58+
);
59+
60+
return (
61+
<Group {...commonGroupProps} {...shapeProps}>
62+
{/* Avatar 1 */}
63+
<Group>
64+
<Rect
65+
x={0}
66+
y={0}
67+
width={restrictedWidth}
68+
height={restrictedHeight}
69+
cornerRadius={10}
70+
stroke="black"
71+
strokeWidth={2}
72+
fill="lightgray"
73+
/>
74+
<Arc
75+
x={restrictedWidth / 2}
76+
y={restrictedHeight - controlBarHeight}
77+
stroke="black"
78+
strokeWidth={2}
79+
innerRadius={0}
80+
outerRadius={avatar1BodyArcRadius}
81+
angle={180}
82+
rotation={180}
83+
fill="white"
84+
/>
85+
<Circle
86+
x={restrictedWidth / 2}
87+
y={restrictedHeight - controlBarHeight - avatar1BodyArcRadius * 1.5}
88+
width={avatar1BodyArcRadius}
89+
height={avatar1BodyArcRadius}
90+
stroke="black"
91+
strokeWidth={2}
92+
fill="white"
93+
/>
94+
</Group>
95+
{/* Avatar 2 */}
96+
<Group
97+
x={restrictedWidth - avatar2Width - 10}
98+
y={restrictedHeight - controlBarHeight - avatar2Width}
99+
>
100+
<Rect
101+
width={avatar2Width}
102+
height={avatar2Width}
103+
cornerRadius={[10, 10, 0, 0]}
104+
stroke="black"
105+
strokeWidth={2}
106+
fill="darkgrey"
107+
/>
108+
<Arc
109+
x={avatar2Width - avatar2Width * 0.5}
110+
y={avatar2Width}
111+
stroke="black"
112+
strokeWidth={2}
113+
innerRadius={0}
114+
outerRadius={avatar2Width * 0.35}
115+
angle={180}
116+
rotation={180}
117+
fill="white"
118+
/>
119+
<Circle
120+
x={avatar2Width - avatar2Width * 0.5}
121+
y={avatar2Width - avatar2Width * 0.55}
122+
width={avatar2Width * 0.4}
123+
height={avatar2Width * 0.4}
124+
stroke="black"
125+
strokeWidth={2}
126+
fill="white"
127+
/>
128+
</Group>
129+
<Line
130+
points={[
131+
0,
132+
restrictedHeight - controlBarHeight,
133+
restrictedWidth,
134+
restrictedHeight - controlBarHeight,
135+
]}
136+
stroke="black"
137+
strokeWidth={2}
138+
/>
139+
{/* Control Bar */}
140+
<Group>
141+
<Rect
142+
x={0}
143+
y={restrictedHeight - controlBarHeight}
144+
width={restrictedWidth}
145+
height={controlBarHeight}
146+
cornerRadius={0}
147+
/>
148+
{/* hang up call button*/}
149+
<Circle
150+
x={restrictedWidth / 2 + 50}
151+
y={restrictedHeight - controlBarHeight / 2}
152+
width={30}
153+
height={30}
154+
fill="red"
155+
stroke="black"
156+
strokeWidth={2}
157+
/>
158+
<Arc
159+
x={restrictedWidth / 2 + 52}
160+
y={restrictedHeight - controlBarHeight / 2}
161+
stroke="black"
162+
strokeWidth={2}
163+
innerRadius={5}
164+
outerRadius={6}
165+
angle={180}
166+
rotation={60}
167+
fill="white"
168+
/>
169+
{/* Camera Button*/}
170+
<Circle
171+
x={restrictedWidth / 2}
172+
y={restrictedHeight - controlBarHeight / 2}
173+
width={30}
174+
height={30}
175+
fill="darkgray"
176+
stroke="black"
177+
strokeWidth={2}
178+
/>
179+
<Rect
180+
x={restrictedWidth / 2 - 9}
181+
y={restrictedHeight - controlBarHeight / 2 - 6}
182+
width={18}
183+
height={12}
184+
stroke="black"
185+
strokeWidth={2}
186+
/>
187+
<Circle
188+
x={restrictedWidth / 2}
189+
y={restrictedHeight - controlBarHeight / 2}
190+
width={5}
191+
height={5}
192+
fill="black"
193+
stroke="black"
194+
strokeWidth={2}
195+
/>
196+
{/* Microphone Button*/}
197+
<Circle
198+
x={restrictedWidth / 2 - 50}
199+
y={restrictedHeight - controlBarHeight / 2}
200+
width={30}
201+
height={30}
202+
fill="darkgray"
203+
stroke="black"
204+
strokeWidth={2}
205+
/>
206+
<Group
207+
x={restrictedWidth / 2 - 62}
208+
y={restrictedHeight - controlBarHeight + 9}
209+
>
210+
<Path
211+
data="M9 2m0 3a3 3 0 0 1 3 -3h0a3 3 0 0 1 3 3v5a3 3 0 0 1 -3 3h0a3 3 0 0 1 -3 -3z"
212+
stroke="black"
213+
strokeWidth={2}
214+
scaleX={1}
215+
scaleY={1}
216+
/>
217+
<Path
218+
data="M5 10a7 7 0 0 0 14 0"
219+
stroke="black"
220+
strokeWidth={2}
221+
scaleX={1}
222+
scaleY={1}
223+
/>
224+
<Path
225+
data="M8 21l8 0"
226+
stroke="black"
227+
strokeWidth={2}
228+
scaleX={1}
229+
scaleY={1}
230+
/>
231+
<Path
232+
data="M12 17l0 4"
233+
stroke="black"
234+
strokeWidth={2}
235+
scaleX={1}
236+
scaleY={1}
237+
/>
238+
</Group>
239+
</Group>
240+
</Group>
241+
);
242+
}
243+
);

src/core/model/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export type ShapeType =
7070
| 'slider'
7171
| 'link'
7272
| 'cilinder'
73+
| 'videoconference'
7374
| 'richtext';
7475

7576
export const ShapeDisplayName: Record<ShapeType, string> = {
@@ -131,6 +132,7 @@ export const ShapeDisplayName: Record<ShapeType, string> = {
131132
slider: 'Slider',
132133
richtext: 'Rich Text',
133134
cilinder: 'Cilinder',
135+
videoconference: 'Videoconference',
134136
};
135137

136138
export type EditType = 'input' | 'textarea' | 'imageupload';

src/pods/canvas/model/shape-size.mapper.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import {
5959
getTabsBarShapeSizeRestrictions,
6060
getVerticalMenuShapeSizeRestrictions,
6161
getVideoPlayerShapeSizeRestrictions,
62+
getVideoconferenceShapeSizeRestrictions,
6263
// other imports
6364
} from '@/common/components/mock-components/front-rich-components';
6465
import {
@@ -142,6 +143,7 @@ const shapeSizeMap: Record<ShapeType, () => ShapeSizeRestrictions> = {
142143
slider: getSliderShapeSizeRestrictions,
143144
audioPlayer: getAudioPlayerShapeSizeRestrictions,
144145
cilinder: getCilinderShapeSizeRestrictions,
146+
videoconference: getVideoconferenceShapeSizeRestrictions,
145147
};
146148

147149
export default shapeSizeMap;

src/pods/canvas/shape-renderer/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
renderModal,
4242
renderButtonBar,
4343
renderTabsBar,
44+
renderVideoconference,
4445
} from './simple-rich-components';
4546
import {
4647
renderDiamond,
@@ -188,6 +189,8 @@ export const renderShapeComponent = (
188189
return renderSlider(shape, shapeRenderedProps);
189190
case 'cilinder':
190191
return renderCilinder(shape, shapeRenderedProps);
192+
case 'videoconference':
193+
return renderVideoconference(shape, shapeRenderedProps);
191194
default:
192195
return renderNotFound(shape, shapeRenderedProps);
193196
}

src/pods/canvas/shape-renderer/simple-rich-components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export * from './appBar.renderer';
1414
export * from './button-bar.renderer';
1515
export * from './tabsbar.renderer';
1616
export * from './audio-player.renderer';
17+
export * from './videoconference.renderer';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { VideoconferenceShape } from '@/common/components/mock-components/front-rich-components';
2+
import { ShapeRendererProps } from '../model';
3+
import { ShapeModel } from '@/core/model';
4+
5+
export const renderVideoconference = (
6+
shape: ShapeModel,
7+
shapeRenderedProps: ShapeRendererProps
8+
) => {
9+
const { handleSelected, shapeRefs, handleDragEnd, handleTransform } =
10+
shapeRenderedProps;
11+
12+
return (
13+
<VideoconferenceShape
14+
id={shape.id}
15+
key={shape.id}
16+
ref={shapeRefs.current[shape.id]}
17+
x={shape.x}
18+
y={shape.y}
19+
name="shape"
20+
width={shape.width}
21+
height={shape.height}
22+
draggable
23+
typeOfTransformer={shape.typeOfTransformer}
24+
onSelected={handleSelected}
25+
onDragEnd={handleDragEnd(shape.id)}
26+
onTransform={handleTransform}
27+
onTransformEnd={handleTransform}
28+
/>
29+
);
30+
};

src/pods/galleries/rich-components-gallery/rich-components-gallery-data/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ export const mockRichComponentsCollection: ItemInfo[] = [
2020
{ thumbnailSrc: '/rich-components/tabsbar.svg', type: 'tabsBar' },
2121
{ thumbnailSrc: '/rich-components/vertical-menu.svg', type: 'vertical-menu' },
2222
{ thumbnailSrc: '/rich-components/videoPlayer.svg', type: 'videoPlayer' },
23+
{
24+
thumbnailSrc: '/rich-components/videoconference.svg',
25+
type: 'videoconference',
26+
},
2327
];

0 commit comments

Comments
 (0)