diff --git a/package.json b/package.json index 8c86ca2d..a82ef881 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/app/organisms/room/AttachmentTypeSelector.jsx b/src/app/organisms/room/AttachmentTypeSelector.jsx deleted file mode 100644 index a4fe8f8a..00000000 --- a/src/app/organisms/room/AttachmentTypeSelector.jsx +++ /dev/null @@ -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 ( - ( - <> - Attachment - { - toggleMenu(); actOnAttaching(attachmentUiFrameTypes.file); - }} - iconSrc={FileIC} - > - File - - { - toggleMenu(); actOnAttaching(attachmentUiFrameTypes.voiceMailRecorder); - }} - > - Audio - - - )} - render={(toggleMenu) => ( - { - 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; diff --git a/src/app/organisms/room/AttachmentUis/AttachmentFrame.jsx b/src/app/organisms/room/AttachmentUis/AttachmentFrame.jsx index 7bf5c1e0..c2cdb3bb 100644 --- a/src/app/organisms/room/AttachmentUis/AttachmentFrame.jsx +++ b/src/app/organisms/room/AttachmentUis/AttachmentFrame.jsx @@ -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 ( -
-
- {fileType === 'image' && {attachmentOrUi.name}} - {fileType === 'video' && } - {fileType === 'audio' && } - {fileType !== 'image' && fileType !== 'video' && fileType !== 'audio' && } -
-
- {attachmentOrUi.name} - {`size: ${bytesToSize(attachmentOrUi.size)}`} -
-
- ); - } - 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 ( - - ); - default: - console.log('unhandled attachmentOrUi'); - return null; + if (typeof attachmentOrUi === 'object') { + return ( + + ); } + + const UiComponent = attachmentUis.get(attachmentOrUi).component; + return (); } return attachmentFrame(); } diff --git a/src/app/organisms/room/AttachmentUis/AttachmentTypeSelector.jsx b/src/app/organisms/room/AttachmentUis/AttachmentTypeSelector.jsx new file mode 100644 index 00000000..e1b80407 --- /dev/null +++ b/src/app/organisms/room/AttachmentUis/AttachmentTypeSelector.jsx @@ -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( + { + toggleMenu(); + actOnAttaching(key); // TODO: change to component + }} + iconSrc={icon} + > + {obj.fullName} + , + ); + }); + + return list; + } + + return ( + ( +
+ Attachment + {getList(toggleMenu)} +
+ )} + render={(toggleMenu) => ( + { + 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; diff --git a/src/app/organisms/room/AttachmentUis/FileAttachedIndicator.jsx b/src/app/organisms/room/AttachmentUis/FileAttachedIndicator.jsx new file mode 100644 index 00000000..2a891646 --- /dev/null +++ b/src/app/organisms/room/AttachmentUis/FileAttachedIndicator.jsx @@ -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 ( +
+
+ {fileType === 'image' && {attachmentOrUi.name}} + {fileType === 'video' && } + {fileType === 'audio' && } + {fileType !== 'image' && fileType !== 'video' && fileType !== 'audio' && } +
+
+ {attachmentOrUi.name} + {`size: ${bytesToSize(attachmentOrUi.size)}`} +
+
+ ); +} + +FileAttachedIndicator.propTypes = { + attachmentOrUi: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired, + uploadProgressRef: PropTypes.shape().isRequired, +}; + +export default FileAttachedIndicator; diff --git a/src/app/organisms/room/AttachmentUis/VoiceMailRecorder.jsx b/src/app/organisms/room/AttachmentUis/VoiceMailRecorder.jsx index 3b5e5acb..b6873678 100644 --- a/src/app/organisms/room/AttachmentUis/VoiceMailRecorder.jsx +++ b/src/app/organisms/room/AttachmentUis/VoiceMailRecorder.jsx @@ -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, }; diff --git a/src/app/organisms/room/AttachmentUis/attachmentUis.js b/src/app/organisms/room/AttachmentUis/attachmentUis.js new file mode 100644 index 00000000..a3465904 --- /dev/null +++ b/src/app/organisms/room/AttachmentUis/attachmentUis.js @@ -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; diff --git a/src/app/organisms/room/RoomViewInput.jsx b/src/app/organisms/room/RoomViewInput.jsx index 36a37e55..3411f032 100644 --- a/src/app/organisms/room/RoomViewInput.jsx +++ b/src/app/organisms/room/RoomViewInput.jsx @@ -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); } }; diff --git a/webpack.common.js b/webpack.common.js index 0dd3e092..c1e88087 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -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: {