From d35619308d3f763ff97256bf1ff24be70a6f5efc Mon Sep 17 00:00:00 2001 From: john Date: Sun, 4 May 2025 23:39:59 +0200 Subject: [PATCH] some imagely stuff --- package.json | 1 + src/components/NewPostWidget.tsx | 94 ++++++++++++++++++-------------- yarn.lock | 5 ++ 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index 41cc063..7d69c88 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dependencies": { "@js-temporal/polyfill": "^0.5.1", "@tailwindcss/vite": "^4.1.5", + "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router": "^7.5.3", diff --git a/src/components/NewPostWidget.tsx b/src/components/NewPostWidget.tsx index b65de69..20b5e0e 100644 --- a/src/components/NewPostWidget.tsx +++ b/src/components/NewPostWidget.tsx @@ -5,48 +5,62 @@ interface NewPostWidgetProps { isSubmitting?: boolean } +interface Thumbnail { + id: string + objectUrl: string +} + export default function NewPostWidget({ onSubmit, isSubmitting = false }: NewPostWidgetProps) { const [content, setContent] = useState('') - const [media, setMedia] = useState([]) - const [mediaPreviewUrls, setMediaPreviewUrls] = useState([]) + const [files, setFiles] = useState<{ id: string; file: File }[]>([]) + const [thumbnails, setThumbnails] = useState([]) const handleContentChange = (e: ChangeEvent) => { setContent(e.target.value) } const handleMediaChange = (e: ChangeEvent) => { - if (e.target.files && e.target.files.length > 0) { - const newFiles = Array.from(e.target.files) - setMedia([...media, ...newFiles]) - - // Create preview URLs for the new files - const newPreviewUrls = newFiles.map((file) => URL.createObjectURL(file)) - setMediaPreviewUrls([...mediaPreviewUrls, ...newPreviewUrls]) + if (!(e.target.files && e.target.files.length > 0)) { + return } + + const newFiles = Array.from(e.target.files).map((file) => ({ + id: crypto.randomUUID(), + file, + })) + + setFiles([...files, ...newFiles]) + + const newThumbnails = newFiles.map((file) => { + return { + id: file.id, + objectUrl: URL.createObjectURL(file.file), + } + }) + + setThumbnails([...thumbnails, ...newThumbnails]) + ;(e.target as HTMLInputElement).value = '' } const handleSubmit = () => { - if (content.trim() || media.length > 0) { - onSubmit(content, media) - setContent('') - setMedia([]) - - // Revoke object URLs to avoid memory leaks - mediaPreviewUrls.forEach((url) => URL.revokeObjectURL(url)) - setMediaPreviewUrls([]) + if (!content.trim() && files.length === 0) { + return } + onSubmit( + content, + files.map((file) => file.file), + ) + setContent('') + setFiles([]) + thumbnails.forEach(({ objectUrl }) => URL.revokeObjectURL(objectUrl)) + setThumbnails([]) } - const handleRemoveMedia = (index: number) => { - const newMedia = [...media] - newMedia.splice(index, 1) - setMedia(newMedia) - - // Revoke the URL of the removed media - URL.revokeObjectURL(mediaPreviewUrls[index]) - const newPreviewUrls = [...mediaPreviewUrls] - newPreviewUrls.splice(index, 1) - setMediaPreviewUrls(newPreviewUrls) + const handleRemoveMedia = (id: string) => { + setFiles(files.filter((file) => file.id !== id)) + const { objectUrl } = thumbnails.find((thumbnail) => thumbnail.id === id)! + URL.revokeObjectURL(objectUrl) + setThumbnails(thumbnails.filter((thumbnail) => thumbnail.id !== id)) } return ( @@ -60,19 +74,17 @@ export default function NewPostWidget({ onSubmit, isSubmitting = false }: NewPos disabled={isSubmitting} /> - {mediaPreviewUrls.length > 0 && ( -
- {mediaPreviewUrls.map((url, index) => ( -
- - -
+ {thumbnails.length > 0 && ( +
+ {thumbnails.map(({ objectUrl, id }) => ( + ))}
)} @@ -92,7 +104,7 @@ export default function NewPostWidget({ onSubmit, isSubmitting = false }: NewPos diff --git a/yarn.lock b/yarn.lock index 6ef9e46..4b81daf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1601,6 +1601,11 @@ ignore@^5.2.0, ignore@^5.3.1: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== +immer@^10.1.1: + version "10.1.1" + resolved "https://registry.yarnpkg.com/immer/-/immer-10.1.1.tgz#206f344ea372d8ea176891545ee53ccc062db7bc" + integrity sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw== + import-fresh@^3.2.1: version "3.3.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf"