From 3ca696dd3d752302463c93de0ad48a6214cbd487 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Fri, 6 Jan 2023 01:51:39 +0800 Subject: [PATCH] Modals for media attachments in composer Dedicated editor experience per media attachment --- src/app.css | 3 + src/components/compose.css | 66 ++++++++++++++++++-- src/components/compose.jsx | 121 ++++++++++++++++++++++++++++++------- 3 files changed, 161 insertions(+), 29 deletions(-) diff --git a/src/app.css b/src/app.css index b8201f9..26751dd 100644 --- a/src/app.css +++ b/src/app.css @@ -655,6 +655,9 @@ button.carousel-dot[disabled].active { padding-right: max(16px, env(safe-area-inset-right)); user-select: none; } +.sheet header :is(h1, h2, h3) { + margin: 0; +} .sheet main { overflow: auto; overflow-x: hidden; diff --git a/src/components/compose.css b/src/components/compose.css index aa6f818..9178744 100644 --- a/src/components/compose.css +++ b/src/components/compose.css @@ -255,16 +255,34 @@ align-items: stretch; } #compose-container .media-preview { - flex-shrink: 1; + flex-shrink: 0; + border: 1px solid var(--outline-color); + border-radius: 4px; + overflow: hidden; + width: 80px; + height: 80px; + /* checkerboard background */ + background-image: linear-gradient( + 45deg, + var(--img-bg-color) 25%, + transparent 25% + ), + linear-gradient(-45deg, var(--img-bg-color) 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, var(--img-bg-color) 75%), + linear-gradient(-45deg, transparent 75%, var(--img-bg-color) 75%); + background-size: 10px 10px; + background-position: 0 0, 0 5px, 5px -5px, -5px 0px; } #compose-container .media-preview > * { - min-width: 80px; - width: 80px !important; + width: 80px; height: 80px; object-fit: contain; - background-color: var(--img-bg-color); - border-radius: 8px; - border: 1px solid var(--outline-color); + vertical-align: middle; + pointer-events: none; +} +#compose-container .media-preview:hover { + box-shadow: 0 0 0 2px var(--link-light-color); + cursor: pointer; } #compose-container .media-attachment textarea { height: 80px; @@ -389,3 +407,39 @@ display: none; } } + +#media-sheet main { + padding-top: 8px; + display: flex; + flex-direction: column; + flex: 1; +} +#media-sheet textarea { + width: 100%; + height: 10em; + margin-top: 8px; +} +#media-sheet .media-preview { + border: 2px solid var(--outline-color); + border-radius: 8px; + overflow: hidden; + box-shadow: 0 2px 16px var(--img-bg-color); + /* checkerboard background */ + background-image: linear-gradient( + 45deg, + var(--img-bg-color) 25%, + transparent 25% + ), + linear-gradient(-45deg, var(--img-bg-color) 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, var(--img-bg-color) 75%), + linear-gradient(-45deg, transparent 75%, var(--img-bg-color) 75%); + background-size: 20px 20px; + background-position: 0 0, 0 10px, 10px -10px, -10px 0px; +} +#media-sheet .media-preview > * { + width: 100%; + height: 100%; + max-height: 50vh; + object-fit: contain; + vertical-align: middle; +} diff --git a/src/components/compose.jsx b/src/components/compose.jsx index 4c084cb..d5d17e8 100644 --- a/src/components/compose.jsx +++ b/src/components/compose.jsx @@ -13,11 +13,13 @@ import emojifyText from '../utils/emojify-text'; import openCompose from '../utils/open-compose'; import states from '../utils/states'; import store from '../utils/store'; +import useDebouncedCallback from '../utils/useDebouncedCallback'; import visibilityIconsMap from '../utils/visibility-icons-map'; import Avatar from './avatar'; import Icon from './icon'; import Loader from './loader'; +import Modal from './modal'; import Status from './status'; const supportedLanguagesMap = supportedLanguages.reduce((acc, l) => { @@ -1090,26 +1092,41 @@ function MediaAttachment({ onDescriptionChange = () => {}, onRemove = () => {}, }) { - const { url, type, id, description } = attachment; + const { url, type, id } = attachment; + console.log({ attachment }); + const [description, setDescription] = useState(attachment.description); const suffixType = type.split('/')[0]; - return ( -
-
- {suffixType === 'image' ? ( - - ) : suffixType === 'video' || suffixType === 'gifv' ? ( -
+ const debouncedOnDescriptionChange = useDebouncedCallback( + onDescriptionChange, + 500, + ); + + const [showModal, setShowModal] = useState(false); + const textareaRef = useRef(null); + useEffect(() => { + let timer; + if (showModal && textareaRef.current) { + timer = setTimeout(() => { + textareaRef.current.focus(); + }, 100); + } + return () => { + clearTimeout(timer); + }; + }, [showModal]); + + const descTextarea = ( + <> {!!id ? (
Uploaded -

{description || No description}

+

+ {attachment.description || No description} +

) : ( )} -
- + {suffixType === 'image' ? ( + + ) : suffixType === 'video' || suffixType === 'gifv' ? ( +
+ {descTextarea} +
+ +
- + {showModal && ( + { + if (e.target === e.currentTarget) { + setShowModal(false); + } + }} + > +
+
+

+ { + { + image: 'Edit image description', + video: 'Edit video description', + audio: 'Edit audio description', + }[suffixType] + } +

+
+
+
+ {suffixType === 'image' ? ( + + ) : suffixType === 'video' || suffixType === 'gifv' ? ( +
+ {descTextarea} +
+
+
+ )} + ); }