feat: add fullscreen download action
This commit is contained in:
@@ -75,6 +75,7 @@ const overlayLoadingText = mustGet("overlay-loading-text");
|
|||||||
const overlayMedia = mustGet("overlay-media");
|
const overlayMedia = mustGet("overlay-media");
|
||||||
const overlayPrev = mustGet("overlay-prev");
|
const overlayPrev = mustGet("overlay-prev");
|
||||||
const overlayNext = mustGet("overlay-next");
|
const overlayNext = mustGet("overlay-next");
|
||||||
|
const overlayDownload = mustGet("overlay-download");
|
||||||
const closeOverlay = mustGet("close-overlay");
|
const closeOverlay = mustGet("close-overlay");
|
||||||
const routeToggle = mustGet("route-toggle");
|
const routeToggle = mustGet("route-toggle");
|
||||||
const routeToggleIcon = mustGet("route-toggle-icon");
|
const routeToggleIcon = mustGet("route-toggle-icon");
|
||||||
@@ -274,6 +275,20 @@ function syncPhotoNameInLocation(photoName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function syncOverlayDownload(photo) {
|
||||||
|
if (!photo) {
|
||||||
|
overlayDownload.setAttribute("href", "#");
|
||||||
|
overlayDownload.setAttribute("aria-disabled", "true");
|
||||||
|
overlayDownload.removeAttribute("download");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
overlayDownload.href = photo.fullUrl;
|
||||||
|
overlayDownload.download = photo.name;
|
||||||
|
overlayDownload.setAttribute("aria-label", "Download photo");
|
||||||
|
overlayDownload.setAttribute("aria-disabled", "false");
|
||||||
|
}
|
||||||
|
|
||||||
function getOverlayPhotos() {
|
function getOverlayPhotos() {
|
||||||
if (!state.visiblePhotos.length) {
|
if (!state.visiblePhotos.length) {
|
||||||
return state.photos;
|
return state.photos;
|
||||||
@@ -566,6 +581,7 @@ function openOverlay(photo) {
|
|||||||
overlay.setAttribute("aria-hidden", "false");
|
overlay.setAttribute("aria-hidden", "false");
|
||||||
overlayTitle.textContent = photo.name;
|
overlayTitle.textContent = photo.name;
|
||||||
overlayImage.alt = photo.name;
|
overlayImage.alt = photo.name;
|
||||||
|
syncOverlayDownload(photo);
|
||||||
overlay.classList.add("loading");
|
overlay.classList.add("loading");
|
||||||
overlayLoading.classList.add("active");
|
overlayLoading.classList.add("active");
|
||||||
overlayLoading.classList.remove("error");
|
overlayLoading.classList.remove("error");
|
||||||
@@ -600,6 +616,7 @@ function closeOverlayView() {
|
|||||||
overlayLoading.classList.remove("error");
|
overlayLoading.classList.remove("error");
|
||||||
overlayLoadingText.textContent = "Loading full-size image...";
|
overlayLoadingText.textContent = "Loading full-size image...";
|
||||||
overlayImage.removeAttribute("src");
|
overlayImage.removeAttribute("src");
|
||||||
|
syncOverlayDownload(null);
|
||||||
syncPhotoNameInLocation("");
|
syncPhotoNameInLocation("");
|
||||||
overlaySwipeState = null;
|
overlaySwipeState = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export const APP_STYLES = ` :root {
|
|||||||
--overlay-media-bg: rgba(248, 250, 252, 0.94);
|
--overlay-media-bg: rgba(248, 250, 252, 0.94);
|
||||||
--overlay-media-border: rgba(148, 163, 184, 0.26);
|
--overlay-media-border: rgba(148, 163, 184, 0.26);
|
||||||
--overlay-media-shadow: 0 10px 24px rgba(15, 23, 42, 0.08);
|
--overlay-media-shadow: 0 10px 24px rgba(15, 23, 42, 0.08);
|
||||||
--overlay-caption-text: rgba(248, 250, 252, 0.95);
|
--overlay-caption-text: #303030;
|
||||||
--card-border: rgba(15, 23, 42, 0.11);
|
--card-border: rgba(15, 23, 42, 0.11);
|
||||||
--timeline-surface: rgba(255, 255, 255, 0.84);
|
--timeline-surface: rgba(255, 255, 255, 0.84);
|
||||||
--timeline-surface-soft: rgba(255, 255, 255, 0.94);
|
--timeline-surface-soft: rgba(255, 255, 255, 0.94);
|
||||||
@@ -730,6 +730,38 @@ export const APP_STYLES = ` :root {
|
|||||||
border-color: var(--timeline-border-strong);
|
border-color: var(--timeline-border-strong);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overlay-download {
|
||||||
|
position: fixed;
|
||||||
|
top: 16px;
|
||||||
|
right: 64px;
|
||||||
|
z-index: 1001;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
padding: 0;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--timeline-surface-soft);
|
||||||
|
color: var(--timeline-text);
|
||||||
|
border: 1px solid var(--timeline-border);
|
||||||
|
box-shadow: var(--shadow-soft);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-action {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-download:hover {
|
||||||
|
background: var(--timeline-surface-strong);
|
||||||
|
border-color: var(--timeline-border-strong);
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-download[aria-disabled="true"] {
|
||||||
|
opacity: 0.45;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.overlay-nav {
|
.overlay-nav {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
|||||||
@@ -147,9 +147,16 @@ ${APP_STYLES}
|
|||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="close overlay-close" id="close-overlay" type="button" aria-label="Close photo">
|
<a class="overlay-action overlay-download" id="overlay-download" href="#" download aria-label="Download photo">
|
||||||
x
|
<span class="button-icon" aria-hidden="true">
|
||||||
</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>
|
||||||
|
</a>
|
||||||
|
<button class="close overlay-close" id="close-overlay" type="button" aria-label="Close photo">x</button>
|
||||||
<div class="overlay-card" id="overlay-card">
|
<div class="overlay-card" id="overlay-card">
|
||||||
<div class="overlay-media" id="overlay-media">
|
<div class="overlay-media" id="overlay-media">
|
||||||
<div class="overlay-loading" id="overlay-loading" aria-live="polite" aria-atomic="true">
|
<div class="overlay-loading" id="overlay-loading" aria-live="polite" aria-atomic="true">
|
||||||
|
|||||||
Reference in New Issue
Block a user