fix: EXIF data now visible in photo preview card

- extractExifData() now async — reads real EXIF tags (Make, Model,
  DateTimeOriginal, ISO, FNumber, ExposureTime, FocalLength, GPS)
  via exifr.parse() and displays them in the UI
- handlePickedPhoto() + reader.onload made async to support this
- GPS extraction already auto-triggers on photo pick (tryExtractGpsFromPicked)
- Server-side exif_data round-trip already functional (verified)
- DNG/RAW-02: .dng allowed, 20MB limit
This commit is contained in:
2026-05-21 22:45:28 -04:00
parent 497d1104c1
commit 02a38a8459
8 changed files with 39 additions and 8 deletions
+39 -8
View File
@@ -1732,15 +1732,15 @@
}
})();
function handlePickedPhoto(file) {
async function handlePickedPhoto(file) {
pickedPhotoFile = file;
const reader = new FileReader();
reader.onload = function(e) {
reader.onload = async function(e) {
document.getElementById('pickedPhotoPreview').src = e.target.result;
document.getElementById('photoPreviewCard').style.display = 'block';
// Extract EXIF / file metadata
extractExifData(file);
await extractExifData(file);
// Auto-extract GPS from the picked photo
tryExtractGpsFromPicked();
@@ -1751,13 +1751,44 @@
reader.readAsDataURL(file);
}
function extractExifData(file) {
async function extractExifData(file) {
const exifDiv = document.getElementById('pickedExifData');
const rows = [];
rows.push({ label: 'File name', value: file.name });
rows.push({ label: 'File size', value: formatFileSize(file.size) });
rows.push({ label: 'Type', value: file.type || 'unknown' });
rows.push({ label: 'Last modified', value: formatDate(new Date(file.lastModified).toISOString()) });
rows.push({ label: '📄 File name', value: file.name });
rows.push({ label: '📦 File size', value: formatFileSize(file.size) });
rows.push({ label: '🏷️ Type', value: file.type || 'unknown' });
rows.push({ label: '🕐 Modified', value: formatDate(new Date(file.lastModified).toISOString()) });
// Try to read actual EXIF tags from the file
try {
const exifData = await exifr.parse(file);
if (exifData) {
if (exifData.Make || exifData.Model) {
rows.push({ label: '📷 Camera', value: [exifData.Make, exifData.Model].filter(Boolean).join(' ') });
}
if (exifData.DateTimeOriginal) {
const d = new Date(exifData.DateTimeOriginal);
rows.push({ label: '📅 Date taken', value: d.toLocaleString() });
}
if (exifData.ISO) {
rows.push({ label: '🎯 ISO', value: String(exifData.ISO) });
}
if (exifData.FNumber) {
rows.push({ label: '🔆 Aperture', value: 'f/' + exifData.FNumber });
}
if (exifData.ExposureTime) {
rows.push({ label: '⏱️ Shutter', value: exifData.ExposureTime + 's' });
}
if (exifData.FocalLength) {
rows.push({ label: '🔭 Focal', value: exifData.FocalLength + 'mm' });
}
if (exifData.GPSLatitude && exifData.GPSLongitude) {
const lat = exifData.latitude || exifData.GPSLatitude;
const lng = exifData.longitude || exifData.GPSLongitude;
rows.push({ label: '📍 GPS', value: typeof lat === 'number' ? `${lat.toFixed(6)}, ${lng.toFixed(6)}` : `${exifData.GPSLatitude.join(' ')} ${exifData.GPSLatitudeRef}, ${exifData.GPSLongitude.join(' ')} ${exifData.GPSLongitudeRef}` });
}
}
} catch (_) { /* EXIF display is best-effort */ }
exifDiv.innerHTML = rows.map(r =>
`<div class="exif-row"><span class="exif-label">${esc(r.label)}</span><span class="exif-value">${esc(r.value)}</span></div>`
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB