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.");