Skip to content
This repository has been archived by the owner on Jun 30, 2022. It is now read-only.

Commit

Permalink
Improve overall codebase
Browse files Browse the repository at this point in the history
- Define an enum like structure for call statuses
- Fix formatting and spelling issues
- General refactoring
  • Loading branch information
murtaza98 committed Nov 16, 2021
1 parent 2d2ca32 commit 2150c96
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 75 deletions.
3 changes: 2 additions & 1 deletion src/components/Calls/CallIFrame.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { h } from 'preact';
import { Livechat } from '../../api';
import store from '../../store';
import { createClassName } from '../helpers';
import { CallStatus } from './constants';
import styles from './styles.scss';


Expand All @@ -17,7 +18,7 @@ export const CallIframe = () => {
);
return store.setState({
incomingCallAlert: { ...incomingCallAlert, show: false },
ongoingCall: { ...ongoingCall, callStatus: 'ongoingCallInNewTab' },
ongoingCall: { ...ongoingCall, callStatus: CallStatus.ON_GOING_CALL_IN_NEW_TAB },
});
};
return (
Expand Down
49 changes: 26 additions & 23 deletions src/components/Calls/CallNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import store from '../../store';
import { Avatar } from '../Avatar';
import { Button } from '../Button';
import { createClassName, getAvatarUrl, isMobileDevice } from '../helpers';
import { CallStatus } from './constants';
import styles from './styles.scss';


export const CallNotification = ({ callProvider, callerUsername, url, dispatch, time, rid, callId } = { callProvider: undefined, callerUsername: undefined, dispatch: undefined, time: undefined, url: undefined }) => {
const [show, setShow] = useState(true);

const callInNewTab = async () => {
const { token, room } = store.state;
const url = `${ Livechat.client.host }/meet/${ room._id }?token=${ token }`;
await dispatch({ ongoingCall: { callStatus: 'ongoingCallInNewTab', time: { time } }, incomingCallAlert: { show: false, callProvider } });
const { token } = store.state;
const url = `${ Livechat.client.host }/meet/${ rid }?token=${ token }`;
await dispatch({ ongoingCall: { callStatus: CallStatus.ON_GOING_CALL_IN_NEW_TAB, time: { time } }, incomingCallAlert: { show: false, callProvider } });
window.open(url, rid);
};

Expand All @@ -28,16 +29,16 @@ export const CallNotification = ({ callProvider, callerUsername, url, dispatch,
switch (callProvider) {
case constants.jitsiCallStartedMessageType: {
window.open(url, rid);
await dispatch({ incomingCallAlert: { show: false, url, callProvider }, ongoingCall: { callStatus: 'accept', time: { time } } });
await dispatch({ incomingCallAlert: { show: false, url, callProvider }, ongoingCall: { callStatus: CallStatus.ACCEPT, time: { time } } });
break;
}
case constants.webrtcCallStartedMessageType: {
await Livechat.updateCallStatus('inProgress', rid, callId);
await Livechat.updateCallStatus(CallStatus.INPROGRESS, rid, callId);
if (isMobileDevice()) {
callInNewTab();
break;
}
await dispatch({ ongoingCall: { callStatus: 'accept', time: { time } } });
await dispatch({ ongoingCall: { callStatus: CallStatus.ACCEPT, time: { time } } });
break;
}
}
Expand All @@ -46,34 +47,36 @@ export const CallNotification = ({ callProvider, callerUsername, url, dispatch,
const declineClick = async () => {
await Livechat.updateCallStatus('declined', rid, callId);
await Livechat.notifyCallDeclined(rid);
await dispatch({ incomingCallAlert: null, ongoingCall: { callStatus: 'declined', time: { time } } });
await dispatch({ incomingCallAlert: null, ongoingCall: { callStatus: CallStatus.DECLINED, time: { time } } });
};

return (
<div className={createClassName(styles, 'call-notification')}>
{ show
? (
<div className={createClassName(styles, 'call-notification__content')}>
<div className={createClassName(styles, 'call-notification__content-avatar')}>
<Avatar
src={getAvatarUrl(callerUsername)}
large
/>
{
show && (
<div className = { createClassName(styles, 'call-notification__content') }>
<div className = { createClassName(styles, 'call-notification__content-avatar') }>
<Avatar src = { getAvatarUrl(callerUsername) } large />
</div>
<div className={createClassName(styles, 'call-notification__content-message')}>
<div className = { createClassName(styles, 'call-notification__content-message') }>
{ I18n.t('Incoming video Call') }
</div>
<div className={createClassName(styles, 'call-notification__content-actions')}>
<Button onClick={declineClick} className={createClassName(styles, 'call-notification__content-actions-decline')}>
<PhoneDecline width={20} height={20} /> <span style='margin-left:5px'> {I18n.t('Decline')} </span>
<div className = { createClassName(styles, 'call-notification__content-actions') }>
<Button
onClick = { declineClick }
className = { createClassName(styles, 'call-notification__content-actions-decline') }>
<PhoneDecline width = { 20 } height = { 20 } />
<span style='margin-left:5px'> {I18n.t('Decline')} </span >
</Button>
<Button onClick={acceptClick} className={createClassName(styles, 'call-notification__content-actions-accept')} >
<PhoneAccept width={20} height={20} /><span style='margin-left:5px'> {I18n.t('Accept')} </span>
<Button onClick = { acceptClick }
className = {createClassName(styles, 'call-notification__content-actions-accept') }>
<PhoneAccept width = { 20 } height = { 20} />
<span style='margin-left:5px'> {I18n.t('Accept')} </span >
</Button>
</div>
</div>
)
: null
}
</div>);
</div>
);
};
30 changes: 19 additions & 11 deletions src/components/Calls/JoinCallButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import constants from '../../lib/constants';
import store from '../../store';
import { Button } from '../Button';
import { createClassName } from '../helpers';
import { CallStatus } from './constants';
import styles from './styles.scss';


Expand All @@ -19,22 +20,29 @@ export const JoinCallButton = (props) => {
window.open(props.url, room._id);
break;
}
case constants.webrtcCallStartedMessageType: {
case constants.webRTCCallStartedMessageType: {
window.open(`${ Livechat.client.host }/meet/${ room._id }?token=${ token }`, room._id);
break;
}
}
};
return (<div>
{ props.callStatus === 'accept' || props.callStatus === 'ongoingCallInNewTab'
? <div className={createClassName(styles, 'joinCall')}>
<div className={createClassName(styles, 'joinCall__content')} >
<div className={createClassName(styles, 'joinCall__content-videoIcon')} >
<VideoIcon width={20} height={20} />
return (
<div className={createClassName(styles, 'joinCall')}>
{
(props.callStatus === CallStatus.ACCEPT || props.callStatus === CallStatus.ON_GOING_CALL_IN_NEW_TAB)
&& (
<div className={createClassName(styles, 'joinCall__content')} >
<div className={createClassName(styles, 'joinCall__content-videoIcon')} >
<VideoIcon width={20} height={20} />
</div>
{ I18n.t('Join my room to start the video call') }
<Button onClick={clickJoinCall} className={createClassName(styles, 'joinCall__content-action')}>
<VideoIcon width={20} height={20} />
{I18n.t('Join Call')}
</Button>
</div>
{I18n.t('Join my room to start the video call')}
</div>
<Button onClick={clickJoinCall} className={createClassName(styles, 'joinCall__content-action')}> <VideoIcon width={20} height={20} /> {I18n.t('Join Call')} </Button>
</div> : null } </div>
)
}
</div>
);
};
8 changes: 8 additions & 0 deletions src/components/Calls/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const CallStatus = {
ACCEPT: 'accept',
DECLINED: 'declined',
RINGING: 'ringing',
INPROGRESS: 'inProgress',
ON_GOING_CALL_IN_NEW_TAB: 'ongoingCallInNewTab',
ENDED: 'ended',
};
2 changes: 1 addition & 1 deletion src/components/Messages/MessageList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export class MessageList extends MemoizedComponent {
const { incomingCallAlert } = store.state;
const { ongoingCall } = store.state;

if ((message.t === constants.webrtcCallStartedMessageType || message.t === constants.jitsiCallStartedMessageType) && message.actionLinks && message.actionLinks.length > 0 && ongoingCall) {
if ((message.t === constants.webRTCCallStartedMessageType || message.t === constants.jitsiCallStartedMessageType) && message.actionLinks && message.actionLinks.length && ongoingCall) {
const { url, callProvider, rid } = incomingCallAlert || {};
items.push(
<JoinCallButton callStatus={ongoingCall.callStatus} url={url} callProvider={callProvider} rid={rid} />,
Expand Down
11 changes: 2 additions & 9 deletions src/components/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,6 @@ export const parseOfflineMessage = (fields = {}) => {
};
export const normalizeDOMRect = ({ left, top, right, bottom }) => ({ left, top, right, bottom });


export const isMobileDevice = () => {
if (window.innerWidth <= 800 && window.innerHeight >= 630) {
return true;
}
return false;
};


export const visibility = (() => {
if (typeof document.hidden !== 'undefined') {
return {
Expand Down Expand Up @@ -253,3 +244,5 @@ export const isActiveSession = () => {

return sessionId === firstSessionId;
};

export const isMobileDevice = () => window.innerWidth <= 800 && window.innerHeight >= 630;
2 changes: 1 addition & 1 deletion src/lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ export default {
livechatConnectedAlertId: 'LIVECHAT_CONNECTED',
livechatDisconnectedAlertId: 'LIVECHAT_DISCONNECTED',
livechatQueueMessageId: 'LIVECHAT_QUEUE_MESSAGE',
webrtcCallStartedMessageType: 'livechat_webrtc_video_call',
webRTCCallStartedMessageType: 'livechat_webrtc_video_call',
jitsiCallStartedMessageType: 'jitsi_call_started',
};
64 changes: 36 additions & 28 deletions src/lib/room.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { route } from 'preact-router';

import { Livechat } from '../api';
import { CallStatus } from '../components/Calls/constants';
import { setCookies, upsert, canRenderMessage, createToken } from '../components/helpers';
import I18n from '../i18n';
import { store } from '../store';
Expand All @@ -26,23 +27,24 @@ export const closeChat = async ({ transcriptRequested } = {}) => {
};

// TODO: use a separate event to listen to call start event. Listening on the message type isn't a good solution
export const processCallMessage = async (message) => {
export const processIncomingCallMessage = async (message) => {
const { alerts } = store.state;
try {
await store.setState({ incomingCallAlert: {
show: true,
callProvider: message.t,
callerUsername: message.u.username,
rid: message.rid,
time: message.ts,
callId: message._id,
url: message.t === constants.jitsiCallStartedMessageType ? message.customFields.jitsiCallUrl : '',
},
ongoingCall: {
callStatus: 'ring',
time: message.ts,
} },
);
await store.setState({
incomingCallAlert: {
show: true,
callProvider: message.t,
callerUsername: message.u.username,
rid: message.rid,
time: message.ts,
callId: message._id,
url: message.t === constants.jitsiCallStartedMessageType ? message.customFields.jitsiCallUrl : '',
},
ongoingCall: {
callStatus: CallStatus.RINGING,
time: message.ts,
},
});
} catch (err) {
console.error(err);
const alert = { id: createToken(), children: I18n.t('error_getting_call_alert'), error: true, timeout: 5000 };
Expand All @@ -56,9 +58,9 @@ const processMessage = async (message) => {
} else if (message.t === 'command') {
commands[message.msg] && commands[message.msg]();
} else if (message.endTs) {
await store.setState({ ongoingCall: { callStatus: 'ended', time: message.ts }, incomingCallAlert: null });
} else if (message.t === constants.webrtcCallStartedMessageType || message.t === constants.jitsiCallStartedMessageType) {
await processCallMessage(message);
await store.setState({ ongoingCall: { callStatus: CallStatus.ENDED, time: message.ts }, incomingCallAlert: null });
} else if (message.t === constants.webRTCCallStartedMessageType || message.t === constants.jitsiCallStartedMessageType) {
await processIncomingCallMessage(message);
}
};

Expand Down Expand Up @@ -184,7 +186,7 @@ Livechat.onMessage(async (message) => {
});

export const getGreetingMessages = (messages) => messages && messages.filter((msg) => msg.trigger);
export const getLatestCallMessage = (messages) => messages && messages.filter((msg) => msg.t === constants.webrtcCallStartedMessageType || msg.t === constants.jitsiCallStartedMessageType).pop();
export const getLatestCallMessage = (messages) => messages && messages.filter((msg) => msg.t === constants.webRTCCallStartedMessageType || msg.t === constants.jitsiCallStartedMessageType).pop();

export const loadMessages = async () => {
const { ongoingCall } = store.state;
Expand All @@ -207,20 +209,26 @@ export const loadMessages = async () => {
await store.setState({ lastReadMessageId: lastMessage && lastMessage._id });
}

if (ongoingCall && (ongoingCall.callStatus === 'accept' || ongoingCall.callStatus === 'ongoingCallInNewTab')) {
if (ongoingCall && (ongoingCall.callStatus === CallStatus.ACCEPT || ongoingCall.callStatus === CallStatus.ON_GOING_CALL_IN_NEW_TAB)) {
return;
}

const latestCallMessage = getLatestCallMessage(messages);
if (latestCallMessage && latestCallMessage.t === constants.jitsiCallStartedMessageType) {
store.setState({ ongoingCall: { callStatus: 'ongoingCallInNewTab', time: latestCallMessage.ts }, incomingCallAlert: { show: false, callProvider: latestCallMessage.t, url: latestCallMessage.customFields.jitsiCallUrl } });
} else if (callStatus === 'inProgress') {
if (!latestCallMessage) {
return;
if (!latestCallMessage) {
return;
}
if (latestCallMessage.t === constants.jitsiCallStartedMessageType) {
await store.setState({ ongoingCall: { callStatus: CallStatus.ON_GOING_CALL_IN_NEW_TAB, time: latestCallMessage.ts }, incomingCallAlert: { show: false, callProvider: latestCallMessage.t, url: latestCallMessage.customFields.jitsiCallUrl } });
return;
}
switch (callStatus) {
case CallStatus.INPROGRESS: {
await store.setState({ ongoingCall: { callStatus: CallStatus.ON_GOING_CALL_IN_NEW_TAB, time: latestCallMessage.ts }, incomingCallAlert: { show: false, callProvider: latestCallMessage.t } });
break;
}
case CallStatus.RINGING: {
processIncomingCallMessage(latestCallMessage);
}
store.setState({ ongoingCall: { callStatus: 'ongoingCallInNewTab', time: latestCallMessage.ts }, incomingCallAlert: { show: false, callProvider: latestCallMessage.t } });
} else if (callStatus === 'ringing') {
processCallMessage(latestCallMessage);
}
};

Expand Down
3 changes: 2 additions & 1 deletion src/routes/Chat/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { h, Component } from 'preact';
import { Button } from '../../components/Button';
import { CallIframe } from '../../components/Calls/CallIFrame';
import { CallNotification } from '../../components/Calls/CallNotification';
import { CallStatus } from '../../components/Calls/constants';
import { Composer, ComposerAction, ComposerActions } from '../../components/Composer';
import { FilesDropTarget } from '../../components/FilesDropTarget';
import { FooterOptions, CharCounter } from '../../components/Footer';
Expand Down Expand Up @@ -150,7 +151,7 @@ export default class Chat extends Component {
>
<Screen.Content nopadding>
{ incomingCallAlert && !!incomingCallAlert.show && <CallNotification { ...incomingCallAlert } dispatch={dispatch} />}
{ incomingCallAlert?.show && ongoingCall && ongoingCall.callStatus === 'accept' ? <CallIframe { ...incomingCallAlert } /> : null }
{ incomingCallAlert?.show && ongoingCall && ongoingCall.callStatus === CallStatus.ACCEPT ? <CallIframe { ...incomingCallAlert } /> : null }
<div className={createClassName(styles, 'chat__messages', { atBottom, loading })}>
<MessageList
ref={this.handleMessagesContainerRef}
Expand Down

0 comments on commit 2150c96

Please sign in to comment.