From f9f6d9d5ced67c69afd1c61b57fbb28eeabb8838 Mon Sep 17 00:00:00 2001 From: Shawn Date: Thu, 21 May 2026 23:12:43 -0400 Subject: [PATCH] Fix manual photo UI: both gallery picker + camera button visible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Manual photo area now shows two clear choices: 📁 Choose from Gallery — plain accept=image/* (EXIF preserved) 📸 Take Photo — calls openManualCamera() for quick capture - Each has a label explaining EXIF behavior - openManualCamera() now appends input to DOM before click() (required by mobile Chrome for programmatic file input clicks) - Dynamically created camera input is cleaned up after use - camera-area overflow:visible to not clip the taller placeholder --- static/index.html | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/static/index.html b/static/index.html index ee23efb..07c2c3d 100644 --- a/static/index.html +++ b/static/index.html @@ -991,10 +991,15 @@
📸 Photo (optional)
-
-
- 📸 -
Tap to choose photo
+
+
+
+ +
(preserves EXIF/GPS)
+
+ +
(quick capture, no EXIF)
+
@@ -2614,13 +2619,23 @@ inp.type = 'file'; inp.accept = 'image/*'; inp.capture = 'environment'; + inp.style.display = 'none'; inp.onchange = handleManualPhotoFile; + // Must be in DOM for mobile Chrome to allow programmatic click + document.body.appendChild(inp); inp.click(); + // Clean up after file is picked (or cancelled) + inp.addEventListener('cancel', () => inp.remove()); + // Fallback: remove after a timeout in case 'cancel' doesn't fire + setTimeout(() => { if (inp.parentNode) inp.remove(); }, 60000); } async function handleManualPhotoFile(event) { const file = event.target.files?.[0]; if (!file) return; + // Clean up any dynamically created camera input + const inp = event.target; + if (inp.id !== 'manPhotoInput' && inp.parentNode) inp.remove(); manualPhotoFile = file; manualPhotoBlob = file; // Use original file (preserves EXIF)