From a2f9183011310a5f1323a4aa0c06e54281af47d1 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Sat, 31 Jan 2026 12:19:16 +0100 Subject: [PATCH] fix(03-04): replace CameraCapture with file input capture="environment" - Remove CameraCapture modal which required getUserMedia (HTTPS only) - Use native file input with capture="environment" attribute - Opens camera directly via OS file picker on mobile - Works over HTTP during development - Simpler implementation with better browser compatibility --- src/lib/components/EntryCard.svelte | 46 ++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/lib/components/EntryCard.svelte b/src/lib/components/EntryCard.svelte index 87956b1..05b7918 100644 --- a/src/lib/components/EntryCard.svelte +++ b/src/lib/components/EntryCard.svelte @@ -5,8 +5,7 @@ import { slide } from 'svelte/transition'; import ImageGallery from './ImageGallery.svelte'; import ImageUpload from './ImageUpload.svelte'; - import CameraCapture from './CameraCapture.svelte'; - + interface EntryWithImages extends Entry { images: Image[]; } @@ -21,8 +20,8 @@ let expanded = $state(false); // Image management state - let showCamera = $state(false); let editImagesMode = $state(false); + let cameraInput: HTMLInputElement; // Edit state - use $derived to stay in sync with entry prop let editTitle = $state(entry.title || ''); @@ -49,6 +48,11 @@ let isSwiping = $state(false); function handleTouchStart(e: TouchEvent) { + // Ignore if touch started on a button or interactive element + const target = e.target as HTMLElement; + if (target.closest('button, input, textarea, select, a, [role="button"]')) { + return; + } touchStartX = e.touches[0].clientX; isSwiping = true; } @@ -151,9 +155,22 @@ // invalidateAll is called by ImageUpload, so nothing extra needed here } - function handleCameraCapture() { - showCamera = false; - // invalidateAll is called by CameraCapture + async function handleCameraInput(e: Event) { + const input = e.target as HTMLInputElement; + const file = input.files?.[0]; + if (!file || !file.type.startsWith('image/')) return; + + const formData = new FormData(); + formData.append('image', file); + formData.append('entryId', entry.id); + + await fetch('?/uploadImage', { + method: 'POST', + body: formData + }); + + await invalidateAll(); + input.value = ''; } @@ -357,7 +374,7 @@ + @@ -436,10 +461,3 @@ {/if} -{#if showCamera} - (showCamera = false)} - onCapture={handleCameraCapture} - /> -{/if}