fix: Only allow image uploads

This commit is contained in:
April Hall 2025-03-05 09:24:25 -05:00
parent 193bd380c3
commit ae9ab3668d
No known key found for this signature in database
GPG Key ID: A49AC35CB186266C
4 changed files with 18 additions and 6 deletions

View File

@ -10,7 +10,7 @@
const { data }: { data: PageData } = $props(); const { data }: { data: PageData } = $props();
let src = $state(data.user.image ?? `https://api.dicebear.com/9.x/identicon/svg?seed=${data.session?.user.id}`); let src = $state(data.user.image ?? `https://api.dicebear.com/9.x/identicon/svg?seed=${data.session?.user.id}`);
let open: boolean = $state(false); let error: string | null = $state(null);
async function submit(file: File) { async function submit(file: File) {
await generateStream(file).then((res) => { await generateStream(file).then((res) => {
@ -23,6 +23,7 @@
<fieldset class="flex size-full flex-col items-center justify-center gap-3 rounded-lg border p-4"> <fieldset class="flex size-full flex-col items-center justify-center gap-3 rounded-lg border p-4">
<legend class="-ml-1 px-1 text-sm font-medium"> Upload Profile Image </legend> <legend class="-ml-1 px-1 text-sm font-medium"> Upload Profile Image </legend>
<ImageCropper.Root <ImageCropper.Root
bind:error
bind:src bind:src
onCropped={async (url) => { onCropped={async (url) => {
const file = await getFileFromUrl(url); const file = await getFileFromUrl(url);
@ -45,5 +46,6 @@
</ImageCropper.Controls> </ImageCropper.Controls>
</ImageCropper.Dialog> </ImageCropper.Dialog>
</ImageCropper.Root> </ImageCropper.Root>
{#if error}<span class="text-sm text-red-500">{error}</span>{/if}
</fieldset> </fieldset>
</form> </form>

View File

@ -15,7 +15,7 @@
const cropState = useImageCropperCrop(); const cropState = useImageCropperCrop();
</script> </script>
<Button {...rest} {size} {variant} onclick={cropState.onclick}> <Button {...rest} {size} {variant} onclick={cropState.onclick} data-testid="crop">
<ImageUp /> <ImageUp />
<span>Upload</span> <span>Upload</span>
</Button> </Button>

View File

@ -11,7 +11,14 @@
import { onDestroy } from 'svelte'; import { onDestroy } from 'svelte';
import { useId } from 'bits-ui'; import { useId } from 'bits-ui';
let { id = useId(), src = $bindable(''), onCropped = () => {}, children, ...rest }: ImageCropperRootProps = $props(); let {
id = useId(),
src = $bindable(''),
onCropped = () => {},
children,
error = $bindable(null),
...rest
}: ImageCropperRootProps & { error?: string | null } = $props();
const rootState = useImageCropperRoot({ const rootState = useImageCropperRoot({
id: box.with(() => id), id: box.with(() => id),
@ -31,6 +38,12 @@
onchange={(e) => { onchange={(e) => {
const file = e.currentTarget.files?.[0]; const file = e.currentTarget.files?.[0];
if (!file) return; if (!file) return;
// Prevent the user from uploading non-image files
if (file.type.split('/')[0] !== 'image') {
error = 'Please upload a valid image.';
return;
}
error = null;
rootState.onUpload(file); rootState.onUpload(file);
// reset so that we can reupload the same file // reset so that we can reupload the same file
(e.target! as HTMLInputElement).value = ''; (e.target! as HTMLInputElement).value = '';

View File

@ -45,11 +45,8 @@ class ImageCropperRootState {
async onCrop() { async onCrop() {
if (!this.pixelCrop || !this.tempUrl) return; if (!this.pixelCrop || !this.tempUrl) return;
this.opts.src.current = await getCroppedImg(this.tempUrl, this.pixelCrop); this.opts.src.current = await getCroppedImg(this.tempUrl, this.pixelCrop);
this.open = false; this.open = false;
this.opts.onCropped(this.opts.src.current); this.opts.onCropped(this.opts.src.current);
} }