Skip to content

Commit

Permalink
[Fix/#457]: Invite link appearance fixed/Copy to clipboard button add…
Browse files Browse the repository at this point in the history
…ed/Improvements in the slash command panel UI/Bug-fixes (#475)

* copy-button/styles-improve

* conditional-render

* command-panel/improv

* slash-commands/improv

* fix/lint-errors

* handle-errors

* format-fixes

---------

Co-authored-by: Sidharth Mohanty <[email protected]>
  • Loading branch information
umangutkarsh and sidmohanty11 authored Mar 9, 2024
1 parent da9a856 commit b147288
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 75 deletions.
83 changes: 69 additions & 14 deletions packages/react/src/components/CommandList/CommandsList.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import React from 'react';
import PropTypes from 'prop-types';
import React, { useEffect } from 'react';
import { css } from '@emotion/react';
import PropTypes from 'prop-types';
import { Box } from '../Box';
import useComponentOverrides from '../../theme/useComponentOverrides';

Expand All @@ -15,33 +15,88 @@ function CommandsList({
...props
}) {
const { classNames, styleOverrides } = useComponentOverrides('CommandsList');
const classNameCommandsList = css`

const listStyle = css`
margin-bottom: 5px;
display: block;
max-height: 10rem;
overflow: scroll;
overflow-x: hidden;
max-height: 145px;
scrollbar-width: thin;
scrollbar-color: #e0e0e1 transparent;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background-color: #e0e0e1;
border-radius: 4px;
}
&::-webkit-scrollbar-thumb:hover {
background-color: #e0e0e1;
}
&::-webkit-scrollbar-track {
background-color: transparent;
}
`;

const listItemStyle = css`
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 0;
padding-right: 2px;
&:hover {
background-color: #dddddd;
}
`;

const handleCommandClick = (command) => {
if (execCommand) {
execCommand(command);
}
if (onCommandClick) {
onCommandClick(command);
}
};

useEffect(() => {
const handleKeyPress = (event) => {
if (event.key === 'Enter') {
const selectedItem = filteredCommands[0];
handleCommandClick(selectedItem);
}
};

document.addEventListener('keydown', handleKeyPress);

return () => {
document.removeEventListener('keydown', handleKeyPress);
};
}, [filteredCommands, handleCommandClick]);

return (
<Box
css={classNameCommandsList}
css={listStyle}
className={`ec-commands-list ${className} ${classNames}`}
style={{ ...styleOverrides, ...style }}
{...props}
>
<ul style={{ listStyle: 'none' }}>
{filteredCommands.map((command) => (
<li
style={{ cursor: 'pointer' }}
onClick={() => {
if (execCommand) {
execCommand(command);
}
if (onCommandClick) {
onCommandClick(command);
}
}}
key={command.command}
css={listItemStyle}
onClick={() => handleCommandClick(command)}
>
{command.command}
<span style={{ justifyContent: 'space-evenly' }}>
<span style={{ color: '#000000' }}>{command.command}</span>
&nbsp;&nbsp;&nbsp;
<span>{command.params}</span>
</span>
<span>{command.description}</span>
</li>
))}
</ul>
Expand Down
14 changes: 14 additions & 0 deletions packages/react/src/components/Icon/icons/Copy.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/react/src/components/Icon/icons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import ArrowDown from './ArrowDown';
import PinFilled from './PinFilled';
import VideoRecorder from './VideoRecoder';
import DisabledRecorder from './DisableRecorder';
import Copy from './Copy';
import Clipboard from './Clipboard';
import Download from './Download';
import At from './At';
Expand All @@ -53,6 +54,7 @@ const icons = {
hash: Hash,
computer: Computer,
cross: Cross,
copy: Copy,
mic: Mic,
'video-recorder': VideoRecorder,
'disabled-recorder': DisabledRecorder,
Expand Down
42 changes: 31 additions & 11 deletions packages/react/src/components/RoomMembers/RoomMember.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useState } from 'react';
import React, { useContext, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import RoomMemberItem from './RoomMemberItem';
import classes from './RoomMember.module.css';
Expand All @@ -20,6 +20,24 @@ const RoomMembers = ({ members }) => {
const toggleInviteView = useInviteStore((state) => state.toggleInviteView);
const showInvite = useInviteStore((state) => state.showInvite);

const [userInfo, setUserInfo] = useState(null);

useEffect(() => {
const getUserInfo = async () => {
try {
const res = await RCInstance.me();
setUserInfo(res);
} catch (error) {
console.error('Error fetching user info:', error);
}
};

getUserInfo();
}, [RCInstance]);

const roles = userInfo && userInfo.roles ? userInfo.roles : [];
const isAdmin = roles.includes('admin');

const [inviteData, setInviteData] = useState(null);

if (showInvite) return <InviteMembers inviteData={inviteData} />;
Expand All @@ -44,16 +62,18 @@ const RoomMembers = ({ members }) => {
<RoomMemberItem user={member} host={host} key={member._id} />
))}
</Box>
<Button
style={{ marginTop: '10px', width: '100%' }}
onClick={async () => {
const res = await RCInstance.findOrCreateInvite();
setInviteData(res);
toggleInviteView();
}}
>
<Icon size="1em" name="link" /> Invite Link
</Button>
{isAdmin && (
<Button
style={{ marginTop: '10px', width: '100%' }}
onClick={async () => {
const res = await RCInstance.findOrCreateInvite();
setInviteData(res);
toggleInviteView();
}}
>
<Icon size="1em" name="link" /> Invite Link
</Button>
)}
</Box>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,47 @@
import React, { useState } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { css } from '@emotion/react';
import classes from '../RoomMember.module.css';
import useInviteStore from '../../../store/inviteStore';
import { useToastBarDispatch } from '../../../hooks/useToastBarDispatch';
import { Box } from '../../Box';
import { Icon } from '../../Icon';
import { Input } from '../../Input';
import { ActionButton } from '../../ActionButton';

const InviteMembers = ({ inviteData }) => {
const toggleInviteView = useInviteStore((state) => state.toggleInviteView);
const [isCopied, setIsCopied] = useState(false);
const copyToClipboard = (url) => {
navigator.clipboard.writeText(url);
setIsCopied(true);
const dispatchToastMessage = useToastBarDispatch();

const copyToClipboard = () => {
if (inviteData && inviteData.url) {
navigator.clipboard
.writeText(inviteData.url)
.then(() => {
dispatchToastMessage({
type: 'success',
message: 'Copied to clipboard',
});
})
.catch((error) => {
console.error('Error copying to clipboard:', error);
});
}
};

return (
<Box style={{ padding: '16px' }} className={classes.modal}>
<Box
css={css`
display: flex;
margin-bottom: 20px;
`}
>
<h3 style={{ display: 'contents' }}>
<Box style={{ paddingRight: '20px' }}>
<ActionButton onClick={() => toggleInviteView()} ghost size="small">
<Icon name="back" size="1.25rem" />
</ActionButton>
</Box>
<Icon
name="link"
size="1.25rem"
style={{ padding: '0px 20px 20px 0px' }}
/>
<Box
css={css`
width: 80%;
Expand All @@ -38,57 +50,56 @@ const InviteMembers = ({ inviteData }) => {
>
Invite Members
</Box>
<ActionButton onClick={() => toggleInviteView()} ghost size="small">
<Icon name="back" size="1.25rem" />
</ActionButton>
</h3>
</Box>
<Box
css={css`
width: 100%;
display: flex;
flex-direction: column;
margin-bottom: 5px;
`}
>
<Box style={{ marginBottom: '5px', alignSelf: 'start' }}>
<span>Invite Link</span>
</Box>
{inviteData && (
<Box
css={css`
display: block;
position: relative;
align-items: center;
width: 100%;
display: flex;
flex-direction: column;
`}
>
<Input
readOnly
value={inviteData.url}
<Box
css={css`
width: 100%;
padding: 10px;
padding-right: 40px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
`}
/>
<ActionButton
onClick={() => copyToClipboard(inviteData.url)}
ghost
size="small"
>
<span>
<b>Invite Link</b>
</span>
<ActionButton onClick={copyToClipboard} ghost size="small">
<Icon name="copy" size="1.25rem" />
</ActionButton>
</Box>
<Input readOnly value={inviteData.url} />
</Box>
)}
<div
css={css`
margin-top: 8px;
`}
>
{inviteData && (
<p
css={css`
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
padding: 0;
color: #9ea2a8;
font-size: 0.78em;
`}
>
<Icon name={isCopied ? 'check' : 'clipboard'} size="1.25rem" />
</ActionButton>
</Box>
</Box>
<span style={{ color: 'grey', fontSize: '13px', fontWeight: '800' }}>
Your invite link will expire on{' '}
{new Date(inviteData.expires).toString().split('GMT')[0]}
</span>
<b>
Your invite link will expire on{' '}
{new Date(inviteData.expires).toString().split('GMT')[0]}
</b>
</p>
)}
</div>
</Box>
);
};
Expand Down

0 comments on commit b147288

Please sign in to comment.