refactor: streamline client import pipeline

This commit is contained in:
2026-06-13 08:28:34 +02:00
parent ee753331ce
commit df17afeb41

View File

@@ -26,6 +26,7 @@ const state = {
};
let activeImportController = null;
const IMPORT_RENDER_INTERVAL_MS = 180;
const IMPORT_CONCURRENCY = 2;
let scheduledRenderFrame = null;
let scheduledRenderTimer = null;
let scheduledRenderOptions = { fitMap: false };
@@ -908,14 +909,19 @@ async function readRemoteImage(entry, shareUrlValue, signal) {
const capturedAt =
normalizeExifDate(tags?.DateTimeOriginal?.value ?? tags?.DateTimeOriginal) ||
parseDateOrNull(entry.lastModified);
if (gps?.latitude === undefined || gps?.longitude === undefined) {
return null;
}
const thumbUrl = await createThumbnailObjectUrl(blob);
state.objectUrls.push(thumbUrl);
return {
id: entry.href,
name: entry.name,
latitude: gps?.latitude ?? null,
longitude: gps?.longitude ?? null,
latitude: gps.latitude,
longitude: gps.longitude,
capturedAt,
thumbUrl,
fullUrl,
@@ -923,6 +929,50 @@ async function readRemoteImage(entry, shareUrlValue, signal) {
};
}
async function processImportEntries(listing, shareUrlValue, signal) {
let loaded = 0;
let skipped = 0;
let processed = 0;
let nextIndex = 0;
async function importWorker() {
while (nextIndex < listing.length) {
if (signal.aborted) {
throw signal.reason ?? new Error("Import canceled");
}
const entry = listing[nextIndex];
nextIndex += 1;
try {
const photo = await readRemoteImage(entry, shareUrlValue, signal);
if (photo) {
appendPhoto(photo);
loaded += 1;
} else {
skipped += 1;
}
} catch (error) {
if (signal.aborted) {
throw signal.reason ?? error;
}
skipped += 1;
console.error(error);
}
processed += 1;
setProgress(processed, listing.length, "processed " + processed + " / " + listing.length);
setImportStatus("Importing: " + loaded + " shown, " + skipped + " skipped.");
await new Promise((resolve) => setTimeout(resolve, 0));
}
}
const workerCount = Math.min(IMPORT_CONCURRENCY, listing.length);
await Promise.all(Array.from({ length: workerCount }, () => importWorker()));
return { loaded, skipped };
}
async function importFromShare() {
if (activeImportController) {
return;
@@ -945,32 +995,7 @@ async function importFromShare() {
setProgress(0, listing.length, "checking files");
let loaded = 0;
let skipped = 0;
let processed = 0;
for (const entry of listing) {
if (controller.signal.aborted) {
throw controller.signal.reason ?? new Error("Import canceled");
}
try {
const photo = await readRemoteImage(entry, importUrlInput.value, controller.signal);
if (photo.latitude !== null && photo.longitude !== null) {
appendPhoto(photo);
loaded += 1;
} else {
skipped += 1;
}
} catch (error) {
skipped += 1;
console.error(error);
}
processed += 1;
setProgress(processed, listing.length, "processed " + processed + " / " + listing.length);
setImportStatus("Importing: " + loaded + " shown, " + skipped + " skipped.");
}
const { loaded, skipped } = await processImportEntries(listing, importUrlInput.value, controller.signal);
if (!loaded) {
throw new Error("No images with GPS data found.");