Files
avandClaude Opus 4.8 9ed732e49e Веб-UI: основной идентификатор карточек — download.id вместо infohash
В карточке списка и шапке /download/{id} показываем и копируем download.id
(ULID) — тот же ключ, что в логах (download_id), удобно грепать. Infohash
остаётся в блоке «Информация о торренте». Поиск по списку расширен: матчит
любой идентификатор (download.id ИЛИ infohash), плюс название/контекст.
Удалены осиротевшие поля Infohash/InfohashShort и хелпер shortenHash.

Дельта web-ui влита в спеки, change заархивирован.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 09:47:27 +03:00

46 lines
1.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Клиентская мелочь без сборки и фреймворков.
// htmx тянет серверные фрагменты, здесь — только то, что серверу знать не нужно.
// Копирование идентификатора (download id / infohash) в буфер обмена. На целевом
// деплое (домашний LAN по HTTP) navigator.clipboard недоступен — secure context
// только на HTTPS/localhost, поэтому есть fallback на execCommand, а индикация
// честная: «✓» лишь при успехе.
function copyHash(btn, full) {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(full).then(
() => flashCopy(btn, true),
() => flashCopy(btn, legacyCopy(full)),
);
} else {
flashCopy(btn, legacyCopy(full));
}
}
function legacyCopy(text) {
try {
const ta = document.createElement('textarea');
ta.value = text;
ta.style.position = 'fixed';
ta.style.opacity = '0';
document.body.appendChild(ta);
ta.focus();
ta.select();
const ok = document.execCommand('copy');
document.body.removeChild(ta);
return ok;
} catch (e) {
return false;
}
}
function flashCopy(btn, ok) {
const old = btn.dataset.label || btn.textContent;
btn.dataset.label = old;
btn.textContent = ok ? '✓ скопировано' : '✗ не вышло';
btn.classList.toggle('copied', ok);
setTimeout(() => { btn.textContent = old; btn.classList.remove('copied'); }, 1400);
}
// Фильтр, поиск и пагинация списка — серверные (GET-параметры f/q/page/all),
// работают без JS. Здесь клиентской фильтрации нет намеренно.