- made code more extendable

- improved code quality
This commit is contained in:
C0ffeeCode 2022-01-06 19:29:17 +01:00
parent a326b0054f
commit 1e53be7210
9 changed files with 148 additions and 139 deletions

View file

@ -69,6 +69,7 @@
"sass-loader": "^11.0.1",
"stream-browserify": "^3.0.0",
"style-loader": "^2.0.0",
"url": "^0.11.0",
"util": "^0.12.4",
"webpack": "^5.62.1",
"webpack-cli": "^4.9.1",

View file

@ -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;

View file

@ -1,46 +1,15 @@
/* eslint-disable react/prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import { attachmentUiFrameTypes } from '../AttachmentTypeSelector';
import VoiceMailRecorder from './VoiceMailRecorder';
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';
import FileAttachedIndicator from './FileAttachedIndicator';
import attachmentUis from './attachmentUis';
function AttachmentFrame({
attachmentOrUi,
fileSetter,
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() {
// let requestResult;
// const fnRequestResult = (func) => {
// requestResult = func;
// };
let submission;
const fnHowToSubmit = (func) => {
submission = func;
@ -48,22 +17,17 @@ function AttachmentFrame({
};
// If there already is an attachment, show it
if (typeof attachmentOrUi === 'object') return fileAttachedIndicator();
// How to interact with components?
switch (attachmentOrUi) {
case attachmentUiFrameTypes.voiceMailRecorder:
// 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;
if (typeof attachmentOrUi === 'object') {
return (
<FileAttachedIndicator
attachmentOrUi={attachmentOrUi}
uploadProgressRef={uploadProgressRef}
/>
);
}
const UiComponent = attachmentUis.get(attachmentOrUi).component;
return (<UiComponent fnHowToSubmit={fnHowToSubmit} />);
}
return attachmentFrame();
}

View file

@ -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;

View file

@ -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;

View file

@ -123,7 +123,6 @@ function VoiceMailRecorder({ fnHowToSubmit }) {
};
}, []);
// fnRequestResult(stopAndSubmit);
initiateInitiation();
const ui = (
@ -155,10 +154,6 @@ function VoiceMailRecorder({ fnHowToSubmit }) {
}
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,
};

View 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;

View file

@ -25,7 +25,7 @@ import SendIC from '../../../../public/res/ic/outlined/send.svg';
import ShieldIC from '../../../../public/res/ic/outlined/shield.svg';
import MarkdownIC from '../../../../public/res/ic/outlined/markdown.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';
const CMD_REGEX = /(^\/|:|@)(\S*)$/;
@ -295,20 +295,13 @@ function RoomViewInput({
}
const handleAttachmentTypeSelectorReturn = (ret) => {
switch (ret) {
case attachmentUiFrameTypes.none:
setAttachmentOrUi(ret);
roomsInput.cancelAttachment(roomId);
break;
case attachmentUiFrameTypes.file:
uploadInputRef.current.click();
break;
case attachmentUiFrameTypes.voiceMailRecorder:
setAttachmentOrUi(ret);
break;
default:
console.log('unhandled attachment type selector return');
break;
if (!ret) {
setAttachmentOrUi(null);
roomsInput.cancelAttachment(roomId);
} else if (ret === 'file') {
uploadInputRef.current.click();
} else {
setAttachmentOrUi(ret);
}
};

View file

@ -16,6 +16,8 @@ module.exports = {
'stream': require.resolve('stream-browserify'),
'util': require.resolve('util/'),
'assert': require.resolve('assert/'),
"events": require.resolve("events/"),
"url": require.resolve("url/"),
}
},
node: {