CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/chat/video/launch-button.tsx
Views: 687
1
import { Button, Popover } from "antd";
2
import { debounce } from "lodash";
3
import type { CSSProperties, ReactNode } from "react";
4
import { useMemo } from "react";
5
import { useInterval } from "react-interval-hook";
6
import type { ChatActions } from "../actions";
7
import { React, useState, useTypedRedux } from "@cocalc/frontend/app-framework";
8
import { Icon } from "@cocalc/frontend/components";
9
10
const VIDEO_UPDATE_INTERVAL_MS = 30 * 1000;
11
// jit.si doesn't seem to have a limit...?
12
const VIDEO_CHAT_LIMIT = 99999;
13
14
interface Props {
15
actions: ChatActions;
16
style?: CSSProperties;
17
label?: ReactNode;
18
}
19
20
export default function VideoChatButton({
21
actions,
22
style: style0,
23
label,
24
}: Props) {
25
// to know if somebody else has video chat opened for this file
26
// @ts-ignore
27
const file_use = useTypedRedux("file_use", "file_use");
28
29
const [counter, set_counter] = useState<number>(0); // to force updates periodically.
30
useInterval(() => set_counter(counter + 1), VIDEO_UPDATE_INTERVAL_MS / 2);
31
const videoChat = useMemo(
32
() => actions.frameTreeActions?.getVideoChat(),
33
[actions],
34
);
35
36
if (videoChat == null) {
37
// eg sage worksheets...
38
return null;
39
}
40
41
const click_video_button = debounce(
42
() => {
43
if (videoChat.weAreChatting()) {
44
// we are chatting, so stop chatting
45
videoChat.stopChatting();
46
} else {
47
videoChat.startChatting(); // not chatting, so start
48
actions.sendChat({
49
input: `${
50
videoChat.getUserName() ?? "User"
51
} joined [the video chat](${videoChat.url()}).`,
52
});
53
}
54
},
55
750,
56
{ leading: true },
57
);
58
59
function render_num_chatting(
60
num_users_chatting: number,
61
): JSX.Element | undefined {
62
if (num_users_chatting > 0) {
63
return (
64
<span>
65
<hr />
66
There following {num_users_chatting} people are using video chat:
67
<br />
68
{videoChat?.getUserNames().join(", ")}
69
</span>
70
);
71
}
72
}
73
74
function render_join(num_users_chatting: number): JSX.Element {
75
if (videoChat?.weAreChatting()) {
76
return (
77
<span>
78
<b>Leave</b> this video chatroom.
79
</span>
80
);
81
} else {
82
if (num_users_chatting < VIDEO_CHAT_LIMIT) {
83
return (
84
<span>
85
{num_users_chatting == 0 ? "Start a new " : "Join the current"}{" "}
86
video chat.
87
</span>
88
);
89
} else {
90
return (
91
<span>
92
At most {VIDEO_CHAT_LIMIT} people can use the video chat at once.
93
</span>
94
);
95
}
96
}
97
}
98
99
const num_users_chatting: number = videoChat?.numUsersChatting() ?? 0;
100
const style: React.CSSProperties = { cursor: "pointer" };
101
if (num_users_chatting > 0) {
102
style.color = "#c9302c";
103
}
104
105
const body = (
106
<>
107
<Icon name="video-camera" />
108
{num_users_chatting > 0 && (
109
<span style={{ marginLeft: "5px" }}>{num_users_chatting}</span>
110
)}
111
<span style={{ marginLeft: "5px" }}>{label ?? "Video Chat"}</span>
112
</>
113
);
114
115
const btn = (
116
<Button onClick={click_video_button} style={{ ...style, ...style0 }}>
117
{body}
118
</Button>
119
);
120
121
return (
122
<Popover
123
mouseEnterDelay={0.8}
124
title={() => (
125
<span>
126
{render_join(num_users_chatting)}
127
{render_num_chatting(num_users_chatting)}
128
</span>
129
)}
130
>
131
{btn}
132
</Popover>
133
);
134
}
135
136