Optimize RAW inspection and add timings v0.8.1

This commit is contained in:
dmo committed 2026-07-25 08:35:22 +02:00
1 parent 4e3c442b26
commit d17bc6a132
6 files changed
+200 -122

No files matched your search

+50 -4
View File
@@ -378,7 +378,10 @@ async function readPhotoMetadata(photo, file) {
try { message = (await response.json()).detail || message; } catch {}
throw new Error(message);
}
const data = await response.json();
applyMetadataResult(photo, await response.json());
}
function applyMetadataResult(photo, data) {
photo.metadataLoaded = true;
photo.metadataPresent = Boolean(data.hasMetadata);
photo.fileValues = data.hasMetadata ? data.values : null;
@@ -391,6 +394,31 @@ async function readPhotoMetadata(photo, file) {
}
}
function base64PreviewUrl(base64, mediaType) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
return URL.createObjectURL(new Blob([bytes], { type: mediaType || 'image/jpeg' }));
}
async function inspectServerPreviewPhoto(photo, file) {
const payload = new FormData();
payload.append('file', file, photo.name);
const response = await fetch('/api/inspect', { method: 'POST', body: payload });
if (!response.ok) {
let message = `Photo inspection failed (${response.status}).`;
try { message = (await response.json()).detail || message; } catch {}
throw new Error(message);
}
const data = await response.json();
const oldUrl = state.thumbUrls.get(photo.name);
if (oldUrl) URL.revokeObjectURL(oldUrl);
const previewUrl = base64PreviewUrl(data.previewBase64, data.previewMediaType);
state.thumbUrls.set(photo.name, previewUrl);
applyMetadataResult(photo, data);
return previewUrl;
}
async function selectPhoto(index, force = false) {
if (index < 0 || index >= state.photos.length || (state.processing && !force)) return;
captureCurrentValues();
@@ -414,9 +442,17 @@ async function selectPhoto(index, force = false) {
if (requiresServerPreview(photo)) {
setSaveStatus('loading', `Rendering ${photo.format} preview…`, photo.name);
}
const previewUrl = await getPreviewUrl(photo, file);
const serverInspectionNeeded = requiresServerPreview(photo)
&& (!state.thumbUrls.has(photo.name) || !photo.metadataLoaded);
const previewUrl = serverInspectionNeeded
? await inspectServerPreviewPhoto(photo, file)
: await getPreviewUrl(photo, file);
if (selectionToken !== state.selectionToken || state.currentIndex !== index) return;
elements.preview.src = previewUrl;
if (serverInspectionNeeded) {
if (!formHasUserInput() && photo.values) restoreValues(photo.values);
updatePhotoStatus(photo);
}
renderFileList();
} catch (error) {
if (selectionToken === state.selectionToken && state.currentIndex === index) {
@@ -574,6 +610,8 @@ async function savePhoto(moveNext) {
payload.append('location_name', values.locationName);
}
const saveStarted = performance.now();
setSaveStatus('saving', 'Uploading and rewriting metadata…', `${photo.name} · large RAW files can take a while`);
const response = await fetch('/api/process', { method: 'POST', body: payload });
if (!response.ok) {
let message = `Save failed (${response.status}).`;
@@ -582,6 +620,9 @@ async function savePhoto(moveNext) {
}
const updatedBlob = await response.blob();
const serverAndTransferSeconds = (performance.now() - saveStarted) / 1000;
setSaveStatus('saving', 'Writing updated file locally…', `${photo.name} · ${serverAndTransferSeconds.toFixed(1)}s processing and transfer`);
const localWriteStarted = performance.now();
const writable = await photo.handle.createWritable({ keepExistingData: false });
try {
await writable.write(updatedBlob);
@@ -590,6 +631,7 @@ async function savePhoto(moveNext) {
await writable.abort().catch(() => {});
throw error;
}
const localWriteSeconds = (performance.now() - localWriteStarted) / 1000;
const updatedFile = await photo.handle.getFile();
photo.size = updatedFile.size;
@@ -602,8 +644,12 @@ async function savePhoto(moveNext) {
photo.metadataLoaded = true;
photo.metadataPresent = true;
saveFolderState();
setSaveStatus('saved', 'Saved in place', formatMetadataSummary(savedValues));
showToast(`Saved ${photo.name}`);
setSaveStatus(
'saved',
'Saved in place',
`${formatMetadataSummary(savedValues)} · ${serverAndTransferSeconds.toFixed(1)}s server/transfer · ${localWriteSeconds.toFixed(1)}s local write`,
);
showToast(`Saved ${photo.name} in ${(serverAndTransferSeconds + localWriteSeconds).toFixed(1)}s`);
updateProgress();
const oldThumb = state.thumbUrls.get(photo.name);
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE_NAME = 'photo-date-editor-v8-0';
const CACHE_NAME = 'photo-date-editor-v8-1';
const SHELL = ['/', '/styles.css', '/app.js', '/manifest.webmanifest', '/vendor/leaflet/leaflet.css', '/vendor/leaflet/leaflet.js'];
self.addEventListener('install', (event) => {