Add binary RAW inspection and diagnostics v0.8.2

This commit is contained in:
dmo committed 2026-07-25 08:37:29 +02:00
1 parent d17bc6a132
commit 2dee67021e
6 files changed
+87 -26

No files matched your search

+26 -11
View File
@@ -356,7 +356,10 @@ function formatMetadataSummary(values) {
function updatePhotoStatus(photo) {
const values = photo.fileValues || photo.values;
if (photo.status === 'saved') {
setSaveStatus('saved', 'Previously saved', formatMetadataSummary(values));
const timing = photo.lastSaveTiming
? ` · ${photo.lastSaveTiming.total.toFixed(1)}s total · ${photo.lastSaveTiming.serverTransfer.toFixed(1)}s server/transfer · ${photo.lastSaveTiming.localWrite.toFixed(1)}s local write`
: '';
setSaveStatus('saved', 'Previously saved', `${formatMetadataSummary(values)}${timing}`);
} else if (photo.status === 'skipped') {
setSaveStatus('skipped', 'Previously skipped', 'No metadata was written to this file.');
} else if (photo.status === 'failed') {
@@ -394,13 +397,6 @@ function applyMetadataResult(photo, data) {
}
}
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);
@@ -410,10 +406,20 @@ async function inspectServerPreviewPhoto(photo, file) {
try { message = (await response.json()).detail || message; } catch {}
throw new Error(message);
}
const data = await response.json();
const buffer = await response.arrayBuffer();
if (buffer.byteLength < 5) throw new Error('The server returned an incomplete inspection response.');
const view = new DataView(buffer);
const metadataLength = view.getUint32(0, false);
if (metadataLength < 2 || metadataLength > buffer.byteLength - 4) {
throw new Error('The server returned an invalid inspection response.');
}
const metadataBytes = new Uint8Array(buffer, 4, metadataLength);
const data = JSON.parse(new TextDecoder().decode(metadataBytes));
const previewBytes = new Uint8Array(buffer, 4 + metadataLength);
if (!previewBytes.length) throw new Error('The server returned no preview image.');
const oldUrl = state.thumbUrls.get(photo.name);
if (oldUrl) URL.revokeObjectURL(oldUrl);
const previewUrl = base64PreviewUrl(data.previewBase64, data.previewMediaType);
const previewUrl = URL.createObjectURL(new Blob([previewBytes], { type: 'image/jpeg' }));
state.thumbUrls.set(photo.name, previewUrl);
applyMetadataResult(photo, data);
return previewUrl;
@@ -632,6 +638,7 @@ async function savePhoto(moveNext) {
throw error;
}
const localWriteSeconds = (performance.now() - localWriteStarted) / 1000;
const totalSaveSeconds = serverAndTransferSeconds + localWriteSeconds;
const updatedFile = await photo.handle.getFile();
photo.size = updatedFile.size;
@@ -643,13 +650,21 @@ async function savePhoto(moveNext) {
photo.fileValues = { ...savedValues };
photo.metadataLoaded = true;
photo.metadataPresent = true;
photo.lastSaveTiming = {
total: totalSaveSeconds,
serverTransfer: serverAndTransferSeconds,
localWrite: localWriteSeconds,
};
saveFolderState();
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`);
showToast(
`Saved ${photo.name}: ${totalSaveSeconds.toFixed(1)}s total · `
+ `${serverAndTransferSeconds.toFixed(1)}s server/transfer · ${localWriteSeconds.toFixed(1)}s local write`,
);
updateProgress();
const oldThumb = state.thumbUrls.get(photo.name);
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE_NAME = 'photo-date-editor-v8-1';
const CACHE_NAME = 'photo-date-editor-v8-2';
const SHELL = ['/', '/styles.css', '/app.js', '/manifest.webmanifest', '/vendor/leaflet/leaflet.css', '/vendor/leaflet/leaflet.js'];
self.addEventListener('install', (event) => {