From 3e6298f81c0767b304f149b95920141ac90aa4cd Mon Sep 17 00:00:00 2001 From: Kibi Kelburton Date: Sat, 23 May 2026 15:35:42 +0200 Subject: [PATCH] previews and make sure blurry thumb gets always generated when rating is changed later on --- public/s/js/f0ckm.js | 29 +++++++++++++++++++++++++++++ src/inc/routes/apiv2/tags.mjs | 10 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/public/s/js/f0ckm.js b/public/s/js/f0ckm.js index 149a356..f2e7f69 100644 --- a/public/s/js/f0ckm.js +++ b/public/s/js/f0ckm.js @@ -7177,12 +7177,30 @@ document.addEventListener('DOMContentLoaded', () => { activeThumb = null; } }; + window.clearHoverPreview = clearPreview; // Use mouseover/mouseout bubbling on document for dynamic elements const startPreview = (thumb, delay = 150) => { // Clear any existing preview clearPreview(); + // If this thumbnail is currently set to be blurred and is not revealed yet, do not preview it! + const mode = thumb.getAttribute('data-mode'); + const blurNsfw = localStorage.getItem('blurNsfw') === 'true'; + const blurNsfl = localStorage.getItem('blurNsfl') === 'true'; + const blurSfw = localStorage.getItem('blurSfw') === 'true'; + const blurUntagged = localStorage.getItem('blurUntagged') === 'true'; + + let shouldBlurThis = false; + if (mode === 'nsfw') shouldBlurThis = blurNsfw; + else if (mode === 'nsfl') shouldBlurThis = blurNsfl; + else if (mode === 'sfw') shouldBlurThis = blurSfw; + else if (mode === 'null' || !mode) shouldBlurThis = blurUntagged; + + if (shouldBlurThis && !thumb.classList.contains('revealed')) { + return; + } + activeThumb = thumb; activeThumb.classList.add('touch-active'); // Visual feedback (box-shadow) @@ -7222,6 +7240,7 @@ document.addEventListener('DOMContentLoaded', () => { hoverTimeout = setTimeout(run, delay); } }; + window.startHoverPreview = startPreview; document.addEventListener('mouseover', (e) => { const thumb = e.target.closest('.thumb'); @@ -8775,6 +8794,11 @@ if (navigator.vibrate) { e.stopPropagation(); const thumb = hideBtn.closest('a.thumb'); if (thumb) { + // Stop any active hover video preview immediately + if (typeof window.clearHoverPreview === 'function') { + window.clearHoverPreview(); + } + thumb.classList.remove('revealed'); hideBtn.remove(); @@ -8822,6 +8846,11 @@ if (navigator.vibrate) { btn.title = 'Hide thumbnail again'; p.appendChild(btn); } + + // Automatically start the hover video preview immediately on reveal since mouse is already over the item + if (typeof window.startHoverPreview === 'function') { + window.startHoverPreview(thumb, 0); + } } } }, true); diff --git a/src/inc/routes/apiv2/tags.mjs b/src/inc/routes/apiv2/tags.mjs index 94c001d..f95618d 100644 --- a/src/inc/routes/apiv2/tags.mjs +++ b/src/inc/routes/apiv2/tags.mjs @@ -115,6 +115,16 @@ export default router => { await db`INSERT INTO tags_assign ${db({ tag_id: nextTagId, item_id: postid, user_id: +req.session.id })}`; } + // Automatically generate blurred thumbnail if cycling TO NSFW or NSFL + if (nextTagId === 2 || nextTagId === nsflId) { + const blurPath = path.join(cfg.paths.t, `${postid}_blur.webp`); + try { + await fs.promises.access(blurPath); + } catch { + await queue.genBlurredThumbnail(postid, false); + } + } + const labels = { 1: { label: 'SFW', cls: 'sfw' }, 2: { label: 'NSFW', cls: 'nsfw' }, [nsflId]: { label: 'NSFL', cls: 'nsfl' } }; const { label, cls } = labels[nextTagId];