diff --git a/CHANGELOG.md b/CHANGELOG.md index dec53b4fbd..0c03027071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,4 +8,6 @@ * Fixed bug with displaying incorrect default settings tab. -* Fixed LoadingPanel useEffect bug. \ No newline at end of file +* Labels for unregistered and duplicate usernames with modals + +* Fixed LoadingPanel useEffect bug. diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after launch-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after launch-actual.png index 9c735a75ac..50419601d9 100644 Binary files a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after launch-actual.png and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after launch-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after pagedown-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after pagedown-actual.png new file mode 100644 index 0000000000..dcdd8c05eb Binary files /dev/null and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after pagedown-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after pageup-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after pageup-actual.png new file mode 100644 index 0000000000..63b66019c1 Binary files /dev/null and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/after pageup-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/message input words wrapping-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/message input words wrapping-actual.png new file mode 100644 index 0000000000..39d774aa67 Binary files /dev/null and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/message input words wrapping-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/message input words wrapping-base.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/message input words wrapping-base.png deleted file mode 100644 index 199d3f83f1..0000000000 Binary files a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/message input words wrapping-base.png and /dev/null differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the middle-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the middle-actual.png index 48450c36cf..0b09d07052 100644 Binary files a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the middle-actual.png and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the middle-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the top-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the top-actual.png index 31e4da3488..80033ad5d9 100644 Binary files a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the top-actual.png and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the top-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after enter-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after enter-actual.png index 56108c2069..5022f8c990 100644 Binary files a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after enter-actual.png and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after enter-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after scroll-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after scroll-actual.png index 0e680505d2..e10e5ac55e 100644 Binary files a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after scroll-actual.png and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after scroll-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after top scroll-actual.png b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after top scroll-actual.png index 80ddbec3cd..eed4002d68 100644 Binary files a/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after top scroll-actual.png and b/packages/desktop/cypress/snapshots/base-local/src/renderer/components/Channel/Channel.regression.cy.tsx/send after top scroll-actual.png differ diff --git a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after launch-base.png b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after launch-base.png index 39a4223081..230d7043d8 100644 Binary files a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after launch-base.png and b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after launch-base.png differ diff --git a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after pagedown-base.png b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after pagedown-base.png index 36ff3978cb..d025ced0d6 100644 Binary files a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after pagedown-base.png and b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after pagedown-base.png differ diff --git a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after pageup-base.png b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after pageup-base.png index d60225e424..a0e8ab49ca 100644 Binary files a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after pageup-base.png and b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/after pageup-base.png differ diff --git a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the middle-base.png b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the middle-base.png index ce986ee567..3f9754f1c7 100644 Binary files a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the middle-base.png and b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the middle-base.png differ diff --git a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the top-base.png b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the top-base.png index 5abdb9e498..e3aa07216c 100644 Binary files a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the top-base.png and b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/scroll to the top-base.png differ diff --git a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after enter-base.png b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after enter-base.png index feafae5789..197bbb0b94 100644 Binary files a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after enter-base.png and b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after enter-base.png differ diff --git a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after scroll-base.png b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after scroll-base.png index b0c2ee2b81..a9fde74be7 100644 Binary files a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after scroll-base.png and b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after scroll-base.png differ diff --git a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after top scroll-base.png b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after top scroll-base.png index b65083c721..df0b76c7ae 100644 Binary files a/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after top scroll-base.png and b/packages/desktop/cypress/snapshots/base/src/renderer/components/Channel/Channel.regression.cy.tsx/send after top scroll-base.png differ diff --git a/packages/desktop/src/renderer/Root.tsx b/packages/desktop/src/renderer/Root.tsx index 913bf1db54..8717893233 100644 --- a/packages/desktop/src/renderer/Root.tsx +++ b/packages/desktop/src/renderer/Root.tsx @@ -29,6 +29,8 @@ import { ChannelContextMenu } from './components/ContextMenu/menus/ChannelContex import { DeleteChannel } from './components/Channel/DeleteChannel/DeleteChannel' import ChannelCreationModal from './components/ChannelCreationModal/ChannelCreationModal' import { SaveStateComponent } from './components/SaveState/SaveStateComponent' +import UnregisteredModalContainer from './components/widgets/userLabel/unregistered/UnregisteredModal.container' +import DuplicateModalContainer from './components/widgets/userLabel/duplicate/DuplicateModal.container' // Trigger lerna export const persistor = persistStore(store) @@ -42,6 +44,8 @@ export default () => { + + diff --git a/packages/desktop/src/renderer/components/Channel/Channel.stories.cy.tsx b/packages/desktop/src/renderer/components/Channel/Channel.stories.cy.tsx index d06ec15c28..4a6ea0d6f9 100644 --- a/packages/desktop/src/renderer/components/Channel/Channel.stories.cy.tsx +++ b/packages/desktop/src/renderer/components/Channel/Channel.stories.cy.tsx @@ -11,6 +11,7 @@ import { HTML5Backend } from 'react-dnd-html5-backend' import { DisplayableMessage } from '@quiet/types' import ChannelComponent from './ChannelComponent' +import { payloadDuplicated, payloadUnregistered } from '../widgets/userLabel/UserLabel.types' const Template: ComponentStory = () => { const [messages, setMessages] = useState<{ @@ -28,7 +29,7 @@ const Template: ComponentStory = () => { message: message, createdAt: 0, date: '12:46', - nickname: 'vader' + nickname: 'vader', } const _messages = mock_messages(_message) setMessages(_messages) @@ -48,23 +49,23 @@ const Template: ComponentStory = () => { createdAt: 0, channelId: 'general', signature: 'signature', - pubKey: 'pubKey' + pubKey: 'pubKey', }} user={{ id: 'id', nickname: 'vader', hiddenService: { onionAddress: 'onionAddress', - privateKey: 'privateKey' + privateKey: 'privateKey', }, peerId: { id: 'id', privKey: 'privKey', - pubKey: 'pubKey' + pubKey: 'pubKey', }, dmKeys: { publicKey: 'publicKey', - privateKey: 'privateKey' + privateKey: 'privateKey', }, userCsr: { userCsr: 'userCsr', @@ -72,18 +73,18 @@ const Template: ComponentStory = () => { pkcs10: { publicKey: 'publicKey', privateKey: 'privateKey', - pkcs10: 'pkcs10' - } + pkcs10: 'pkcs10', + }, }, userCertificate: 'userCertificate', - joinTimestamp: null + joinTimestamp: null, }} isCommunityInitialized={true} uploadedFileModal={{ open: false, handleOpen: function (_args?: any): any {}, handleClose: function (): any {}, - src: 'images/butterfly.jpeg' + src: 'images/butterfly.jpeg', }} channelId={'general'} channelName={'general'} @@ -107,6 +108,8 @@ const Template: ComponentStory = () => { handleClipboardFiles={function (arg: ArrayBuffer, ext: string, name: string): void { throw new Error('Function not implemented.') }} + duplicatedUsernameModalHandleOpen={() => payloadDuplicated} + unregisteredUsernameModalHandleOpen={() => payloadUnregistered} /> @@ -118,7 +121,7 @@ export const Component = Template.bind({}) const component: ComponentMeta = { title: 'Components/ChannelComponentCypress', decorators: [withTheme], - component: ChannelComponent + component: ChannelComponent, } export default component diff --git a/packages/desktop/src/renderer/components/Channel/Channel.tsx b/packages/desktop/src/renderer/components/Channel/Channel.tsx index b4235ac7c1..df69e07268 100644 --- a/packages/desktop/src/renderer/components/Channel/Channel.tsx +++ b/packages/desktop/src/renderer/components/Channel/Channel.tsx @@ -55,6 +55,8 @@ const Channel = () => { const pendingMessages = useSelector(messages.selectors.messagesSendingStatus) const uploadedFileModal = useModal<{ src: string }>(ModalName.uploadedFileModal) + const { handleOpen: duplicatedUsernameModalHandleOpen } = useModal(ModalName.duplicatedUsernameModal) + const { handleOpen: unregisteredUsernameModalHandleOpen } = useModal(ModalName.unregisteredUsernameModal) const [uploadingFiles, setUploadingFiles] = React.useState({}) @@ -220,6 +222,8 @@ const Channel = () => { openContextMenu: openContextMenu, enableContextMenu: enableContextMenu, pendingGeneralChannelRecreation: pendingGeneralChannelRecreation, + unregisteredUsernameModalHandleOpen, + duplicatedUsernameModalHandleOpen, } const uploadFilesPreviewProps: UploadFilesPreviewsProps = { diff --git a/packages/desktop/src/renderer/components/Channel/ChannelComponent.tsx b/packages/desktop/src/renderer/components/Channel/ChannelComponent.tsx index 6cc17b0079..6924e53c7c 100644 --- a/packages/desktop/src/renderer/components/Channel/ChannelComponent.tsx +++ b/packages/desktop/src/renderer/components/Channel/ChannelComponent.tsx @@ -25,6 +25,7 @@ import { NewMessagesInfoComponent } from './NewMessagesInfo/NewMessagesInfoCompo import { FileActionsProps } from './File/FileComponent/FileComponent' import { UseModalType } from '../../containers/hooks' +import { HandleOpenModalType } from '../widgets/userLabel/UserLabel.types' const ChannelMessagesWrapperStyled = styled(Grid)(({ theme }) => ({ position: 'relative', @@ -57,6 +58,8 @@ export interface ChannelComponentProps { openContextMenu?: () => void enableContextMenu?: boolean pendingGeneralChannelRecreation: boolean + unregisteredUsernameModalHandleOpen: HandleOpenModalType + duplicatedUsernameModalHandleOpen: HandleOpenModalType } const enum ScrollPosition { @@ -90,6 +93,8 @@ export const ChannelComponent: React.FC { const [lastSeenMessage, setLastSeenMessage] = useState() const [newMessagesInfo, setNewMessagesInfo] = useState(false) @@ -232,6 +237,8 @@ export const ChannelComponent: React.FC diff --git a/packages/desktop/src/renderer/components/widgets/channels/BasicMessage.test.tsx b/packages/desktop/src/renderer/components/widgets/channels/BasicMessage.test.tsx index dcbee412d0..5ea510e3df 100644 --- a/packages/desktop/src/renderer/components/widgets/channels/BasicMessage.test.tsx +++ b/packages/desktop/src/renderer/components/widgets/channels/BasicMessage.test.tsx @@ -19,7 +19,12 @@ describe('BasicMessage', () => { const result = renderComponent( - + ) @@ -27,7 +32,7 @@ describe('BasicMessage', () => {
  • { class="MuiGrid-root MuiGrid-container MuiGrid-item css-1f064cs-MuiGrid-root" >
    { const result = renderComponent( - + ) @@ -110,7 +120,7 @@ describe('BasicMessage', () => {
  • { class="MuiGrid-root MuiGrid-container MuiGrid-item css-1f064cs-MuiGrid-root" >
    { const result = renderComponent( - + ) @@ -203,7 +218,7 @@ describe('BasicMessage', () => {
  • { class="MuiGrid-root MuiGrid-container MuiGrid-item css-1f064cs-MuiGrid-root" >
    { const result = renderComponent( - + ) @@ -300,7 +320,7 @@ describe('BasicMessage', () => {
  • { class="MuiGrid-root MuiGrid-container MuiGrid-item css-1f064cs-MuiGrid-root" >
    ({ }, [`& .${classes.avatar}`]: { - minHeight: 36, - minWidth: 36, + minHeight: 40, + minWidth: 40, marginRight: 10, marginBottom: 4, borderRadius: 4, @@ -101,8 +103,8 @@ const StyledListItem = styled(ListItem)(({ theme }) => ({ [`& .${classes.alignAvatar}`]: { marginTop: 2, marginLeft: 2, - width: 32, - height: 32, + width: 38, + height: 38, }, [`& .${classes.moderation}`]: { @@ -113,8 +115,7 @@ const StyledListItem = styled(ListItem)(({ theme }) => ({ [`& .${classes.time}`]: { color: theme.palette.colors.lightGray, fontSize: 14, - marginTop: -4, - marginRight: 5, + marginTop: -2, }, [`& .${classes.iconBox}`]: { @@ -130,7 +131,7 @@ const StyledListItem = styled(ListItem)(({ theme }) => ({ }, [`& .${classes.infoIcon}`]: { - width: 32, + width: 38, }, })) @@ -151,6 +152,9 @@ export interface BasicMessageProps { src: string }> onMathMessageRendered?: () => void + userLabel?: UserLabelType + unregisteredUsernameModalHandleOpen: HandleOpenModalType + duplicatedUsernameModalHandleOpen: HandleOpenModalType } export const BasicMessageComponent: React.FC = ({ @@ -163,6 +167,9 @@ export const BasicMessageComponent: React.FC { const messageDisplayData = messages[0] @@ -189,13 +196,13 @@ export const BasicMessageComponent: React.FC ) : ( - + )}
    - - + + + {userLabel && ( + + + + )} {status !== 'failed' && ( { const result = renderComponent( {
  • { class="MuiGrid-root MuiGrid-container MuiGrid-item css-1f064cs-MuiGrid-root" >
    onMathMessageRendered?: () => void pendingGeneralChannelRecreation?: boolean + unregisteredUsernameModalHandleOpen: HandleOpenModalType + duplicatedUsernameModalHandleOpen: HandleOpenModalType } export const ChannelMessagesComponent: React.FC = ({ @@ -96,6 +99,8 @@ export const ChannelMessagesComponent: React.FC { const spinnerMessage = pendingGeneralChannelRecreation ? deletingChannelMessage : fetchingChannelMessagesText const listRef = useRef(null) @@ -152,6 +157,8 @@ export const ChannelMessagesComponent: React.FC ) })} diff --git a/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.component.tsx b/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.component.tsx new file mode 100644 index 0000000000..97cdea0b35 --- /dev/null +++ b/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.component.tsx @@ -0,0 +1,91 @@ +import React from 'react' +import { styled } from '@mui/material/styles' +import Grid from '@mui/material/Grid' +import Typography from '@mui/material/Typography' +import classNames from 'classnames' +import WarnIcon from '../../../static/images/warning-icon.svg' +import { HandleOpenModalType, UserLabelType } from './UserLabel.types' + +const PREFIX = 'UserLabel-' + +const classes = { + messageCard: `${PREFIX}messageCard`, + textWhite: `${PREFIX}textWhite`, + textBlack: `${PREFIX}textBlack`, + wrapper: `${PREFIX}wrapper`, + wrapperRed: `${PREFIX}wrapperRed`, + wrapperGray: `${PREFIX}wrapperGray`, + image: `${PREFIX}image`, +} + +const StyledGrid = styled(Grid)(({ theme }) => ({ + margin: '-4px 8px 0 4px', + [`& .${classes.wrapper}`]: { + padding: '1px 6px', + borderRadius: '8px', + cursor: 'pointer', + }, + [`& .${classes.wrapperGray}`]: { + backgroundColor: theme.palette.colors.gray03, + }, + [`& .${classes.wrapperRed}`]: { + backgroundColor: theme.palette.colors.error, + }, + [`& .${classes.textWhite}`]: { + color: 'white', + }, + [`& .${classes.textBlack}`]: { + color: 'black', + }, + [`& .${classes.image}`]: { + width: '12px', + height: '12px', + marginLeft: '4px', + }, +})) + +export interface UserLabelProps { + type: UserLabelType + username: string + unregisteredUsernameModalHandleOpen?: HandleOpenModalType + duplicatedUsernameModalHandleOpen?: HandleOpenModalType +} + +const UserLabel: React.FC = ({ + type, + username, + unregisteredUsernameModalHandleOpen, + duplicatedUsernameModalHandleOpen, +}) => { + const isUnregistered = type === UserLabelType.UNREGISTERED + const handleOpen = isUnregistered ? unregisteredUsernameModalHandleOpen : duplicatedUsernameModalHandleOpen + + return ( + + handleOpen({ username }) : () => {}} + container + item + alignItems='center' + justifyContent='space-between' + className={classNames(classes.wrapper, { + [classes.wrapperGray]: isUnregistered, + [classes.wrapperRed]: !isUnregistered, + })} + > + {!isUnregistered && } + + {type} + + + + ) +} + +export default UserLabel diff --git a/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.stories.tsx b/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.stories.tsx new file mode 100644 index 0000000000..628782bb5d --- /dev/null +++ b/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.stories.tsx @@ -0,0 +1,45 @@ +import React from 'react' +import { ComponentStory, ComponentMeta } from '@storybook/react' +import { withTheme } from '../../../storybook/decorators' +import UserLabel, { UserLabelProps } from './UserLabel.component' +import { payloadDuplicated, payloadUnregistered, UserLabelType } from './UserLabel.types' +import { ModalName } from '../../../sagas/modals/modals.types' +import { modalsActions } from '../../../sagas/modals/modals.slice' + +const Template: ComponentStory = args => { + return ( +
    + +
    + ) +} + +export const Duplicate = Template.bind({}) +export const Unregistered = Template.bind({}) + +const baseArg = { + duplicatedUsernameModalHandleOpen: () => payloadDuplicated, + unregisteredUsernameModalHandleOpen: () => payloadUnregistered, + username: 'johnny', +} + +const argsDuplicate: UserLabelProps = { + ...baseArg, + type: UserLabelType.DUPLICATE, +} + +const argsUnregistered: UserLabelProps = { + ...baseArg, + type: UserLabelType.UNREGISTERED, +} + +Duplicate.args = argsDuplicate +Unregistered.args = argsUnregistered + +const component: ComponentMeta = { + title: 'Components/UserLabel', + decorators: [withTheme], + component: UserLabel, +} + +export default component diff --git a/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.test.tsx b/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.test.tsx new file mode 100644 index 0000000000..2f2768df8b --- /dev/null +++ b/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.test.tsx @@ -0,0 +1,75 @@ +import React from 'react' +import theme from '../../../theme' +import { ThemeProvider } from '@mui/material/styles' +import { renderComponent } from '../../../testUtils/renderComponent' +import UserLabel from './UserLabel.component' +import { payloadDuplicated, payloadUnregistered, UserLabelType } from './UserLabel.types' + +describe('UserLabel', () => { + it('duplicate', () => { + const result = renderComponent( + + payloadDuplicated} + unregisteredUsernameModalHandleOpen={() => payloadUnregistered} + username={'johnny'} + type={UserLabelType.DUPLICATE} + /> + + ) + expect(result.baseElement).toMatchInlineSnapshot(` + +
    +
    +
    + + + Duplicate + +
    +
    +
    + + `) + }) + it('unregistered', () => { + const result = renderComponent( + + payloadDuplicated} + unregisteredUsernameModalHandleOpen={() => payloadUnregistered} + username={'johnny'} + type={UserLabelType.UNREGISTERED} + /> + + ) + expect(result.baseElement).toMatchInlineSnapshot(` + +
    +
    +
    + + Unregistered + +
    +
    +
    + + `) + }) +}) diff --git a/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.types.ts b/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.types.ts new file mode 100644 index 0000000000..8eadac2da0 --- /dev/null +++ b/packages/desktop/src/renderer/components/widgets/userLabel/UserLabel.types.ts @@ -0,0 +1,26 @@ +import { modalsActions, OpenModalPayload } from '../../../sagas/modals/modals.slice' +import { ModalName } from '../../../sagas/modals/modals.types' + +export enum UserLabelType { + DUPLICATE = 'Duplicate', + UNREGISTERED = 'Unregistered', +} + +export type HandleOpenModalType = (args?: object | undefined) => { + payload: OpenModalPayload + type: 'Modals/openModal' +} + +export const payloadDuplicated = { + payload: { + name: ModalName.duplicatedUsernameModal, + }, + type: modalsActions.openModal.type, +} + +export const payloadUnregistered = { + payload: { + name: ModalName.duplicatedUsernameModal, + }, + type: modalsActions.openModal.type, +} diff --git a/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.component.tsx b/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.component.tsx new file mode 100644 index 0000000000..c0a1bc96ff --- /dev/null +++ b/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.component.tsx @@ -0,0 +1,60 @@ +import React from 'react' +import Modal from '../../../ui/Modal/Modal' +import { Grid, Typography } from '@mui/material' +import { styled } from '@mui/material/styles' +import WarnIcon from '../../../../static/images/exclamationMark.svg' +import UserLabel from '../UserLabel.component' +import { UserLabelType } from '../UserLabel.types' + +const PREFIX = 'UserDuplicateModalComponent-' + +const classes = { + bodyText: `${PREFIX}bodyText`, + image: `${PREFIX}image`, +} + +const StyledGrid = styled(Grid)(({ theme }) => ({ + [`& .${classes.bodyText}`]: { + textAlign: 'center', + width: '60%', + margin: '24px 0 4px', + }, + [`& .${classes.image}`]: { + width: '70px', + height: '70px', + margin: '30px 0 24px', + }, +})) + +export interface DuplicateModalComponentProps { + open: boolean + handleClose: () => void +} + +const DuplicateModalComponent: React.FC = ({ handleClose, open }) => { + return ( + + + + Multiple users with same name + + An unregistered user is using the same name as another user. This should be rare, and could mean someone is + impersonating another user. +
    +
    + These users will be marked +
    + +
    +
    + ) +} + +export default DuplicateModalComponent diff --git a/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.container.tsx b/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.container.tsx new file mode 100644 index 0000000000..50c8993c92 --- /dev/null +++ b/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.container.tsx @@ -0,0 +1,11 @@ +import React from 'react' +import { useModal } from '../../../../containers/hooks' +import { ModalName } from '../../../../sagas/modals/modals.types' +import DuplicateModalComponent from './DuplicateModal.component' + +const DuplicateModalContainer = () => { + const duplicateModal = useModal(ModalName.duplicatedUsernameModal) + return +} + +export default DuplicateModalContainer diff --git a/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.stories.tsx b/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.stories.tsx new file mode 100644 index 0000000000..385e91440c --- /dev/null +++ b/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.stories.tsx @@ -0,0 +1,29 @@ +import React from 'react' +import { ComponentStory, ComponentMeta } from '@storybook/react' +import { withTheme } from '../../../../storybook/decorators' +import DuplicateModalComponent, { DuplicateModalComponentProps } from './DuplicateModal.component' + +const Template: ComponentStory = args => { + return ( +
    + +
    + ) +} + +export const Component = Template.bind({}) + +const args: DuplicateModalComponentProps = { + handleClose: function (): void {}, + open: true, +} + +Component.args = args + +const component: ComponentMeta = { + title: 'Components/UserLabel/DuplicateModalComponent', + decorators: [withTheme], + component: DuplicateModalComponent, +} + +export default component diff --git a/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.test.tsx b/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.test.tsx new file mode 100644 index 0000000000..371b5cb186 --- /dev/null +++ b/packages/desktop/src/renderer/components/widgets/userLabel/duplicate/DuplicateModal.test.tsx @@ -0,0 +1,142 @@ +import React from 'react' +import theme from '../../../../theme' +import { ThemeProvider } from '@mui/material/styles' +import { renderComponent } from '../../../../testUtils/renderComponent' +import DuplicateModalComponent from './DuplicateModal.component' + +describe('DuplicateModalComponent', () => { + it('renderComponent', () => { + const result = renderComponent( + + {}} open={true} /> + + ) + expect(result.baseElement).toMatchInlineSnapshot(` + +