Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/chat/video/video-chat.ts
Views: 687
import { client_db } from "@cocalc/util/schema";1import { alert_message } from "@cocalc/frontend/alerts";2import { webapp_client } from "@cocalc/frontend/webapp-client";3import { len, trunc_middle } from "@cocalc/util/misc";4import { redux } from "@cocalc/frontend/app-framework";5import { open_new_tab } from "../../misc/open-browser-tab";67const VIDEO_CHAT_SERVER = "https://meet.jit.si";8const VIDEO_UPDATE_INTERVAL_MS = 30 * 1000;910// Create pop-up window for video chat11function videoWindow(url: string) {12return open_new_tab(url, true, { noopener: false });13}1415const videoWindows = {};1617export class VideoChat {18private intervalId?: any;19private project_id: string;20private path: string;2122constructor({ project_id, path }: { project_id: string; path: string }) {23this.project_id = project_id;24this.path = path;25}2627close = () => {28this.closeVideoChatWindow();29delete this.intervalId;30};3132weAreChatting = (): boolean => {33const { account_id } = webapp_client;34if (account_id == null) {35return false;36}37const timestamp: Date | undefined = this.getUsers()?.[account_id];38return (39timestamp != null &&40webapp_client.server_time().valueOf() - timestamp.valueOf() <=41VIDEO_UPDATE_INTERVAL_MS42);43};4445numUsersChatting = (): number => {46return len(this.getUsers());47};4849getUserName = (): string | undefined => {50const users = redux.getStore("users");51const { account_id } = webapp_client;52if (account_id == null) {53return;54}55return users?.get_name(account_id);56};5758getUserNames = (): string[] => {59const users = redux.getStore("users");60const v: string[] = [];61for (const account_id in this.getUsers()) {62const name = users.get_name(account_id)?.trim();63if (name) {64v.push(trunc_middle(name, 25));65}66}67return v;68};6970private getUsers = (): { [account_id: string]: Date } => {71// Users is a map {account_id:timestamp of last chat file marking}72return (73redux.getStore("file_use")?.get_video_chat_users({74project_id: this.project_id,75path: this.path,76ttl: 1.3 * VIDEO_UPDATE_INTERVAL_MS,77}) ?? {}78);79};8081stopChatting = () => {82this.closeVideoChatWindow();83};8485startChatting = () => {86redux.getActions("file_use")?.mark_file(this.project_id, this.path, "chat");87this.openVideoChatWindow();88};8990// The canonical secret chatroom id.91private chatroomId = (): string => {92const secret_token = redux93.getStore("projects")94.getIn(["project_map", this.project_id, "status", "secret_token"]);95if (!secret_token) {96alert_message({97type: "error",98message: "You MUST be a project collaborator -- video chat will fail.",99});100}101return client_db.sha1(secret_token, this.path);102};103104url = (): string => {105const room_id = this.chatroomId();106return `${VIDEO_CHAT_SERVER}/${room_id}`;107};108109// Open the video chat window, if it isn't already opened110private openVideoChatWindow = (): void => {111const room_id = this.chatroomId();112if (videoWindows[room_id]) {113return;114}115116const chatWindowIsOpen = () => {117return redux118.getActions("file_use")119?.mark_file(this.project_id, this.path, "video", 0);120};121122chatWindowIsOpen();123this.intervalId = setInterval(124chatWindowIsOpen,125VIDEO_UPDATE_INTERVAL_MS * 0.8,126);127128//const title = `CoCalc Video Chat: ${trunc_middle(this.path, 30)}`;129const w = videoWindow(this.url());130// https://github.com/sagemathinc/cocalc/issues/3648131if (w == null) {132return;133}134videoWindows[room_id] = w;135// disabled -- see https://github.com/sagemathinc/cocalc/issues/1899136//w.addEventListener "unload", =>137// @close_video_chat_window()138// workaround for https://github.com/sagemathinc/cocalc/issues/1899139const pollWindow = setInterval(() => {140if (w.closed !== false) {141// != is required for compatibility with Opera142clearInterval(pollWindow);143this.closeVideoChatWindow();144}145}, 1000);146};147148// User wants to close the video chat window, but not via just clicking the149// close button on the popup window150private closeVideoChatWindow = (): void => {151const room_id = this.chatroomId();152const w = videoWindows[room_id];153if (!w) {154return;155}156redux157.getActions("file_use")158?.mark_file(this.project_id, this.path, "video", 0, true, new Date(0));159if (this.intervalId) {160clearInterval(this.intervalId);161delete this.intervalId;162}163delete videoWindows[room_id];164w.close();165};166}167168169