diff --git a/src/components/compose.css b/src/components/compose.css index d62de4701f..f27d83bd06 100644 --- a/src/components/compose.css +++ b/src/components/compose.css @@ -377,6 +377,9 @@ background-size: 10px 10px; background-position: 0 0, 0 5px, 5px -5px, -5px 0px; } +#compose-container .media-preview.dragging-over { + opacity: 0.5; +} #compose-container .media-preview > * { width: 80px; height: 80px; diff --git a/src/components/compose.jsx b/src/components/compose.jsx index ea7574aff8..04a0e1ac47 100644 --- a/src/components/compose.jsx +++ b/src/components/compose.jsx @@ -254,6 +254,8 @@ function Compose({ ); const prevLanguage = useRef(language); const [mediaAttachments, setMediaAttachments] = useState([]); + const [draggingAttachment, setDraggingAttachment] = useState(null); + const [draggingOver, setDraggingOver] = useState(null); const [poll, setPoll] = useState(null); const prefs = store.account.get('preferences') || {}; @@ -1252,6 +1254,40 @@ function Compose({ return newAttachments; }); }} + draggingOver={draggingOver === i} + onDragStart={(e) => { + setDraggingAttachment(i); + e.dataTransfer.dropEffect = 'move'; + }} + onDragEnter={() => setDraggingOver(i)} + onDragLeave={() => setDraggingOver(null)} + onDragEnd={() => { + setDraggingAttachment(null); + setDraggingOver(null); + }} + onDrop={(e) => { + const from = draggingAttachment; + const to = i; + if (from == null || from === to) return; + setMediaAttachments((attachments) => { + if (to < from) { + return [ + ...attachments.slice(0, to), + attachments[from], + ...attachments.slice(to, from), + ...attachments.slice(from + 1), + ]; + } else { + return [ + ...attachments.slice(0, from), + ...attachments.slice(from + 1, to + 1), + attachments[from], + ...attachments.slice(to + 1), + ]; + } + }); + e.stopPropagation(); + }} onRemove={() => { setMediaAttachments((attachments) => { return attachments.filter((_, j) => j !== i); @@ -2114,6 +2150,12 @@ function MediaAttachment({ disabled, lang, onDescriptionChange = () => {}, + draggingOver, + onDragStart, + onDragEnd, + onDragEnter, + onDragLeave, + onDrop, onRemove = () => {}, }) { const { i18n } = useLingui(); @@ -2329,8 +2371,15 @@ function MediaAttachment({ <>