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
This commit is contained in:
@@ -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 = '';
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -357,7 +374,7 @@
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => (showCamera = true)}
|
||||
onclick={() => cameraInput?.click()}
|
||||
class="px-4 py-2 border border-gray-300 rounded-lg flex items-center gap-2 hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -376,6 +393,14 @@
|
||||
</svg>
|
||||
Camera
|
||||
</button>
|
||||
<input
|
||||
bind:this={cameraInput}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
capture="environment"
|
||||
onchange={handleCameraInput}
|
||||
class="hidden"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -436,10 +461,3 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if showCamera}
|
||||
<CameraCapture
|
||||
entryId={entry.id}
|
||||
onClose={() => (showCamera = false)}
|
||||
onCapture={handleCameraCapture}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user