Skip to content
Snippets Groups Projects
Unverified Commit 573e6d46 authored by Douglas Fabris's avatar Douglas Fabris Committed by GitHub
Browse files

Chore: Rewrite Jitsi Contextualbar to TS (#25303)

parent c1ccd0ef
No related branches found
No related tags found
No related merge requests found
Showing
with 71 additions and 76 deletions
...@@ -8,8 +8,6 @@ import { useTranslation } from '../../../client/contexts/TranslationContext'; ...@@ -8,8 +8,6 @@ import { useTranslation } from '../../../client/contexts/TranslationContext';
import { useUser } from '../../../client/contexts/UserContext'; import { useUser } from '../../../client/contexts/UserContext';
import Header from '../../../client/components/Header'; import Header from '../../../client/components/Header';
const templateBBB = lazy(() => import('../../../client/views/room/contextualBar/Call/BBB'));
addAction('bbb_video', ({ room }) => { addAction('bbb_video', ({ room }) => {
const enabled = useSetting('bigbluebutton_Enabled'); const enabled = useSetting('bigbluebutton_Enabled');
const t = useTranslation(); const t = useTranslation();
...@@ -30,6 +28,8 @@ addAction('bbb_video', ({ room }) => { ...@@ -30,6 +28,8 @@ addAction('bbb_video', ({ room }) => {
const username = user ? user.username : ''; const username = user ? user.username : '';
const enableOption = enabled && (!username || !room.muted?.includes(username)); const enableOption = enabled && (!username || !room.muted?.includes(username));
const templateBBB = lazy(() => import('../../../client/views/room/contextualBar/VideoConference/BBB'));
return useMemo( return useMemo(
() => () =>
enableOption enableOption
...@@ -62,7 +62,7 @@ addAction('bbb_video', ({ room }) => { ...@@ -62,7 +62,7 @@ addAction('bbb_video', ({ room }) => {
); );
}); });
const templateJitsi = lazy(() => import('../../../client/views/room/contextualBar/Call/Jitsi')); const templateJitsi = lazy(() => import('../../../client/views/room/contextualBar/VideoConference/Jitsi'));
addAction('video', ({ room }) => { addAction('video', ({ room }) => {
const enabled = useSetting('Jitsi_Enabled'); const enabled = useSetting('Jitsi_Enabled');
......
...@@ -6,6 +6,7 @@ import { AsyncStatePhase } from '../../lib/asyncState'; ...@@ -6,6 +6,7 @@ import { AsyncStatePhase } from '../../lib/asyncState';
import { AddWebdavAccountMethod } from './methods/addWebdavAccount'; import { AddWebdavAccountMethod } from './methods/addWebdavAccount';
import { FollowMessageMethod } from './methods/followMessage'; import { FollowMessageMethod } from './methods/followMessage';
import { GetReadReceiptsMethod } from './methods/getReadReceipts'; import { GetReadReceiptsMethod } from './methods/getReadReceipts';
import { JoinRoomMethod } from './methods/joinRoom';
import { UnsubscribeMethod as MailerUnsubscribeMethod } from './methods/mailer/unsubscribe'; import { UnsubscribeMethod as MailerUnsubscribeMethod } from './methods/mailer/unsubscribe';
import { RoomNameExistsMethod } from './methods/roomNameExists'; import { RoomNameExistsMethod } from './methods/roomNameExists';
import { SaveRoomSettingsMethod } from './methods/saveRoomSettings'; import { SaveRoomSettingsMethod } from './methods/saveRoomSettings';
...@@ -80,6 +81,7 @@ export type ServerMethods = { ...@@ -80,6 +81,7 @@ export type ServerMethods = {
'instances/get': (...args: any[]) => any; 'instances/get': (...args: any[]) => any;
'jitsi:generateAccessToken': (...args: any[]) => any; 'jitsi:generateAccessToken': (...args: any[]) => any;
'jitsi:updateTimeout': (...args: any[]) => any; 'jitsi:updateTimeout': (...args: any[]) => any;
'joinRoom': JoinRoomMethod;
'leaveRoom': (...args: any[]) => any; 'leaveRoom': (...args: any[]) => any;
'license:getModules': () => string[]; 'license:getModules': () => string[];
'license:getTags': () => ILicenseTag[]; 'license:getTags': () => ILicenseTag[];
......
import type { IRoom } from '@rocket.chat/core-typings';
export type JoinRoomMethod = (rid: IRoom['_id'], code?: unknown) => void;
...@@ -166,7 +166,7 @@ const AppsWithData = ({ ...@@ -166,7 +166,7 @@ const AppsWithData = ({
const handleSubmit = useMutableCallback((e) => { const handleSubmit = useMutableCallback((e) => {
prevent(e); prevent(e);
closeTabBar(e); closeTabBar();
triggerSubmitView({ triggerSubmitView({
viewId, viewId,
appId, appId,
...@@ -182,7 +182,7 @@ const AppsWithData = ({ ...@@ -182,7 +182,7 @@ const AppsWithData = ({
const handleCancel = useMutableCallback((e) => { const handleCancel = useMutableCallback((e) => {
prevent(e); prevent(e);
closeTabBar(e); closeTabBar();
return triggerCancel({ return triggerCancel({
appId, appId,
viewId, viewId,
...@@ -196,7 +196,7 @@ const AppsWithData = ({ ...@@ -196,7 +196,7 @@ const AppsWithData = ({
const handleClose = useMutableCallback((e) => { const handleClose = useMutableCallback((e) => {
prevent(e); prevent(e);
closeTabBar(e); closeTabBar();
return triggerCancel({ return triggerCancel({
appId, appId,
viewId, viewId,
......
import { Box, Button, ButtonGroup, Icon, Modal } from '@rocket.chat/fuselage';
import React from 'react';
import { useTranslation } from '../../../../../../contexts/TranslationContext';
export const CallModal = ({ handleYes, handleCancel }) => {
const t = useTranslation();
return (
<Modal>
<Modal.Header>
<Modal.Title>{t('Video_Conference')}</Modal.Title>
<Modal.Close onClick={handleCancel} />
</Modal.Header>
<Modal.Content display='flex' flexDirection='column' alignItems='center'>
<Icon name='modal-warning' size='x128' color='warning-500' />
<Box fontScale='h4'>{t('Start_video_call')}</Box>
</Modal.Content>
<Modal.Footer>
<ButtonGroup align='end'>
<Button onClick={handleCancel}>{t('Cancel')}</Button>
<Button primary onClick={handleYes}>
{t('Yes')}
</Button>
</ButtonGroup>
</Modal.Footer>
</Modal>
);
};
export default CallModal;
...@@ -3,7 +3,6 @@ import React from 'react'; ...@@ -3,7 +3,6 @@ import React from 'react';
import VerticalBar from '../../../../../components/VerticalBar'; import VerticalBar from '../../../../../components/VerticalBar';
import CallJitsi from './CallJitsi'; import CallJitsi from './CallJitsi';
import CallModal from './components/CallModal';
export default { export default {
title: 'Room/Contextual Bar/CallJitsi', title: 'Room/Contextual Bar/CallJitsi',
...@@ -19,5 +18,3 @@ Default.storyName = 'CallJitsi'; ...@@ -19,5 +18,3 @@ Default.storyName = 'CallJitsi';
Default.args = { Default.args = {
openNewWindow: true, openNewWindow: true,
}; };
export const Modal: ComponentStory<typeof CallModal> = (args) => <CallModal {...args} />;
import { ISetting } from '@rocket.chat/core-typings';
import { Box } from '@rocket.chat/fuselage'; import { Box } from '@rocket.chat/fuselage';
import React from 'react'; import React, { ReactElement, ReactNode, RefObject } from 'react';
import VerticalBar from '../../../../../components/VerticalBar'; import VerticalBar from '../../../../../components/VerticalBar';
import { useTranslation } from '../../../../../contexts/TranslationContext'; import { useTranslation } from '../../../../../contexts/TranslationContext';
const CallJitsi = ({ handleClose, openNewWindow, refContent, children }) => { type CallJitsiProps = {
handleClose: () => void;
openNewWindow: ISetting['value'];
refContent: RefObject<HTMLDivElement>;
children: ReactNode;
};
const CallJitsi = ({ handleClose, openNewWindow, refContent, children }: CallJitsiProps): ReactElement => {
const t = useTranslation(); const t = useTranslation();
const content = openNewWindow ? ( const content = openNewWindow ? (
......
import { Skeleton } from '@rocket.chat/fuselage'; import { IRoom } from '@rocket.chat/core-typings';
import { Skeleton, Icon, Box } from '@rocket.chat/fuselage';
import { useMutableCallback, useSafely } from '@rocket.chat/fuselage-hooks'; import { useMutableCallback, useSafely } from '@rocket.chat/fuselage-hooks';
import { clear } from '@rocket.chat/memo'; import { clear } from '@rocket.chat/memo';
import React, { useRef, useEffect, useState, useMemo, useLayoutEffect, memo } from 'react'; import React, { useRef, useEffect, useState, useMemo, useLayoutEffect, memo, ReactElement } from 'react';
import { Subscriptions } from '../../../../../../app/models/client'; import { Subscriptions } from '../../../../../../app/models/client';
import { HEARTBEAT, TIMEOUT, DEBOUNCE } from '../../../../../../app/videobridge/constants'; import { HEARTBEAT, TIMEOUT, DEBOUNCE } from '../../../../../../app/videobridge/constants';
import GenericModal from '../../../../../components/GenericModal';
import { useConnectionStatus } from '../../../../../contexts/ConnectionStatusContext'; import { useConnectionStatus } from '../../../../../contexts/ConnectionStatusContext';
import { useSetModal } from '../../../../../contexts/ModalContext'; import { useSetModal } from '../../../../../contexts/ModalContext';
import { useMethod } from '../../../../../contexts/ServerContext'; import { useMethod } from '../../../../../contexts/ServerContext';
...@@ -15,11 +17,8 @@ import { useUser } from '../../../../../contexts/UserContext'; ...@@ -15,11 +17,8 @@ import { useUser } from '../../../../../contexts/UserContext';
import { useRoom } from '../../../contexts/RoomContext'; import { useRoom } from '../../../contexts/RoomContext';
import { useTabBarClose } from '../../../providers/ToolboxProvider'; import { useTabBarClose } from '../../../providers/ToolboxProvider';
import CallJitsi from './CallJitsi'; import CallJitsi from './CallJitsi';
import CallModal from './components/CallModal';
import { JitsiBridge } from './lib/JitsiBridge'; import { JitsiBridge } from './lib/JitsiBridge';
export { default as CallJitsi } from './CallJitsi';
const querySettings = { const querySettings = {
_id: [ _id: [
'Jitsi_Open_New_Window', 'Jitsi_Open_New_Window',
...@@ -34,12 +33,13 @@ const querySettings = { ...@@ -34,12 +33,13 @@ const querySettings = {
], ],
}; };
const CallJitsiWithData = ({ rid }) => { const CallJitsiWithData = ({ rid }: { rid: IRoom['_id'] }): ReactElement => {
const user = useUser(); const user = useUser();
const { connected } = useConnectionStatus(); const { connected } = useConnectionStatus();
const [accessToken, setAccessToken] = useSafely(useState()); const [accessToken, setAccessToken] = useSafely(useState());
const [accepted, setAccepted] = useState(false); const [accepted, setAccepted] = useState(false);
const room = useRoom(); const room = useRoom();
const ref = useRef<HTMLDivElement>(null);
const setModal = useSetModal(); const setModal = useSetModal();
const handleClose = useTabBarClose(); const handleClose = useTabBarClose();
const closeModal = useMutableCallback(() => setModal(null)); const closeModal = useMutableCallback(() => setModal(null));
...@@ -54,8 +54,6 @@ const CallJitsiWithData = ({ rid }) => { ...@@ -54,8 +54,6 @@ const CallJitsiWithData = ({ rid }) => {
handleClose(); handleClose();
}); });
const ref = useRef();
const { const {
Jitsi_Open_New_Window: openNewWindow, Jitsi_Open_New_Window: openNewWindow,
Jitsi_Domain: domain, Jitsi_Domain: domain,
...@@ -71,14 +69,16 @@ const CallJitsiWithData = ({ rid }) => { ...@@ -71,14 +69,16 @@ const CallJitsiWithData = ({ rid }) => {
useEffect(() => { useEffect(() => {
let ignore = false; let ignore = false;
if (!isEnabledTokenAuth) { if (!isEnabledTokenAuth) {
setAccessToken(); setAccessToken(undefined);
return; return;
} }
(async () => {
(async (): Promise<void> => {
const accessToken = await generateAccessToken(rid); const accessToken = await generateAccessToken(rid);
!ignore && setAccessToken(accessToken); !ignore && setAccessToken(accessToken);
})(); })();
return () => {
return (): void => {
ignore = true; ignore = true;
}; };
}, [generateAccessToken, isEnabledTokenAuth, rid, setAccessToken]); }, [generateAccessToken, isEnabledTokenAuth, rid, setAccessToken]);
...@@ -89,7 +89,7 @@ const CallJitsiWithData = ({ rid }) => { ...@@ -89,7 +89,7 @@ const CallJitsiWithData = ({ rid }) => {
} }
}, [connected, handleClose]); }, [connected, handleClose]);
const rname = useHashName ? uniqueID + rid : encodeURIComponent(room.t === 'd' ? room.usernames.join(' x ') : room.name); const rname = useHashName ? uniqueID + rid : encodeURIComponent((room?.t === 'd' ? room.usernames?.join('x') : room.name) ?? '');
const jitsi = useMemo(() => { const jitsi = useMemo(() => {
if (isEnabledTokenAuth && !accessToken) { if (isEnabledTokenAuth && !accessToken) {
...@@ -106,7 +106,7 @@ const CallJitsiWithData = ({ rid }) => { ...@@ -106,7 +106,7 @@ const CallJitsiWithData = ({ rid }) => {
jitsiRoomName, jitsiRoomName,
accessToken, accessToken,
desktopSharingChromeExtId, desktopSharingChromeExtId,
name: user.name || user.username, name: user?.name || user?.username,
}, },
HEARTBEAT, HEARTBEAT,
); );
...@@ -120,36 +120,38 @@ const CallJitsiWithData = ({ rid }) => { ...@@ -120,36 +120,38 @@ const CallJitsiWithData = ({ rid }) => {
rname, rname,
ssl, ssl,
sufix, sufix,
user.name, user?.name,
user.username, user?.username,
]); ]);
const testAndHandleTimeout = useMutableCallback(() => { const testAndHandleTimeout = useMutableCallback(() => {
if (jitsi.openNewWindow) { if (jitsi?.openNewWindow) {
if (jitsi.window?.closed) { if (jitsi?.window?.closed) {
return jitsi.dispose(); return jitsi.dispose();
} }
try { try {
return updateTimeout(rid, false); return updateTimeout(rid, false);
} catch (error) { } catch (error) {
dispatchToastMessage({ type: 'error', message: t(error.reason) }); dispatchToastMessage({ type: 'error', message: t(error.reason) });
clear(); clear(() => undefined);
handleClose(); handleClose();
return jitsi.dispose(); return jitsi.dispose();
} }
} }
if (new Date() - new Date(room.jitsiTimeout) > TIMEOUT) {
return jitsi.dispose(); if (new Date().valueOf() - new Date(room.jitsiTimeout ?? '').valueOf() > TIMEOUT) {
return jitsi?.dispose();
} }
if (new Date() - new Date(room.jitsiTimeout) + TIMEOUT > DEBOUNCE) { if (new Date().valueOf() - new Date(room.jitsiTimeout ?? '').valueOf() + TIMEOUT > DEBOUNCE) {
try { try {
return updateTimeout(rid, false); return updateTimeout(rid, false);
} catch (error) { } catch (error) {
dispatchToastMessage({ type: 'error', message: t(error.reason) }); dispatchToastMessage({ type: 'error', message: t(error.reason) });
clear(); clear(() => undefined);
handleClose(); handleClose();
return jitsi.dispose(); return jitsi?.dispose();
} }
} }
}); });
...@@ -159,7 +161,7 @@ const CallJitsiWithData = ({ rid }) => { ...@@ -159,7 +161,7 @@ const CallJitsiWithData = ({ rid }) => {
return; return;
} }
const clear = () => { const clear = (): void => {
jitsi.off('HEARTBEAT', testAndHandleTimeout); jitsi.off('HEARTBEAT', testAndHandleTimeout);
jitsi.dispose(); jitsi.dispose();
}; };
...@@ -178,18 +180,18 @@ const CallJitsiWithData = ({ rid }) => { ...@@ -178,18 +180,18 @@ const CallJitsiWithData = ({ rid }) => {
} }
jitsi.on('HEARTBEAT', testAndHandleTimeout); jitsi.on('HEARTBEAT', testAndHandleTimeout);
return () => { return (): void => {
if (!jitsi.openNewWindow) clear(); if (!jitsi.openNewWindow) clear();
}; };
}, [accepted, jitsi, rid, testAndHandleTimeout, updateTimeout, dispatchToastMessage, handleClose, t]); }, [accepted, jitsi, rid, testAndHandleTimeout, updateTimeout, dispatchToastMessage, handleClose, t]);
const handleYes = useMutableCallback(() => { const handleConfirm = useMutableCallback(() => {
if (jitsi) { if (jitsi) {
jitsi.needsStart = true; jitsi.needsStart = true;
} }
setAccepted(true); setAccepted(true);
const sub = Subscriptions.findOne({ rid, 'u._id': user._id }); const sub = Subscriptions.findOne({ rid, 'u._id': user?._id });
if (!sub) { if (!sub) {
joinRoom(rid); joinRoom(rid);
} }
...@@ -201,11 +203,25 @@ const CallJitsiWithData = ({ rid }) => { ...@@ -201,11 +203,25 @@ const CallJitsiWithData = ({ rid }) => {
useLayoutEffect(() => { useLayoutEffect(() => {
if (!accepted) { if (!accepted) {
setModal(() => <CallModal handleYes={handleYes} handleCancel={handleCancel} />); return setModal(() => (
return; <GenericModal
variant='warning'
title={t('Video_Conference')}
confirmText={t('Yes')}
onClose={handleCancel}
onCancel={handleCancel}
onConfirm={handleConfirm}
>
<Box display='flex' flexDirection='column' alignItems='center'>
<Icon name='modal-warning' size='x128' color='warning-500' />
<Box fontScale='h4'>{t('Start_video_call')}</Box>
</Box>
</GenericModal>
));
} }
closeModal(); closeModal();
}, [accepted, closeModal, handleCancel, handleYes, setModal]); }, [accepted, closeModal, handleCancel, handleConfirm, setModal, t]);
return ( return (
<CallJitsi handleClose={handleClose} openNewWindow={openNewWindow} refContent={ref}> <CallJitsi handleClose={handleClose} openNewWindow={openNewWindow} refContent={ref}>
......
import { IRoom } from '@rocket.chat/core-typings'; import { IRoom } from '@rocket.chat/core-typings';
import { EventHandlerOf } from '@rocket.chat/emitter'; import { EventHandlerOf } from '@rocket.chat/emitter';
import { createContext, MouseEventHandler, useContext } from 'react'; import { createContext, useContext } from 'react';
import { actions, listen, ToolboxActionConfig, ToolboxAction, Events } from '.'; import { actions, listen, ToolboxActionConfig, ToolboxAction, Events } from '.';
import './defaultActions'; import './defaultActions';
...@@ -14,7 +14,7 @@ export type ToolboxContextValue = { ...@@ -14,7 +14,7 @@ export type ToolboxContextValue = {
context?: any; context?: any;
open: Function; open: Function;
openUserInfo: (username: string) => void; openUserInfo: (username: string) => void;
close: MouseEventHandler<HTMLOrSVGElement>; close: () => void;
activeTabBar?: ToolboxActionConfig; activeTabBar?: ToolboxActionConfig;
}; };
......
import type { IRoom } from '@rocket.chat/core-typings'; import type { IRoom } from '@rocket.chat/core-typings';
import { useDebouncedState, useMutableCallback, useSafely } from '@rocket.chat/fuselage-hooks'; import { useDebouncedState, useMutableCallback, useSafely } from '@rocket.chat/fuselage-hooks';
import React, { ReactNode, useContext, useMemo, useState, useLayoutEffect, MouseEventHandler, useEffect } from 'react'; import React, { ReactNode, useContext, useMemo, useState, useLayoutEffect, useEffect } from 'react';
import { useCurrentRoute, useRoute } from '../../../contexts/RouterContext'; import { useCurrentRoute, useRoute } from '../../../contexts/RouterContext';
import { useSession } from '../../../contexts/SessionContext'; import { useSession } from '../../../contexts/SessionContext';
...@@ -125,7 +125,7 @@ const ToolboxProvider = ({ children, room }: { children: ReactNode; room: IRoom ...@@ -125,7 +125,7 @@ const ToolboxProvider = ({ children, room }: { children: ReactNode; room: IRoom
export const useTabContext = (): unknown | undefined => useContext(ToolboxContext).context; export const useTabContext = (): unknown | undefined => useContext(ToolboxContext).context;
export const useTab = (): ToolboxActionConfig | undefined => useContext(ToolboxContext).activeTabBar; export const useTab = (): ToolboxActionConfig | undefined => useContext(ToolboxContext).activeTabBar;
export const useTabBarOpen = (): Function => useContext(ToolboxContext).open; export const useTabBarOpen = (): Function => useContext(ToolboxContext).open;
export const useTabBarClose = (): MouseEventHandler<HTMLOrSVGElement> => useContext(ToolboxContext).close; export const useTabBarClose = (): (() => void) => useContext(ToolboxContext).close;
export const useTabBarOpenUserInfo = (): Function => useContext(ToolboxContext).openUserInfo; export const useTabBarOpenUserInfo = (): Function => useContext(ToolboxContext).openUserInfo;
export default ToolboxProvider; export default ToolboxProvider;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment