style: unify ui copy and naming
This commit is contained in:
@@ -799,7 +799,7 @@ function htmlPage(): string {
|
|||||||
<div class="layout">
|
<div class="layout">
|
||||||
<aside>
|
<aside>
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Nextcloud Share</h2>
|
<h2>Nextcloud Import</h2>
|
||||||
<p>Paste a public share link to import images directly in the browser.</p>
|
<p>Paste a public share link to import images directly in the browser.</p>
|
||||||
<label>
|
<label>
|
||||||
Share URL
|
Share URL
|
||||||
@@ -866,7 +866,7 @@ function htmlPage(): string {
|
|||||||
<h2>Timeline</h2>
|
<h2>Timeline</h2>
|
||||||
<div class="timeline-summary" id="timeline-summary">No photos imported yet.</div>
|
<div class="timeline-summary" id="timeline-summary">No photos imported yet.</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="secondary" id="timeline-clear" type="button" disabled>Clear range</button>
|
<button class="secondary" id="timeline-clear" type="button" disabled>Reset range</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline-chart" id="timeline-chart">
|
<div class="timeline-chart" id="timeline-chart">
|
||||||
<div class="timeline-bars" id="timeline-bars"></div>
|
<div class="timeline-bars" id="timeline-bars"></div>
|
||||||
@@ -876,7 +876,7 @@ function htmlPage(): string {
|
|||||||
<div class="timeline-axis" id="timeline-axis"></div>
|
<div class="timeline-axis" id="timeline-axis"></div>
|
||||||
<div class="timeline-footer">
|
<div class="timeline-footer">
|
||||||
<span id="timeline-range">All photos</span>
|
<span id="timeline-range">All photos</span>
|
||||||
<span id="timeline-unit">Scale: day</span>
|
<span id="timeline-unit">Scale: Day</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
@@ -946,7 +946,7 @@ function htmlPage(): string {
|
|||||||
const progressDetail = mustGet("progress-detail");
|
const progressDetail = mustGet("progress-detail");
|
||||||
const activitySpinner = mustGet("activity-spinner");
|
const activitySpinner = mustGet("activity-spinner");
|
||||||
const timelineSummary = mustGet("timeline-summary");
|
const timelineSummary = mustGet("timeline-summary");
|
||||||
const timelineClear = mustGet("timeline-clear");
|
const timelineClearButton = mustGet("timeline-clear");
|
||||||
const timelineChart = mustGet("timeline-chart");
|
const timelineChart = mustGet("timeline-chart");
|
||||||
const timelineBars = mustGet("timeline-bars");
|
const timelineBars = mustGet("timeline-bars");
|
||||||
const timelineSelection = mustGet("timeline-selection");
|
const timelineSelection = mustGet("timeline-selection");
|
||||||
@@ -957,10 +957,10 @@ function htmlPage(): string {
|
|||||||
const themeToggle = mustGet("theme-toggle");
|
const themeToggle = mustGet("theme-toggle");
|
||||||
const themeToggleIcon = mustGet("theme-toggle-icon");
|
const themeToggleIcon = mustGet("theme-toggle-icon");
|
||||||
const themeToggleLabel = mustGet("theme-toggle-label");
|
const themeToggleLabel = mustGet("theme-toggle-label");
|
||||||
const shareUrl = mustGet("share-url");
|
const importUrlInput = mustGet("share-url");
|
||||||
const shareStatus = mustGet("share-status");
|
const importStatus = mustGet("share-status");
|
||||||
const loadShare = mustGet("load-share");
|
const importButton = mustGet("load-share");
|
||||||
const cancelShare = mustGet("cancel-share");
|
const stopImportButton = mustGet("cancel-share");
|
||||||
|
|
||||||
function mustGet(id) {
|
function mustGet(id) {
|
||||||
const element = document.getElementById(id);
|
const element = document.getElementById(id);
|
||||||
@@ -1266,9 +1266,9 @@ function htmlPage(): string {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateStatus(message, tone = "info") {
|
function setImportStatus(message, tone = "info") {
|
||||||
shareStatus.textContent = message;
|
importStatus.textContent = message;
|
||||||
shareStatus.style.color = tone === "error" ? "#9d174d" : "var(--muted)";
|
importStatus.style.color = tone === "error" ? "#9d174d" : "var(--muted)";
|
||||||
}
|
}
|
||||||
|
|
||||||
function setProgress(processed, total, detail) {
|
function setProgress(processed, total, detail) {
|
||||||
@@ -1281,8 +1281,8 @@ function htmlPage(): string {
|
|||||||
|
|
||||||
function setImporting(isImporting) {
|
function setImporting(isImporting) {
|
||||||
activitySpinner.classList.toggle("active", isImporting);
|
activitySpinner.classList.toggle("active", isImporting);
|
||||||
loadShare.disabled = isImporting;
|
importButton.disabled = isImporting;
|
||||||
cancelShare.disabled = !isImporting;
|
stopImportButton.disabled = !isImporting;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearObjectUrls() {
|
function clearObjectUrls() {
|
||||||
@@ -1311,15 +1311,15 @@ function htmlPage(): string {
|
|||||||
photoCount.textContent = "0 photos";
|
photoCount.textContent = "0 photos";
|
||||||
timelineSummary.textContent = "No photos imported yet.";
|
timelineSummary.textContent = "No photos imported yet.";
|
||||||
timelineRange.textContent = "All photos";
|
timelineRange.textContent = "All photos";
|
||||||
timelineUnit.textContent = "Scale: day";
|
timelineUnit.textContent = "Scale: Day";
|
||||||
timelineClear.disabled = true;
|
timelineClearButton.disabled = true;
|
||||||
timelineBars.replaceChildren();
|
timelineBars.replaceChildren();
|
||||||
timelineAxis.replaceChildren();
|
timelineAxis.replaceChildren();
|
||||||
timelineSelection.classList.remove("visible");
|
timelineSelection.classList.remove("visible");
|
||||||
timelineSelection.style.left = "0";
|
timelineSelection.style.left = "0";
|
||||||
timelineSelection.style.width = "0";
|
timelineSelection.style.width = "0";
|
||||||
timelineBrush.classList.remove("visible");
|
timelineBrush.classList.remove("visible");
|
||||||
setProgress(0, 0, "ready");
|
setProgress(0, 0, "idle");
|
||||||
}
|
}
|
||||||
|
|
||||||
function openOverlay(photo) {
|
function openOverlay(photo) {
|
||||||
@@ -1414,7 +1414,7 @@ function htmlPage(): string {
|
|||||||
if (start === null || end === null) {
|
if (start === null || end === null) {
|
||||||
state.timelineSelection = null;
|
state.timelineSelection = null;
|
||||||
state.timelineViewport = null;
|
state.timelineViewport = null;
|
||||||
timelineClear.disabled = true;
|
timelineClearButton.disabled = true;
|
||||||
} else {
|
} else {
|
||||||
const normalizedStart = Math.min(start, end);
|
const normalizedStart = Math.min(start, end);
|
||||||
const normalizedEnd = Math.max(start, end);
|
const normalizedEnd = Math.max(start, end);
|
||||||
@@ -1426,7 +1426,7 @@ function htmlPage(): string {
|
|||||||
start: normalizedStart,
|
start: normalizedStart,
|
||||||
end: normalizedEnd
|
end: normalizedEnd
|
||||||
};
|
};
|
||||||
timelineClear.disabled = false;
|
timelineClearButton.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderVisiblePhotos({ fitMap: true });
|
renderVisiblePhotos({ fitMap: true });
|
||||||
@@ -1441,7 +1441,11 @@ function htmlPage(): string {
|
|||||||
const timeline = buildTimeline(timelinePhotos, state.timelineViewport);
|
const timeline = buildTimeline(timelinePhotos, state.timelineViewport);
|
||||||
state.timeline = timeline;
|
state.timeline = timeline;
|
||||||
timelineSummary.textContent = formatTimelineSummary(state.photos, timeline.unit);
|
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();
|
timelineBars.replaceChildren();
|
||||||
timelineAxis.replaceChildren();
|
timelineAxis.replaceChildren();
|
||||||
@@ -1699,7 +1703,7 @@ function htmlPage(): string {
|
|||||||
timelineChart.addEventListener("pointerup", finishTimelinePointer);
|
timelineChart.addEventListener("pointerup", finishTimelinePointer);
|
||||||
timelineChart.addEventListener("pointercancel", finishTimelinePointer);
|
timelineChart.addEventListener("pointercancel", finishTimelinePointer);
|
||||||
|
|
||||||
timelineClear.addEventListener("click", clearTimelineSelection);
|
timelineClearButton.addEventListener("click", clearTimelineSelection);
|
||||||
|
|
||||||
function appendPhoto(photo) {
|
function appendPhoto(photo) {
|
||||||
state.photos.push(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 davBaseUrl = resolveDavBaseUrl(shareUrlValue);
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
"/api/nextcloud/list?share=" + encodeURIComponent(shareUrlValue.trim()),
|
"/api/nextcloud/list?share=" + encodeURIComponent(shareUrlValue.trim()),
|
||||||
@@ -1761,7 +1765,7 @@ function htmlPage(): string {
|
|||||||
return parseListing(await response.text(), davBaseUrl);
|
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), {
|
const response = await fetch("/api/nextcloud/blob?url=" + encodeURIComponent(entry.href), {
|
||||||
signal
|
signal
|
||||||
});
|
});
|
||||||
@@ -1789,7 +1793,7 @@ function htmlPage(): string {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function importFromNextcloud() {
|
async function importFromShare() {
|
||||||
if (activeImportController) {
|
if (activeImportController) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1801,11 +1805,11 @@ function htmlPage(): string {
|
|||||||
try {
|
try {
|
||||||
clearObjectUrls();
|
clearObjectUrls();
|
||||||
clearGallery();
|
clearGallery();
|
||||||
updateStatus("Importing...");
|
setImportStatus("Importing...");
|
||||||
const listing = await loadShareListing(shareUrl.value, controller.signal);
|
const listing = await loadImportListing(importUrlInput.value, controller.signal);
|
||||||
|
|
||||||
if (!listing.length) {
|
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");
|
setProgress(0, listing.length, "checking files");
|
||||||
@@ -1820,7 +1824,7 @@ function htmlPage(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const photo = await readRemotePhoto(entry, controller.signal);
|
const photo = await readRemoteImage(entry, controller.signal);
|
||||||
if (photo.latitude !== null && photo.longitude !== null) {
|
if (photo.latitude !== null && photo.longitude !== null) {
|
||||||
appendPhoto(photo);
|
appendPhoto(photo);
|
||||||
loaded += 1;
|
loaded += 1;
|
||||||
@@ -1833,33 +1837,27 @@ function htmlPage(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processed += 1;
|
processed += 1;
|
||||||
setProgress(
|
setProgress(processed, listing.length, "processed " + processed + " / " + listing.length);
|
||||||
processed,
|
setImportStatus("Importing: " + loaded + " shown, " + skipped + " skipped.");
|
||||||
listing.length,
|
|
||||||
"processed " + processed + " / " + listing.length
|
|
||||||
);
|
|
||||||
updateStatus(
|
|
||||||
"Importing: " + loaded + " shown, " + skipped + " skipped."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loaded) {
|
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" : "") + "."
|
"Import complete: " + loaded + " images imported" + (skipped ? ", " + skipped + " skipped" : "") + "."
|
||||||
);
|
);
|
||||||
setProgress(listing.length, listing.length, "complete");
|
setProgress(listing.length, listing.length, "complete");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (controller.signal.aborted) {
|
if (controller.signal.aborted) {
|
||||||
updateStatus("Import canceled.");
|
setImportStatus("Import stopped.");
|
||||||
setProgress(state.processed, state.total, "canceled");
|
setProgress(state.processed, state.total, "canceled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(error);
|
console.error(error);
|
||||||
updateStatus(
|
setImportStatus(
|
||||||
"Import failed: " + (error instanceof Error ? error.message : "unknown error"),
|
"Import failed: " + (error instanceof Error ? error.message : "unknown error"),
|
||||||
"error"
|
"error"
|
||||||
);
|
);
|
||||||
@@ -1879,18 +1877,18 @@ function htmlPage(): string {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
loadShare.addEventListener("click", () => {
|
importButton.addEventListener("click", () => {
|
||||||
void importFromNextcloud();
|
void importFromShare();
|
||||||
});
|
});
|
||||||
|
|
||||||
cancelShare.addEventListener("click", () => {
|
stopImportButton.addEventListener("click", () => {
|
||||||
if (activeImportController) {
|
if (activeImportController) {
|
||||||
activeImportController.abort("Import canceled by user");
|
activeImportController.abort("Import canceled by user");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
clearGallery();
|
clearGallery();
|
||||||
updateStatus("Ready to import.");
|
setImportStatus("Ready to import.");
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>`;
|
</html>`;
|
||||||
|
|||||||
Reference in New Issue
Block a user