diff --git a/src/server/request-handler.ts b/src/server/request-handler.ts index 906944e..91f88d4 100644 --- a/src/server/request-handler.ts +++ b/src/server/request-handler.ts @@ -799,7 +799,7 @@ function htmlPage(): string {
- +
@@ -876,7 +876,7 @@ function htmlPage(): string {
@@ -946,7 +946,7 @@ function htmlPage(): string { const progressDetail = mustGet("progress-detail"); const activitySpinner = mustGet("activity-spinner"); const timelineSummary = mustGet("timeline-summary"); - const timelineClear = mustGet("timeline-clear"); + const timelineClearButton = mustGet("timeline-clear"); const timelineChart = mustGet("timeline-chart"); const timelineBars = mustGet("timeline-bars"); const timelineSelection = mustGet("timeline-selection"); @@ -957,10 +957,10 @@ function htmlPage(): string { const themeToggle = mustGet("theme-toggle"); const themeToggleIcon = mustGet("theme-toggle-icon"); const themeToggleLabel = mustGet("theme-toggle-label"); - const shareUrl = mustGet("share-url"); - const shareStatus = mustGet("share-status"); - const loadShare = mustGet("load-share"); - const cancelShare = mustGet("cancel-share"); + const importUrlInput = mustGet("share-url"); + const importStatus = mustGet("share-status"); + const importButton = mustGet("load-share"); + const stopImportButton = mustGet("cancel-share"); function mustGet(id) { const element = document.getElementById(id); @@ -1266,9 +1266,9 @@ function htmlPage(): string { }; } - function updateStatus(message, tone = "info") { - shareStatus.textContent = message; - shareStatus.style.color = tone === "error" ? "#9d174d" : "var(--muted)"; + function setImportStatus(message, tone = "info") { + importStatus.textContent = message; + importStatus.style.color = tone === "error" ? "#9d174d" : "var(--muted)"; } function setProgress(processed, total, detail) { @@ -1281,8 +1281,8 @@ function htmlPage(): string { function setImporting(isImporting) { activitySpinner.classList.toggle("active", isImporting); - loadShare.disabled = isImporting; - cancelShare.disabled = !isImporting; + importButton.disabled = isImporting; + stopImportButton.disabled = !isImporting; } function clearObjectUrls() { @@ -1311,15 +1311,15 @@ function htmlPage(): string { photoCount.textContent = "0 photos"; timelineSummary.textContent = "No photos imported yet."; timelineRange.textContent = "All photos"; - timelineUnit.textContent = "Scale: day"; - timelineClear.disabled = true; + timelineUnit.textContent = "Scale: Day"; + timelineClearButton.disabled = true; timelineBars.replaceChildren(); timelineAxis.replaceChildren(); timelineSelection.classList.remove("visible"); timelineSelection.style.left = "0"; timelineSelection.style.width = "0"; timelineBrush.classList.remove("visible"); - setProgress(0, 0, "ready"); + setProgress(0, 0, "idle"); } function openOverlay(photo) { @@ -1414,7 +1414,7 @@ function htmlPage(): string { if (start === null || end === null) { state.timelineSelection = null; state.timelineViewport = null; - timelineClear.disabled = true; + timelineClearButton.disabled = true; } else { const normalizedStart = Math.min(start, end); const normalizedEnd = Math.max(start, end); @@ -1426,7 +1426,7 @@ function htmlPage(): string { start: normalizedStart, end: normalizedEnd }; - timelineClear.disabled = false; + timelineClearButton.disabled = false; } renderVisiblePhotos({ fitMap: true }); @@ -1441,7 +1441,11 @@ function htmlPage(): string { const timeline = buildTimeline(timelinePhotos, state.timelineViewport); state.timeline = timeline; timelineSummary.textContent = formatTimelineSummary(state.photos, timeline.unit); - timelineUnit.textContent = "Scale: " + timeline.unit + (state.timelineSelection ? " · zoomed" : ""); + timelineUnit.textContent = + "Scale: " + + timeline.unit.charAt(0).toUpperCase() + + timeline.unit.slice(1) + + (state.timelineSelection ? " · zoomed" : ""); timelineBars.replaceChildren(); timelineAxis.replaceChildren(); @@ -1699,7 +1703,7 @@ function htmlPage(): string { timelineChart.addEventListener("pointerup", finishTimelinePointer); timelineChart.addEventListener("pointercancel", finishTimelinePointer); - timelineClear.addEventListener("click", clearTimelineSelection); + timelineClearButton.addEventListener("click", clearTimelineSelection); function appendPhoto(photo) { state.photos.push(photo); @@ -1745,7 +1749,7 @@ function htmlPage(): string { }); } - async function loadShareListing(shareUrlValue, signal) { + async function loadImportListing(shareUrlValue, signal) { const davBaseUrl = resolveDavBaseUrl(shareUrlValue); const response = await fetch( "/api/nextcloud/list?share=" + encodeURIComponent(shareUrlValue.trim()), @@ -1761,7 +1765,7 @@ function htmlPage(): string { return parseListing(await response.text(), davBaseUrl); } - async function readRemotePhoto(entry, signal) { + async function readRemoteImage(entry, signal) { const response = await fetch("/api/nextcloud/blob?url=" + encodeURIComponent(entry.href), { signal }); @@ -1789,7 +1793,7 @@ function htmlPage(): string { }; } - async function importFromNextcloud() { + async function importFromShare() { if (activeImportController) { return; } @@ -1801,11 +1805,11 @@ function htmlPage(): string { try { clearObjectUrls(); clearGallery(); - updateStatus("Importing..."); - const listing = await loadShareListing(shareUrl.value, controller.signal); + setImportStatus("Importing..."); + const listing = await loadImportListing(importUrlInput.value, controller.signal); if (!listing.length) { - throw new Error("No images were found in the share."); + throw new Error("No images found in the share."); } setProgress(0, listing.length, "checking files"); @@ -1820,7 +1824,7 @@ function htmlPage(): string { } try { - const photo = await readRemotePhoto(entry, controller.signal); + const photo = await readRemoteImage(entry, controller.signal); if (photo.latitude !== null && photo.longitude !== null) { appendPhoto(photo); loaded += 1; @@ -1833,33 +1837,27 @@ function htmlPage(): string { } processed += 1; - setProgress( - processed, - listing.length, - "processed " + processed + " / " + listing.length - ); - updateStatus( - "Importing: " + loaded + " shown, " + skipped + " skipped." - ); + setProgress(processed, listing.length, "processed " + processed + " / " + listing.length); + setImportStatus("Importing: " + loaded + " shown, " + skipped + " skipped."); } if (!loaded) { - throw new Error("No images with GPS data were found."); + throw new Error("No images with GPS data found."); } - updateStatus( + setImportStatus( "Import complete: " + loaded + " images imported" + (skipped ? ", " + skipped + " skipped" : "") + "." ); setProgress(listing.length, listing.length, "complete"); } catch (error) { if (controller.signal.aborted) { - updateStatus("Import canceled."); + setImportStatus("Import stopped."); setProgress(state.processed, state.total, "canceled"); return; } console.error(error); - updateStatus( + setImportStatus( "Import failed: " + (error instanceof Error ? error.message : "unknown error"), "error" ); @@ -1879,18 +1877,18 @@ function htmlPage(): string { } }); - loadShare.addEventListener("click", () => { - void importFromNextcloud(); + importButton.addEventListener("click", () => { + void importFromShare(); }); - cancelShare.addEventListener("click", () => { + stopImportButton.addEventListener("click", () => { if (activeImportController) { activeImportController.abort("Import canceled by user"); } }); clearGallery(); - updateStatus("Ready to import."); + setImportStatus("Ready to import."); `;