refactor: streamline client import pipeline
This commit is contained in:
@@ -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.");
|
||||
|
||||
Reference in New Issue
Block a user