Add reusable dialog (#459)

Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
Ajay Bura 2022-03-31 20:39:05 +05:30 committed by GitHub
parent 53a8e2aa57
commit 3f6e3074f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 82 additions and 9 deletions

View file

@ -12,6 +12,7 @@ import RawModal from '../../atoms/modal/RawModal';
function Dialog({ function Dialog({
className, isOpen, title, onAfterOpen, onAfterClose, className, isOpen, title, onAfterOpen, onAfterClose,
contentOptions, onRequestClose, closeFromOutside, children, contentOptions, onRequestClose, closeFromOutside, children,
invisibleScroll,
}) { }) {
return ( return (
<RawModal <RawModal
@ -36,7 +37,7 @@ function Dialog({
{contentOptions} {contentOptions}
</Header> </Header>
<div className="dialog__content__wrapper"> <div className="dialog__content__wrapper">
<ScrollView autoHide> <ScrollView autoHide invisible={invisibleScroll}>
<div className="dialog__content-container"> <div className="dialog__content-container">
{children} {children}
</div> </div>
@ -55,6 +56,7 @@ Dialog.defaultProps = {
onAfterClose: null, onAfterClose: null,
onRequestClose: null, onRequestClose: null,
closeFromOutside: true, closeFromOutside: true,
invisibleScroll: false,
}; };
Dialog.propTypes = { Dialog.propTypes = {
@ -67,6 +69,7 @@ Dialog.propTypes = {
onRequestClose: PropTypes.func, onRequestClose: PropTypes.func,
closeFromOutside: PropTypes.bool, closeFromOutside: PropTypes.bool,
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
invisibleScroll: PropTypes.bool,
}; };
export default Dialog; export default Dialog;

View file

@ -21,8 +21,3 @@
flex-direction: column; flex-direction: column;
} }
} }
.dialog__content-container {
padding-top: var(--sp-extra-tight);
padding-bottom: var(--sp-extra-loose);
}

View file

@ -0,0 +1,49 @@
import React, { useState, useEffect } from 'react';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
import IconButton from '../../atoms/button/IconButton';
import Dialog from './Dialog';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
function ReusableDialog() {
const [isOpen, setIsOpen] = useState(false);
const [data, setData] = useState(null);
useEffect(() => {
const handleOpen = (title, render, afterClose) => {
setIsOpen(true);
setData({ title, render, afterClose });
};
navigation.on(cons.events.navigation.REUSABLE_DIALOG_OPENED, handleOpen);
return () => {
navigation.removeListener(cons.events.navigation.REUSABLE_DIALOG_OPENED, handleOpen);
};
}, []);
const handleAfterClose = () => {
data.afterClose();
setData(null);
};
const handleRequestClose = () => {
setIsOpen(false);
};
return (
<Dialog
isOpen={isOpen}
title={data?.title || ''}
onAfterClose={handleAfterClose}
onRequestClose={handleRequestClose}
contentOptions={<IconButton src={CrossIC} onClick={handleRequestClose} tooltip="Close" />}
invisibleScroll
>
{data?.render(handleRequestClose) || <div />}
</Dialog>
);
}
export default ReusableDialog;

View file

@ -2,6 +2,7 @@
@use '../../partials/dir'; @use '../../partials/dir';
.create-room { .create-room {
margin: var(--sp-normal);
@include dir.side(margin, var(--sp-normal), var(--sp-extra-tight)); @include dir.side(margin, var(--sp-normal), var(--sp-extra-tight));
&__form > * { &__form > * {

View file

@ -8,6 +8,8 @@ import Search from '../search/Search';
import ViewSource from '../view-source/ViewSource'; import ViewSource from '../view-source/ViewSource';
import CreateRoom from '../create-room/CreateRoom'; import CreateRoom from '../create-room/CreateRoom';
import ReusableDialog from '../../molecules/dialog/ReusableDialog';
function Dialogs() { function Dialogs() {
return ( return (
<> <>
@ -18,6 +20,8 @@ function Dialogs() {
<CreateRoom /> <CreateRoom />
<SpaceAddExisting /> <SpaceAddExisting />
<Search /> <Search />
<ReusableDialog />
</> </>
); );
} }

View file

@ -64,9 +64,11 @@ function ReadReceipts() {
onRequestClose={() => setIsOpen(false)} onRequestClose={() => setIsOpen(false)}
contentOptions={<IconButton src={CrossIC} onClick={() => setIsOpen(false)} tooltip="Close" />} contentOptions={<IconButton src={CrossIC} onClick={() => setIsOpen(false)} tooltip="Close" />}
> >
<div style={{ marginTop: 'var(--sp-tight)', marginBottom: 'var(--sp-extra-loose)' }}>
{ {
readers.map(renderPeople) readers.map(renderPeople)
} }
</div>
</Dialog> </Dialog>
); );
} }

View file

@ -150,3 +150,12 @@ export function openReusableContextMenu(placement, cords, render, afterClose) {
afterClose, afterClose,
}); });
} }
export function openReusableDialog(title, render, afterClose) {
appDispatcher.dispatch({
type: cons.actions.navigation.OPEN_REUSABLE_DIALOG,
title,
render,
afterClose,
});
}

View file

@ -47,6 +47,7 @@ const cons = {
CLICK_REPLY_TO: 'CLICK_REPLY_TO', CLICK_REPLY_TO: 'CLICK_REPLY_TO',
OPEN_SEARCH: 'OPEN_SEARCH', OPEN_SEARCH: 'OPEN_SEARCH',
OPEN_REUSABLE_CONTEXT_MENU: 'OPEN_REUSABLE_CONTEXT_MENU', OPEN_REUSABLE_CONTEXT_MENU: 'OPEN_REUSABLE_CONTEXT_MENU',
OPEN_REUSABLE_DIALOG: 'OPEN_REUSABLE_DIALOG',
}, },
room: { room: {
JOIN: 'JOIN', JOIN: 'JOIN',
@ -92,6 +93,7 @@ const cons = {
REPLY_TO_CLICKED: 'REPLY_TO_CLICKED', REPLY_TO_CLICKED: 'REPLY_TO_CLICKED',
SEARCH_OPENED: 'SEARCH_OPENED', SEARCH_OPENED: 'SEARCH_OPENED',
REUSABLE_CONTEXT_MENU_OPENED: 'REUSABLE_CONTEXT_MENU_OPENED', REUSABLE_CONTEXT_MENU_OPENED: 'REUSABLE_CONTEXT_MENU_OPENED',
REUSABLE_DIALOG_OPENED: 'REUSABLE_DIALOG_OPENED',
}, },
roomList: { roomList: {
ROOMLIST_UPDATED: 'ROOMLIST_UPDATED', ROOMLIST_UPDATED: 'ROOMLIST_UPDATED',

View file

@ -174,6 +174,14 @@ class Navigation extends EventEmitter {
action.afterClose, action.afterClose,
); );
}, },
[cons.actions.navigation.OPEN_REUSABLE_DIALOG]: () => {
this.emit(
cons.events.navigation.REUSABLE_DIALOG_OPENED,
action.title,
action.render,
action.afterClose,
);
},
}; };
actions[action.type]?.(); actions[action.type]?.();
} }