Кнопка «Скачать» текущей версии фото (доступна при навигации по истории)

This commit is contained in:
2026-08-25 23:34:47 +07:00
parent 839ed50ef4
commit 1dec7e5178
3 changed files with 87 additions and 4 deletions

View File

@@ -34,6 +34,7 @@ const resultLabel = document.querySelector("#result-label");
const jobStatus = document.querySelector("#job-status");
const jobStatusText = document.querySelector("#job-status-text");
const downloadLink = document.querySelector("#download-link");
const downloadCurrent = document.querySelector("#download-current");
let currentVersionId = null;
let historyVersions = [];
@@ -61,6 +62,37 @@ function formatFileSize(bytes) {
return `${(bytes / (1024 * 1024)).toFixed(1)} МБ`;
}
function versionFileName(version) {
const kindName = {
original: "original",
edit: "edited",
upscale: "upscaled"
}[version.kind] || "photo";
let stamp = "";
try {
const d = new Date(version.createdAt);
stamp = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
} catch {
stamp = "photo";
}
return `${kindName}-${stamp}.${version.ext || "jpg"}`;
}
function updateDownloadCurrent(version) {
if (!version) {
downloadCurrent.hidden = true;
downloadCurrent.removeAttribute("href");
downloadCurrent.removeAttribute("download");
return;
}
downloadCurrent.href = version.url;
downloadCurrent.download = versionFileName(version);
downloadCurrent.hidden = false;
}
function setHealthState(state, message, title = "") {
healthStatus.className = `health-status health-${state}`;
healthText.textContent = message;
@@ -201,6 +233,7 @@ async function selectFile(file) {
file.name,
`${formatFileSize(file.size)} · готово к обработке`
);
updateDownloadCurrent(data.version);
setJobStatus("", "");
setBusy(false);
} catch (error) {
@@ -299,6 +332,7 @@ async function runJob(kind) {
if (version) {
historyVersions.push(version);
currentVersionId = version.id;
updateDownloadCurrent(version);
renderHistory();
}
@@ -428,6 +462,7 @@ function selectHistoryVersion(version) {
currentVersionId = version.id;
resetResult();
updateDownloadCurrent(version);
showSourcePreviewFromUrl(
version.url,
version.label || "Версия",
@@ -455,6 +490,7 @@ async function loadHistoryOnStart() {
if (historyVersions.length > 0) {
const latest = historyVersions[historyVersions.length - 1];
currentVersionId = latest.id;
updateDownloadCurrent(latest);
showSourcePreviewFromUrl(
latest.url,
latest.label || "Текущая фотография",

View File

@@ -15,7 +15,7 @@
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='16' fill='%23202321'/%3E%3Ctext x='32' y='45' font-size='38' font-weight='bold' text-anchor='middle' fill='%23ffffff' font-family='sans-serif'%3E%D0%9A%3C/text%3E%3C/svg%3E"
>
<link rel="stylesheet" href="/style.css?v=7">
<link rel="stylesheet" href="/style.css?v=8">
</head>
<body>
<header class="topbar">
@@ -129,7 +129,19 @@
<p class="workspace-kicker">Предпросмотр</p>
<h2 id="workspace-title">До и после</h2>
</div>
<span class="local-badge">LAN · локально</span>
<div class="workspace-head-actions">
<a
id="download-current"
class="download-current"
href="#"
download
hidden
>
Скачать
<span aria-hidden="true">↓</span>
</a>
<span class="local-badge">LAN · локально</span>
</div>
</div>
<div class="comparison">
@@ -224,6 +236,6 @@
</div>
</noscript>
<script src="/app.js?v=7" defer></script>
<script src="/app.js?v=8" defer></script>
</body>
</html>

View File

@@ -445,6 +445,41 @@ textarea:disabled {
text-transform: uppercase;
}
.workspace-head-actions {
display: flex;
align-items: center;
gap: 10px;
}
.download-current {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 9px 13px;
border: 1px solid var(--dark);
border-radius: 999px;
color: var(--dark);
background: transparent;
font-size: 12px;
font-weight: 740;
text-decoration: none;
transition:
transform 150ms ease,
background 150ms ease,
color 150ms ease;
}
.download-current:hover {
background: var(--dark);
color: white;
transform: translateY(-1px);
}
.download-current:focus-visible {
outline: 3px solid rgba(108, 92, 231, 0.28);
outline-offset: 2px;
}
.comparison {
display: grid;
grid-template-columns: 1fr 1fr;
@@ -854,7 +889,7 @@ textarea:disabled {
}
}
/* -- Èñòîðèÿ âåðñèé ------------------------------------------- */
/* -- История версий ------------------------------------------------- */
.history-section {
margin-top: 30px;