- made code more extendable
- improved code quality
This commit is contained in:
parent
a326b0054f
commit
1e53be7210
9 changed files with 148 additions and 139 deletions
|
@ -69,6 +69,7 @@
|
||||||
"sass-loader": "^11.0.1",
|
"sass-loader": "^11.0.1",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"style-loader": "^2.0.0",
|
"style-loader": "^2.0.0",
|
||||||
|
"url": "^0.11.0",
|
||||||
"util": "^0.12.4",
|
"util": "^0.12.4",
|
||||||
"webpack": "^5.62.1",
|
"webpack": "^5.62.1",
|
||||||
"webpack-cli": "^4.9.1",
|
"webpack-cli": "^4.9.1",
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import IconButton from '../../atoms/button/IconButton';
|
|
||||||
import CirclePlusIC from '../../../../public/res/ic/outlined/circle-plus.svg';
|
|
||||||
import FileIC from '../../../../public/res/ic/outlined/file.svg';
|
|
||||||
import ContextMenu, { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu';
|
|
||||||
|
|
||||||
// const AttachmentTypes = {
|
|
||||||
// remove: 'remove',
|
|
||||||
// file: 'file',
|
|
||||||
// voice: 'voice',
|
|
||||||
// };
|
|
||||||
const attachmentUiFrameTypes = {
|
|
||||||
none: null,
|
|
||||||
hasFile: 'file',
|
|
||||||
voiceMailRecorder: 'voiceMailRecorder',
|
|
||||||
};
|
|
||||||
|
|
||||||
function AttachmentTypeSelector({ alreadyHasAttachment, actOnAttaching }) {
|
|
||||||
return (
|
|
||||||
<ContextMenu
|
|
||||||
maxWidth={200}
|
|
||||||
content={(toggleMenu) => (
|
|
||||||
<>
|
|
||||||
<MenuHeader>Attachment</MenuHeader>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
toggleMenu(); actOnAttaching(attachmentUiFrameTypes.file);
|
|
||||||
}}
|
|
||||||
iconSrc={FileIC}
|
|
||||||
>
|
|
||||||
File
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
toggleMenu(); actOnAttaching(attachmentUiFrameTypes.voiceMailRecorder);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Audio
|
|
||||||
</MenuItem>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
render={(toggleMenu) => (
|
|
||||||
<IconButton
|
|
||||||
onClick={() => {
|
|
||||||
if (!alreadyHasAttachment) {
|
|
||||||
toggleMenu();
|
|
||||||
} else {
|
|
||||||
actOnAttaching(attachmentUiFrameTypes.none);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
tooltip={alreadyHasAttachment ? 'Cancel' : 'Select attachment'}
|
|
||||||
src={CirclePlusIC}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
AttachmentTypeSelector.propTypes = {
|
|
||||||
alreadyHasAttachment: PropTypes.bool,
|
|
||||||
actOnAttaching: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
AttachmentTypeSelector.defaultProps = {
|
|
||||||
alreadyHasAttachment: false,
|
|
||||||
actOnAttaching: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
export { AttachmentTypeSelector, attachmentUiFrameTypes };
|
|
||||||
export default AttachmentTypeSelector;
|
|
|
@ -1,46 +1,15 @@
|
||||||
/* eslint-disable react/prop-types */
|
/* eslint-disable react/prop-types */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { attachmentUiFrameTypes } from '../AttachmentTypeSelector';
|
import FileAttachedIndicator from './FileAttachedIndicator';
|
||||||
import VoiceMailRecorder from './VoiceMailRecorder';
|
import attachmentUis from './attachmentUis';
|
||||||
import RawIcon from '../../../atoms/system-icons/RawIcon';
|
|
||||||
import VLCIC from '../../../../../public/res/ic/outlined/vlc.svg';
|
|
||||||
import VolumeFullIC from '../../../../../public/res/ic/outlined/volume-full.svg';
|
|
||||||
import FileIC from '../../../../../public/res/ic/outlined/file.svg';
|
|
||||||
import Text from '../../../atoms/text/Text';
|
|
||||||
import { bytesToSize } from '../../../../util/common';
|
|
||||||
|
|
||||||
function AttachmentFrame({
|
function AttachmentFrame({
|
||||||
attachmentOrUi,
|
attachmentOrUi,
|
||||||
fileSetter,
|
fileSetter,
|
||||||
uploadProgressRef,
|
uploadProgressRef,
|
||||||
}) {
|
}) {
|
||||||
function fileAttachedIndicator() {
|
|
||||||
// If this is not a file object, how can this be reached?
|
|
||||||
if (typeof attachmentOrUi !== 'object') return null;
|
|
||||||
|
|
||||||
const fileType = attachmentOrUi.type.slice(0, attachmentOrUi.type.indexOf('/'));
|
|
||||||
return (
|
|
||||||
<div className="room-attachment">
|
|
||||||
<div className={`room-attachment__preview${fileType !== 'image' ? ' room-attachment__icon' : ''}`}>
|
|
||||||
{fileType === 'image' && <img alt={attachmentOrUi.name} src={URL.createObjectURL(attachmentOrUi)} />}
|
|
||||||
{fileType === 'video' && <RawIcon src={VLCIC} />}
|
|
||||||
{fileType === 'audio' && <RawIcon src={VolumeFullIC} />}
|
|
||||||
{fileType !== 'image' && fileType !== 'video' && fileType !== 'audio' && <RawIcon src={FileIC} />}
|
|
||||||
</div>
|
|
||||||
<div className="room-attachment__info">
|
|
||||||
<Text variant="b1">{attachmentOrUi.name}</Text>
|
|
||||||
<Text variant="b3"><span ref={uploadProgressRef}>{`size: ${bytesToSize(attachmentOrUi.size)}`}</span></Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachmentFrame() {
|
function attachmentFrame() {
|
||||||
// let requestResult;
|
|
||||||
// const fnRequestResult = (func) => {
|
|
||||||
// requestResult = func;
|
|
||||||
// };
|
|
||||||
let submission;
|
let submission;
|
||||||
const fnHowToSubmit = (func) => {
|
const fnHowToSubmit = (func) => {
|
||||||
submission = func;
|
submission = func;
|
||||||
|
@ -48,22 +17,17 @@ function AttachmentFrame({
|
||||||
};
|
};
|
||||||
|
|
||||||
// If there already is an attachment, show it
|
// If there already is an attachment, show it
|
||||||
if (typeof attachmentOrUi === 'object') return fileAttachedIndicator();
|
if (typeof attachmentOrUi === 'object') {
|
||||||
|
return (
|
||||||
// How to interact with components?
|
<FileAttachedIndicator
|
||||||
switch (attachmentOrUi) {
|
attachmentOrUi={attachmentOrUi}
|
||||||
case attachmentUiFrameTypes.voiceMailRecorder:
|
uploadProgressRef={uploadProgressRef}
|
||||||
// Not too easy, need to attach function to return the audio blob
|
/>
|
||||||
return (
|
);
|
||||||
<VoiceMailRecorder
|
|
||||||
// fnRequestResult={fnRequestResult}
|
|
||||||
fnHowToSubmit={fnHowToSubmit}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
console.log('unhandled attachmentOrUi');
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UiComponent = attachmentUis.get(attachmentOrUi).component;
|
||||||
|
return (<UiComponent fnHowToSubmit={fnHowToSubmit} />);
|
||||||
}
|
}
|
||||||
return attachmentFrame();
|
return attachmentFrame();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import IconButton from '../../../atoms/button/IconButton';
|
||||||
|
import CirclePlusIC from '../../../../../public/res/ic/outlined/circle-plus.svg';
|
||||||
|
import PlusIC from '../../../../../public/res/ic/outlined/plus.svg';
|
||||||
|
import ContextMenu, { MenuHeader, MenuItem } from '../../../atoms/context-menu/ContextMenu';
|
||||||
|
import attachmentUiFrameTypes from './attachmentUis';
|
||||||
|
|
||||||
|
function AttachmentTypeSelector({ alreadyHasAttachment, actOnAttaching }) {
|
||||||
|
function getList(toggleMenu) {
|
||||||
|
const list = [];
|
||||||
|
|
||||||
|
attachmentUiFrameTypes.forEach((obj, key) => {
|
||||||
|
const icon = obj.icon ?? PlusIC;
|
||||||
|
|
||||||
|
list.push(
|
||||||
|
<MenuItem
|
||||||
|
// This does not matter
|
||||||
|
// eslint-disable-next-line react/no-array-index-key
|
||||||
|
key={`attachmentUiListItem-${key}`}
|
||||||
|
// variant="surface"
|
||||||
|
onClick={() => {
|
||||||
|
toggleMenu();
|
||||||
|
actOnAttaching(key); // TODO: change to component
|
||||||
|
}}
|
||||||
|
iconSrc={icon}
|
||||||
|
>
|
||||||
|
{obj.fullName}
|
||||||
|
</MenuItem>,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ContextMenu
|
||||||
|
maxWidth={200}
|
||||||
|
content={(toggleMenu) => (
|
||||||
|
<div>
|
||||||
|
<MenuHeader>Attachment</MenuHeader>
|
||||||
|
{getList(toggleMenu)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
render={(toggleMenu) => (
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
if (!alreadyHasAttachment) {
|
||||||
|
toggleMenu();
|
||||||
|
} else {
|
||||||
|
actOnAttaching(attachmentUiFrameTypes.none);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
tooltip={alreadyHasAttachment ? 'Cancel' : 'Select attachment'}
|
||||||
|
src={CirclePlusIC}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
AttachmentTypeSelector.propTypes = {
|
||||||
|
alreadyHasAttachment: PropTypes.bool,
|
||||||
|
actOnAttaching: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
AttachmentTypeSelector.defaultProps = {
|
||||||
|
alreadyHasAttachment: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AttachmentTypeSelector;
|
|
@ -0,0 +1,39 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import RawIcon from '../../../atoms/system-icons/RawIcon';
|
||||||
|
import VLCIC from '../../../../../public/res/ic/outlined/vlc.svg';
|
||||||
|
import VolumeFullIC from '../../../../../public/res/ic/outlined/volume-full.svg';
|
||||||
|
import FileIC from '../../../../../public/res/ic/outlined/file.svg';
|
||||||
|
import Text from '../../../atoms/text/Text';
|
||||||
|
import { bytesToSize } from '../../../../util/common';
|
||||||
|
|
||||||
|
function FileAttachedIndicator({
|
||||||
|
attachmentOrUi,
|
||||||
|
uploadProgressRef,
|
||||||
|
}) {
|
||||||
|
// If this is not a file object, how can this be reached?
|
||||||
|
if (typeof attachmentOrUi !== 'object') return null;
|
||||||
|
|
||||||
|
const fileType = attachmentOrUi.type.slice(0, attachmentOrUi.type.indexOf('/'));
|
||||||
|
return (
|
||||||
|
<div className="room-attachment">
|
||||||
|
<div className={`room-attachment__preview${fileType !== 'image' ? ' room-attachment__icon' : ''}`}>
|
||||||
|
{fileType === 'image' && <img alt={attachmentOrUi.name} src={URL.createObjectURL(attachmentOrUi)} />}
|
||||||
|
{fileType === 'video' && <RawIcon src={VLCIC} />}
|
||||||
|
{fileType === 'audio' && <RawIcon src={VolumeFullIC} />}
|
||||||
|
{fileType !== 'image' && fileType !== 'video' && fileType !== 'audio' && <RawIcon src={FileIC} />}
|
||||||
|
</div>
|
||||||
|
<div className="room-attachment__info">
|
||||||
|
<Text variant="b1">{attachmentOrUi.name}</Text>
|
||||||
|
<Text variant="b3"><span ref={uploadProgressRef}>{`size: ${bytesToSize(attachmentOrUi.size)}`}</span></Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileAttachedIndicator.propTypes = {
|
||||||
|
attachmentOrUi: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||||
|
uploadProgressRef: PropTypes.shape().isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FileAttachedIndicator;
|
|
@ -123,7 +123,6 @@ function VoiceMailRecorder({ fnHowToSubmit }) {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// fnRequestResult(stopAndSubmit);
|
|
||||||
initiateInitiation();
|
initiateInitiation();
|
||||||
|
|
||||||
const ui = (
|
const ui = (
|
||||||
|
@ -155,10 +154,6 @@ function VoiceMailRecorder({ fnHowToSubmit }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VoiceMailRecorder.propTypes = {
|
VoiceMailRecorder.propTypes = {
|
||||||
// // Might be useful in the future if
|
|
||||||
// // components should be requested to submit their result content when the message gets sent
|
|
||||||
// // so the user does not need this UI to attach its result here but can just sent it
|
|
||||||
// fnRequestResult: PropTypes.func.isRequired,
|
|
||||||
fnHowToSubmit: PropTypes.func.isRequired,
|
fnHowToSubmit: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
15
src/app/organisms/room/AttachmentUis/attachmentUis.js
Normal file
15
src/app/organisms/room/AttachmentUis/attachmentUis.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import FileIC from '../../../../../public/res/ic/outlined/file.svg';
|
||||||
|
import VoiceMailRecorder from './VoiceMailRecorder';
|
||||||
|
|
||||||
|
const attachmentUis = new Map();
|
||||||
|
|
||||||
|
attachmentUis.set('file', {
|
||||||
|
fullName: 'File',
|
||||||
|
icon: FileIC,
|
||||||
|
});
|
||||||
|
attachmentUis.set('voiceMailRecorder', {
|
||||||
|
fullName: 'Voice mail',
|
||||||
|
component: VoiceMailRecorder,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default attachmentUis;
|
|
@ -25,7 +25,7 @@ import SendIC from '../../../../public/res/ic/outlined/send.svg';
|
||||||
import ShieldIC from '../../../../public/res/ic/outlined/shield.svg';
|
import ShieldIC from '../../../../public/res/ic/outlined/shield.svg';
|
||||||
import MarkdownIC from '../../../../public/res/ic/outlined/markdown.svg';
|
import MarkdownIC from '../../../../public/res/ic/outlined/markdown.svg';
|
||||||
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
|
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
|
||||||
import { AttachmentTypeSelector, attachmentUiFrameTypes } from './AttachmentTypeSelector';
|
import AttachmentTypeSelector from './AttachmentUis/AttachmentTypeSelector';
|
||||||
import AttachmentFrame from './AttachmentUis/AttachmentFrame';
|
import AttachmentFrame from './AttachmentUis/AttachmentFrame';
|
||||||
|
|
||||||
const CMD_REGEX = /(^\/|:|@)(\S*)$/;
|
const CMD_REGEX = /(^\/|:|@)(\S*)$/;
|
||||||
|
@ -295,20 +295,13 @@ function RoomViewInput({
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleAttachmentTypeSelectorReturn = (ret) => {
|
const handleAttachmentTypeSelectorReturn = (ret) => {
|
||||||
switch (ret) {
|
if (!ret) {
|
||||||
case attachmentUiFrameTypes.none:
|
setAttachmentOrUi(null);
|
||||||
setAttachmentOrUi(ret);
|
roomsInput.cancelAttachment(roomId);
|
||||||
roomsInput.cancelAttachment(roomId);
|
} else if (ret === 'file') {
|
||||||
break;
|
uploadInputRef.current.click();
|
||||||
case attachmentUiFrameTypes.file:
|
} else {
|
||||||
uploadInputRef.current.click();
|
setAttachmentOrUi(ret);
|
||||||
break;
|
|
||||||
case attachmentUiFrameTypes.voiceMailRecorder:
|
|
||||||
setAttachmentOrUi(ret);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log('unhandled attachment type selector return');
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ module.exports = {
|
||||||
'stream': require.resolve('stream-browserify'),
|
'stream': require.resolve('stream-browserify'),
|
||||||
'util': require.resolve('util/'),
|
'util': require.resolve('util/'),
|
||||||
'assert': require.resolve('assert/'),
|
'assert': require.resolve('assert/'),
|
||||||
|
"events": require.resolve("events/"),
|
||||||
|
"url": require.resolve("url/"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
node: {
|
node: {
|
||||||
|
|
Loading…
Reference in a new issue