gallery: split Take Photo vs Pick from Gallery inputs

- Two dedicated <input> elements: cameraInput (capture=environment) for
  direct camera, galleryInput (no capture) for gallery picker
- Both wired to handlePickedPhoto() via a shared wireInput helper
- refreshGPS() fires on button click (before picker opens) for a fresh
  high-accuracy GPS fix — no maximumAge, so it pulls current location
  instead of relying on cached values from page-load initGPS()
- Workaround for browser EXIF GPS stripping: camera captures may preserve
  EXIF GPS, gallery picks fall through to device geolocation API
This commit is contained in:
2026-05-21 15:29:03 -04:00
parent 09d83da4e2
commit e16f2ec90f
+36 -11
View File
@@ -1213,8 +1213,9 @@
TAB: ADD ASSET (Barcode / OCR / Manual)
═══════════════════════════════════════════════════════════════════════ -->
<div id="tabAddAsset" class="tab-panel active">
<!-- Hidden photo picker input -->
<input type="file" id="photoPicker" accept="image/*" capture="environment" style="display:none;">
<!-- Hidden photo inputs: dedicated camera + gallery (EXIF stripping workaround) -->
<input type="file" id="cameraInput" accept="image/*" capture="environment" style="display:none;">
<input type="file" id="galleryInput" accept="image/*" style="display:none;">
<!-- Mode Toggles -->
<div class="mode-toggles">
<button class="mode-toggle active" data-mode="barcode" onclick="setAddAssetMode('barcode')">📷 Scan</button>
@@ -1238,7 +1239,8 @@
<div id="scanStatus" class="status-bar">Point camera at a barcode or sticker</div>
<div id="scanResult" class="scan-result" style="display:none;"></div>
<div style="display:flex;gap:6px;margin-top:6px;">
<button class="btn btn-outline btn-sm" onclick="document.getElementById('photoPicker').click()" style="flex:1;">📱 Pick from Gallery</button>
<button class="btn btn-outline btn-sm" onclick="refreshGPS();document.getElementById('cameraInput').click()" style="flex:1;">📸 Take Photo</button>
<button class="btn btn-outline btn-sm" onclick="refreshGPS();document.getElementById('galleryInput').click()" style="flex:1;">📱 Pick from Gallery</button>
</div>
</div>
@@ -2369,6 +2371,25 @@
);
}
// Refresh GPS fix on demand (called when user taps Take Photo / Pick from Gallery)
function refreshGPS() {
if (!navigator.geolocation) return;
navigator.geolocation.getCurrentPosition(
pos => {
AppState.gpsLat = pos.coords.latitude;
AppState.gpsLng = pos.coords.longitude;
AppState.gpsAcc = pos.coords.accuracy;
const badge = document.getElementById('gpsBadge');
if (badge) {
badge.className = 'gps-badge ok';
badge.textContent = `📍 ${AppState.gpsLat.toFixed(4)}, ${AppState.gpsLng.toFixed(4)}`;
}
},
() => {}, // silent fail — keep existing fix if user denies
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 0 }
);
}
// =========================================================================
// TOAST
// =========================================================================
@@ -2594,16 +2615,20 @@
let pickedPhotoFile = null;
let pickedPhotoGps = null; // { lat, lng, accuracy } from EXIF
// Wire the hidden file input
// Wire the hidden file inputs (camera + gallery — two paths for EXIF GPS workaround)
(function() {
const pp = document.getElementById('photoPicker');
if (pp) {
pp.addEventListener('change', function(e) {
if (e.target.files && e.target.files[0]) {
handlePickedPhoto(e.target.files[0]);
}
});
function wireInput(id) {
const el = document.getElementById(id);
if (el) {
el.addEventListener('change', function(e) {
if (e.target.files && e.target.files[0]) {
handlePickedPhoto(e.target.files[0]);
}
});
}
}
wireInput('cameraInput');
wireInput('galleryInput');
})();
function handlePickedPhoto(file) {