feat: localize ui and remove demo mode
This commit is contained in:
@@ -33,7 +33,7 @@ function resolveDavUrlFromShareUrl(shareUrl: string): string {
|
|||||||
return `${url.origin}/public.php/dav/files/${davShare[1]}/`;
|
return `${url.origin}/public.php/dav/files/${davShare[1]}/`;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Bitte einen öffentlichen Nextcloud-Share-Link einfügen.");
|
throw new Error("Please enter a public Nextcloud share link.");
|
||||||
}
|
}
|
||||||
|
|
||||||
async function proxyUpstream(url: string, init?: RequestInit) {
|
async function proxyUpstream(url: string, init?: RequestInit) {
|
||||||
@@ -47,45 +47,6 @@ async function proxyUpstream(url: string, init?: RequestInit) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const demoPhotos: Photo[] = [
|
|
||||||
{
|
|
||||||
id: "demo-1",
|
|
||||||
name: "berlin-brandenburg-gate.jpg",
|
|
||||||
latitude: 52.516275,
|
|
||||||
longitude: 13.377704,
|
|
||||||
capturedAt: "2026-06-07T08:20:00.000Z",
|
|
||||||
thumbUrl:
|
|
||||||
"https://images.unsplash.com/photo-1467269204594-9661b134dd2b?auto=format&fit=crop&w=240&q=60",
|
|
||||||
fullUrl:
|
|
||||||
"https://images.unsplash.com/photo-1467269204594-9661b134dd2b?auto=format&fit=crop&w=1600&q=80",
|
|
||||||
source: "demo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "demo-2",
|
|
||||||
name: "museum-island.jpg",
|
|
||||||
latitude: 52.5169,
|
|
||||||
longitude: 13.4015,
|
|
||||||
capturedAt: "2026-06-07T08:42:00.000Z",
|
|
||||||
thumbUrl:
|
|
||||||
"https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?auto=format&fit=crop&w=240&q=60",
|
|
||||||
fullUrl:
|
|
||||||
"https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?auto=format&fit=crop&w=1600&q=80",
|
|
||||||
source: "demo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "demo-3",
|
|
||||||
name: "alexanderplatz.jpg",
|
|
||||||
latitude: 52.521918,
|
|
||||||
longitude: 13.413215,
|
|
||||||
capturedAt: "2026-06-07T09:05:00.000Z",
|
|
||||||
thumbUrl:
|
|
||||||
"https://images.unsplash.com/photo-1494526585095-c41746248156?auto=format&fit=crop&w=240&q=60",
|
|
||||||
fullUrl:
|
|
||||||
"https://images.unsplash.com/photo-1494526585095-c41746248156?auto=format&fit=crop&w=1600&q=80",
|
|
||||||
source: "demo"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
function htmlPage(): string {
|
function htmlPage(): string {
|
||||||
return `<!doctype html>
|
return `<!doctype html>
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
@@ -228,6 +189,24 @@ function htmlPage(): string {
|
|||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon svg {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary {
|
.primary {
|
||||||
@@ -354,6 +333,15 @@ function htmlPage(): string {
|
|||||||
font-size: 0.82rem;
|
font-size: 0.82rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
padding: 14px;
|
||||||
|
border-radius: 14px;
|
||||||
|
border: 1px dashed rgba(15, 23, 42, 0.16);
|
||||||
|
color: var(--muted);
|
||||||
|
background: rgba(255, 255, 255, 0.45);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -464,33 +452,48 @@ function htmlPage(): string {
|
|||||||
<header>
|
<header>
|
||||||
<div class="brand">
|
<div class="brand">
|
||||||
<h1>mapy-mg</h1>
|
<h1>mapy-mg</h1>
|
||||||
<p>Fotos laden, EXIF lokal im Browser auslesen und auf OpenStreetMap anzeigen.</p>
|
<p>Load photos, read EXIF locally in the browser, and show them on OpenStreetMap.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">Client-only Import · kein Bildspeicher auf dem Server</div>
|
<div class="meta">Client-side import · no image storage on the server</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<aside>
|
<aside>
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Nextcloud Share</h2>
|
<h2>Nextcloud Share</h2>
|
||||||
<p>Public share-Link einfügen. Die App lädt die Bilder direkt im Browser und extrahiert die GPS-Daten lokal.</p>
|
<p>Paste a public share link. The app loads the images in the browser and extracts GPS data locally.</p>
|
||||||
<label>
|
<label>
|
||||||
Share-Link
|
Share URL
|
||||||
<input
|
<input
|
||||||
id="share-url"
|
id="share-url"
|
||||||
value="https://cloud.br0tkasten.de/index.php/s/cjYjeSYZwgLJNBT"
|
placeholder="https://cloud.example.com/index.php/s/..."
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div class="button-row">
|
<div class="button-row">
|
||||||
<button class="primary" id="load-share" type="button">Share laden</button>
|
<button class="primary" id="load-share" type="button">
|
||||||
<button class="danger" id="cancel-share" type="button" disabled>Abbrechen</button>
|
<span class="button-icon" aria-hidden="true">
|
||||||
<button class="secondary" id="use-demo" type="button">Demo anzeigen</button>
|
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8 2v7" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
|
||||||
|
<path d="M5 6.5 8 9.5 11 6.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M3 12.5h10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>Load share</span>
|
||||||
|
</button>
|
||||||
|
<button class="danger" id="cancel-share" type="button" disabled>
|
||||||
|
<span class="button-icon" aria-hidden="true">
|
||||||
|
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>Cancel</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-row">
|
<div class="status-row">
|
||||||
<span class="spinner" id="activity-spinner" aria-hidden="true"></span>
|
<span class="spinner" id="activity-spinner" aria-hidden="true"></span>
|
||||||
<div class="status" id="share-status">Demo-Daten aktiv.</div>
|
<div class="status" id="share-status">Ready to load a share.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress" aria-label="Ladefortschritt">
|
<div class="progress" aria-label="Ladefortschritt">
|
||||||
<div class="progress-bar" aria-hidden="true">
|
<div class="progress-bar" aria-hidden="true">
|
||||||
@@ -498,21 +501,23 @@ function htmlPage(): string {
|
|||||||
</div>
|
</div>
|
||||||
<div class="progress-meta">
|
<div class="progress-meta">
|
||||||
<span id="progress-text">0 / 0</span>
|
<span id="progress-text">0 / 0</span>
|
||||||
<span id="progress-detail">bereit</span>
|
<span id="progress-detail">ready</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<small>Hinweis: Öffentliche Nextcloud-Shares werden per WebDAV gelesen.</small>
|
<small>Public Nextcloud shares are read via WebDAV.</small>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Fotos</h2>
|
<h2>Photos</h2>
|
||||||
<small id="photo-count" class="muted">0 Bilder</small>
|
<small id="photo-count" class="muted">0 photos</small>
|
||||||
<div id="photo-list" class="list"></div>
|
<div id="photo-list" class="list">
|
||||||
|
<div class="empty-state" id="empty-state">No images loaded yet.</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="map-label">Hover: Thumbnail · Klick: Vollbild · Route: zeitlich sortiert</div>
|
<div class="map-label">Hover: thumbnail · click: fullscreen · route: time sorted</div>
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
@@ -520,8 +525,15 @@ function htmlPage(): string {
|
|||||||
<div class="overlay" id="overlay" aria-hidden="true">
|
<div class="overlay" id="overlay" aria-hidden="true">
|
||||||
<div class="overlay-card">
|
<div class="overlay-card">
|
||||||
<header>
|
<header>
|
||||||
<strong id="overlay-title">Foto</strong>
|
<strong id="overlay-title">Photo</strong>
|
||||||
<button class="close" id="close-overlay" type="button">Schließen</button>
|
<button class="close" id="close-overlay" type="button">
|
||||||
|
<span class="button-icon" aria-hidden="true">
|
||||||
|
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>Close</span>
|
||||||
|
</button>
|
||||||
</header>
|
</header>
|
||||||
<img id="overlay-image" alt="" />
|
<img id="overlay-image" alt="" />
|
||||||
</div>
|
</div>
|
||||||
@@ -531,9 +543,8 @@ function htmlPage(): string {
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
import exifr from "https://cdn.jsdelivr.net/npm/exifr@7.1.3/+esm";
|
import exifr from "https://cdn.jsdelivr.net/npm/exifr@7.1.3/+esm";
|
||||||
|
|
||||||
const DEMO_PHOTOS = ${JSON.stringify(demoPhotos)};
|
|
||||||
const state = {
|
const state = {
|
||||||
photos: DEMO_PHOTOS,
|
photos: [],
|
||||||
objectUrls: [],
|
objectUrls: [],
|
||||||
processed: 0,
|
processed: 0,
|
||||||
total: 0
|
total: 0
|
||||||
@@ -558,6 +569,7 @@ function htmlPage(): string {
|
|||||||
const overlayImage = mustGet("overlay-image");
|
const overlayImage = mustGet("overlay-image");
|
||||||
const closeOverlay = mustGet("close-overlay");
|
const closeOverlay = mustGet("close-overlay");
|
||||||
const photoList = mustGet("photo-list");
|
const photoList = mustGet("photo-list");
|
||||||
|
const emptyState = mustGet("empty-state");
|
||||||
const photoCount = mustGet("photo-count");
|
const photoCount = mustGet("photo-count");
|
||||||
const progressFill = mustGet("progress-fill");
|
const progressFill = mustGet("progress-fill");
|
||||||
const progressText = mustGet("progress-text");
|
const progressText = mustGet("progress-text");
|
||||||
@@ -567,7 +579,6 @@ function htmlPage(): string {
|
|||||||
const shareStatus = mustGet("share-status");
|
const shareStatus = mustGet("share-status");
|
||||||
const loadShare = mustGet("load-share");
|
const loadShare = mustGet("load-share");
|
||||||
const cancelShare = mustGet("cancel-share");
|
const cancelShare = mustGet("cancel-share");
|
||||||
const useDemo = mustGet("use-demo");
|
|
||||||
|
|
||||||
function mustGet(id) {
|
function mustGet(id) {
|
||||||
const element = document.getElementById(id);
|
const element = document.getElementById(id);
|
||||||
@@ -629,7 +640,6 @@ function htmlPage(): string {
|
|||||||
function setImporting(isImporting) {
|
function setImporting(isImporting) {
|
||||||
activitySpinner.classList.toggle("active", isImporting);
|
activitySpinner.classList.toggle("active", isImporting);
|
||||||
loadShare.disabled = isImporting;
|
loadShare.disabled = isImporting;
|
||||||
useDemo.disabled = isImporting;
|
|
||||||
cancelShare.disabled = !isImporting;
|
cancelShare.disabled = !isImporting;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,9 +654,9 @@ function htmlPage(): string {
|
|||||||
state.photos = [];
|
state.photos = [];
|
||||||
markers.clearLayers();
|
markers.clearLayers();
|
||||||
route.setLatLngs([]);
|
route.setLatLngs([]);
|
||||||
photoList.replaceChildren();
|
photoList.replaceChildren(emptyState);
|
||||||
photoCount.textContent = "0 Bilder";
|
photoCount.textContent = "0 photos";
|
||||||
setProgress(0, 0, "bereit");
|
setProgress(0, 0, "ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
function openOverlay(photo) {
|
function openOverlay(photo) {
|
||||||
@@ -686,7 +696,10 @@ function htmlPage(): string {
|
|||||||
|
|
||||||
function appendPhoto(photo) {
|
function appendPhoto(photo) {
|
||||||
state.photos.push(photo);
|
state.photos.push(photo);
|
||||||
photoCount.textContent = state.photos.length + (state.photos.length === 1 ? " Bild" : " Bilder");
|
photoCount.textContent = state.photos.length + (state.photos.length === 1 ? " photo" : " photos");
|
||||||
|
if (emptyState.isConnected) {
|
||||||
|
emptyState.remove();
|
||||||
|
}
|
||||||
|
|
||||||
if (photo.latitude !== null && photo.longitude !== null) {
|
if (photo.latitude !== null && photo.longitude !== null) {
|
||||||
const marker = L.marker([photo.latitude, photo.longitude]).addTo(markers);
|
const marker = L.marker([photo.latitude, photo.longitude]).addTo(markers);
|
||||||
@@ -696,7 +709,7 @@ function htmlPage(): string {
|
|||||||
'<img src="' + photo.thumbUrl + '" alt="' + photo.name + '" />' +
|
'<img src="' + photo.thumbUrl + '" alt="' + photo.name + '" />' +
|
||||||
'<strong>' + photo.name + '</strong>' +
|
'<strong>' + photo.name + '</strong>' +
|
||||||
'<small>' + formatDate(photo.capturedAt) + '</small>' +
|
'<small>' + formatDate(photo.capturedAt) + '</small>' +
|
||||||
'<button type="button" data-open="' + photo.id + '">Vollbild</button>' +
|
'<button type="button" data-open="' + photo.id + '">Open</button>' +
|
||||||
'</div>'
|
'</div>'
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -715,16 +728,6 @@ function htmlPage(): string {
|
|||||||
updateRouteView();
|
updateRouteView();
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPhotos(photos) {
|
|
||||||
clearGallery();
|
|
||||||
let processed = 0;
|
|
||||||
for (const photo of photos) {
|
|
||||||
appendPhoto(photo);
|
|
||||||
processed += 1;
|
|
||||||
setProgress(processed, photos.length, "Demo geladen");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseShareInput(value) {
|
function parseShareInput(value) {
|
||||||
const trimmed = value.trim();
|
const trimmed = value.trim();
|
||||||
const url = new URL(trimmed);
|
const url = new URL(trimmed);
|
||||||
@@ -744,7 +747,7 @@ function htmlPage(): string {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Bitte einen öffentlichen Nextcloud-Share-Link einfügen.");
|
throw new Error("Please enter a public Nextcloud share link.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function textContent(node, namespace, localName) {
|
function textContent(node, namespace, localName) {
|
||||||
@@ -771,7 +774,7 @@ function htmlPage(): string {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
href: absoluteUrl,
|
href: absoluteUrl,
|
||||||
name: displayName || decodeURIComponent(absoluteUrl.split("/").pop() || "Bild"),
|
name: displayName || decodeURIComponent(absoluteUrl.split("/").pop() || "image"),
|
||||||
lastModified,
|
lastModified,
|
||||||
contentType,
|
contentType,
|
||||||
isCollection
|
isCollection
|
||||||
@@ -795,7 +798,7 @@ function htmlPage(): string {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error("Nextcloud-Liste konnte nicht geladen werden: " + response.status);
|
throw new Error("Could not load the Nextcloud listing: " + response.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseListing(await response.text(), davUrl);
|
return parseListing(await response.text(), davUrl);
|
||||||
@@ -806,7 +809,7 @@ function htmlPage(): string {
|
|||||||
signal
|
signal
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error("Bild konnte nicht geladen werden: " + entry.name);
|
throw new Error("Could not load image: " + entry.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
@@ -841,15 +844,15 @@ function htmlPage(): string {
|
|||||||
try {
|
try {
|
||||||
clearObjectUrls();
|
clearObjectUrls();
|
||||||
clearGallery();
|
clearGallery();
|
||||||
updateStatus("Share wird geladen...");
|
updateStatus("Loading share...");
|
||||||
const { davUrl } = parseShareInput(shareUrl.value);
|
const { davUrl } = parseShareInput(shareUrl.value);
|
||||||
const listing = await loadShareListing(davUrl, controller.signal);
|
const listing = await loadShareListing(davUrl, controller.signal);
|
||||||
|
|
||||||
if (!listing.length) {
|
if (!listing.length) {
|
||||||
throw new Error("Im Share wurden keine Bilder gefunden.");
|
throw new Error("No images were found in the share.");
|
||||||
}
|
}
|
||||||
|
|
||||||
setProgress(0, listing.length, "Dateien werden geprüft");
|
setProgress(0, listing.length, "checking files");
|
||||||
|
|
||||||
let loaded = 0;
|
let loaded = 0;
|
||||||
let skipped = 0;
|
let skipped = 0;
|
||||||
@@ -857,7 +860,7 @@ function htmlPage(): string {
|
|||||||
|
|
||||||
for (const entry of listing) {
|
for (const entry of listing) {
|
||||||
if (controller.signal.aborted) {
|
if (controller.signal.aborted) {
|
||||||
throw controller.signal.reason ?? new Error("Import abgebrochen");
|
throw controller.signal.reason ?? new Error("Import canceled");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -877,39 +880,39 @@ function htmlPage(): string {
|
|||||||
setProgress(
|
setProgress(
|
||||||
processed,
|
processed,
|
||||||
listing.length,
|
listing.length,
|
||||||
"geladen " + loaded + ", übersprungen " + skipped
|
"loaded " + loaded + ", skipped " + skipped
|
||||||
);
|
);
|
||||||
updateStatus(
|
updateStatus(
|
||||||
"Import läuft: " +
|
"Import running: " +
|
||||||
loaded +
|
loaded +
|
||||||
" Bilder angezeigt, " +
|
" images shown, " +
|
||||||
skipped +
|
skipped +
|
||||||
" übersprungen."
|
" skipped."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
throw new Error("Keine Bilder mit GPS-Daten gefunden.");
|
throw new Error("No images with GPS data were found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
"Nextcloud-Import fertig: " +
|
"Nextcloud import complete: " +
|
||||||
loaded +
|
loaded +
|
||||||
" Bilder geladen" +
|
" images loaded" +
|
||||||
(skipped ? ", " + skipped + " übersprungen" : "") +
|
(skipped ? ", " + skipped + " skipped" : "") +
|
||||||
"."
|
"."
|
||||||
);
|
);
|
||||||
setProgress(listing.length, listing.length, "fertig");
|
setProgress(listing.length, listing.length, "done");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (controller.signal.aborted) {
|
if (controller.signal.aborted) {
|
||||||
updateStatus("Import abgebrochen.");
|
updateStatus("Import canceled.");
|
||||||
setProgress(state.processed, state.total, "abgebrochen");
|
setProgress(state.processed, state.total, "canceled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(error);
|
console.error(error);
|
||||||
updateStatus(
|
updateStatus(
|
||||||
"Import fehlgeschlagen: " + (error instanceof Error ? error.message : "Unbekannter Fehler"),
|
"Import failed: " + (error instanceof Error ? error.message : "unknown error"),
|
||||||
"error"
|
"error"
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -918,12 +921,6 @@ function htmlPage(): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showDemo() {
|
|
||||||
clearObjectUrls();
|
|
||||||
renderPhotos(DEMO_PHOTOS);
|
|
||||||
updateStatus("Demo-Daten aktiv.");
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("click", (event) => {
|
document.addEventListener("click", (event) => {
|
||||||
const target = event.target;
|
const target = event.target;
|
||||||
if (target instanceof HTMLElement && target.dataset.open) {
|
if (target instanceof HTMLElement && target.dataset.open) {
|
||||||
@@ -940,13 +937,12 @@ function htmlPage(): string {
|
|||||||
|
|
||||||
cancelShare.addEventListener("click", () => {
|
cancelShare.addEventListener("click", () => {
|
||||||
if (activeImportController) {
|
if (activeImportController) {
|
||||||
activeImportController.abort("Import durch Benutzer abgebrochen");
|
activeImportController.abort("Import canceled by user");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useDemo.addEventListener("click", showDemo);
|
clearGallery();
|
||||||
|
updateStatus("Ready to load a share.");
|
||||||
showDemo();
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>`;
|
</html>`;
|
||||||
|
|||||||
Reference in New Issue
Block a user