From ffd32a6b630752d0ee45aaa9c8898a122c780619 Mon Sep 17 00:00:00 2001 From: Kibi Kelburton Date: Sun, 13 Sep 2026 18:13:12 +0200 Subject: [PATCH] gfsd --- public/s/js/f0ckm.js | 35 ++++++++++++++++------ public/s/js/upload.js | 67 ++++++++++++++++++++++++++++++++---------- src/upload_handler.mjs | 21 +++---------- 3 files changed, 81 insertions(+), 42 deletions(-) diff --git a/public/s/js/f0ckm.js b/public/s/js/f0ckm.js index d8d8439..5cc79a5 100644 --- a/public/s/js/f0ckm.js +++ b/public/s/js/f0ckm.js @@ -1638,6 +1638,9 @@ window.cancelAnimFrame = (function () { } modal._isClosing = false; document.body.classList.add('onara-modal-open'); + if (document.querySelector('.index-container') && window.scrollY !== 0) { + window.scrollTo(0, 0); + } modal.style.display = 'flex'; modal.setAttribute('aria-hidden', 'false'); modal.classList.remove('onara-fade-out'); @@ -1647,6 +1650,27 @@ window.cancelAnimFrame = (function () { }; window.openOnaraModal = openOnaraModal; + const scrollOnaraThumbIntoView = (thumb, forceCenter = false) => { + if (!thumb) return; + const container = thumb.closest('.index-container'); + if (container) { + const cRect = container.getBoundingClientRect(); + const tRect = thumb.getBoundingClientRect(); + const navbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--navbar-h')) || 50; + const vh = window.innerHeight || document.documentElement.clientHeight; + const isVisible = tRect.bottom > navbarH && tRect.top < vh; + if (!isVisible || forceCenter) { + const targetScrollTop = container.scrollTop + (tRect.top - cRect.top) - (container.clientHeight / 2) + (tRect.height / 2); + container.scrollTop = Math.max(0, targetScrollTop); + } + } else { + thumb.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'instant' }); + } + if (document.querySelector('.index-container') && window.scrollY !== 0) { + window.scrollTo(0, 0); + } + }; + const updateOnaraActiveItem = (itemid, url, forceScroll = false, slug = null) => { if (!isOnaraActive()) return null; // Clear onara-active from any and all elements to guarantee only 1 item is selected @@ -1673,14 +1697,7 @@ window.cancelAnimFrame = (function () { if (targetThumb) { targetThumb.classList.add('onara-active'); - const rect = targetThumb.getBoundingClientRect(); - const navbarH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--navbar-h')) || 50; - const vh = window.innerHeight || document.documentElement.clientHeight; - // If any part of the thumbnail is already visible in the viewport, do not scroll - const isVisible = rect.bottom > navbarH && rect.top < vh; - if (!isVisible || forceScroll) { - targetThumb.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'instant' }); - } + scrollOnaraThumbIntoView(targetThumb, forceScroll); } return targetThumb; }; @@ -1804,7 +1821,7 @@ window.cancelAnimFrame = (function () { synthThumb.innerHTML = '

'; oldPosts.prepend(synthThumb); if (typeof window.initLazyLoading === 'function') window.initLazyLoading(); - synthThumb.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'instant' }); + scrollOnaraThumbIntoView(synthThumb, true); } } catch (err) { console.error('[ONARA] Failed to sync background grid:', err); diff --git a/public/s/js/upload.js b/public/s/js/upload.js index ab5a1fb..4697711 100644 --- a/public/s/js/upload.js +++ b/public/s/js/upload.js @@ -2670,6 +2670,7 @@ window.initUploadForm = (selector) => { let successCount = 0; let lastData = null; + const uploadedResults = []; for (let i = 0; i < selectedFiles.length; i++) { const item = selectedFiles[i]; @@ -2765,6 +2766,7 @@ window.initUploadForm = (selector) => { if (res.success) { successCount++; lastData = res; + uploadedResults.push(res); if (res.pending) { // Background URL download — show tracker widget entry if (window.urlUploadTracker) { @@ -2830,30 +2832,63 @@ window.initUploadForm = (selector) => { if (successCount > 0) { if (dragModal) dragModal.classList.remove('show'); + const dropModal = document.getElementById('upload-drag-modal'); + if (dropModal) dropModal.classList.remove('show'); form._f0ckUploader.reset(); - if (isShitpost) { - if (lastData?.manual_approval && typeof window.flashMessage === 'function') { - window.flashMessage(window.f0ckI18n?.upload_pending_approval_patient || 'Upload awaits approval', 3000, 'warning'); - } - } else { - if (lastData?.manual_approval) { - if (typeof window.flashMessage === 'function') { - window.flashMessage(window.f0ckI18n?.upload_pending_approval_patient || 'Upload awaits approval', 3000, 'warning'); - } - } else if (!dragModal && statusDiv) { - statusDiv.innerHTML = '✓ ' + (lastData?.msg || 'Upload successful'); - statusDiv.className = 'upload-status success'; - } - } - // URL background uploads do not redirect; standard file uploads redirect back to main page ('/') const isBgUrlUpload = lastData?.pending && selectedFiles.every(i => i.type === 'url'); if (isBgUrlUpload) { if (typeof window.flashMessage === 'function') { window.flashMessage((window.f0ckI18n && window.f0ckI18n.url_upload_started) || 'Background upload started', 3000, 'info'); } } else { - window.location.href = '/'; + if (lastData?.manual_approval) { + if (typeof window.flashMessage === 'function') { + window.flashMessage(window.f0ckI18n?.upload_pending_approval_patient || 'Upload awaits approval', 3000, 'warning'); + } + } else { + const successMsg = successCount > 1 + ? `${successCount} items uploaded successfully!` + : (lastData?.msg || 'Upload successful'); + if (typeof window.flashMessage === 'function') { + window.flashMessage(successMsg, 3000, 'success'); + } else if (!dragModal && statusDiv) { + statusDiv.innerHTML = '✓ ' + successMsg; + statusDiv.className = 'upload-status success'; + } + } + + // Seamless live injection without hard reload + if (window.location.pathname === '/upload') { + if (typeof window.loadPageAjax === 'function') { + window.loadPageAjax('/', true, { bypassCache: true }); + } else { + window.location.href = '/'; + } + } else { + // Prepend items to live grid seamlessly + if (window.NotificationSystemInstance && typeof window.NotificationSystemInstance.handleNewItem === 'function') { + for (const up of uploadedResults) { + if (!up.manual_approval && !up.pending && up.itemid) { + window.NotificationSystemInstance.handleNewItem({ + id: up.itemid, + dest: up.dest, + mime: up.mime, + username: up.username || window.f0ckSession?.user || '', + display_name: up.display_name || window.f0ckSession?.display_name || null, + tag_id: up.tag_id ?? 0, + is_oc: !!up.is_oc, + slug: up.slug, + visibility: up.visibility || 0 + }); + } + } + } + // Refresh grid & pagination seamlessly in background without reload + if (typeof window.loadPageAjax === 'function') { + window.loadPageAjax(window.location.pathname + window.location.search, true, { bypassCache: true, skipPush: true }); + } + } } } else { restoreBtn(); diff --git a/src/upload_handler.mjs b/src/upload_handler.mjs index c2696d0..4469a96 100644 --- a/src/upload_handler.mjs +++ b/src/upload_handler.mjs @@ -967,9 +967,7 @@ export const handleUpload = async (req, res, self) => { if (actualMime.startsWith('audio')) { await moveSafe(path.join(cfg.paths.pending, 'ca', `${itemid}.webp`), coverDest); } - if (effectiveRating === 'nsfw' || effectiveRating === 'nsfl') { - await moveSafe(path.join(cfg.paths.pending, 't', `${itemid}_blur.webp`), blurDest); - } + await moveSafe(path.join(cfg.paths.pending, 't', `${itemid}_blur.webp`), blurDest); } } @@ -981,13 +979,7 @@ export const handleUpload = async (req, res, self) => { // EXCEPT for custom thumbnails which are already processed. const isPending = manualApproval; try { - // If it's Flash, we might have already processed a custom thumbnail. - // We'll only run genThumbnail if the thumbnail doesn't exist yet. - const tDir = isPending ? path.join(cfg.paths.pending, 't') : cfg.paths.t; - const thumbPath = path.join(tDir, `${itemid}.webp`); - const thumbExists = await fs.access(thumbPath).then(() => true).catch(() => false); - - if (!thumbExists) { + if (!thumbProcessed) { await queue.genThumbnail(filename, actualMime, itemid, '', isPending, 512); } @@ -998,13 +990,8 @@ export const handleUpload = async (req, res, self) => { console.error(`[BACKGROUND ERROR] genThumbnail failed for item ${itemid}:`, err); } - // Ensure blurred thumbnail exists - const tDir = isPending ? path.join(cfg.paths.pending, 't') : cfg.paths.t; - const blurPath = path.join(tDir, `${itemid}_blur.webp`); - const blurExists = await fs.access(blurPath).then(() => true).catch(() => false); - if (!blurExists) { - await queue.genBlurredThumbnail(itemid, isPending).catch(err => console.error(`[BACKGROUND ERROR] genBlurredThumbnail failed:`, err)); - } + // Ensure blurred thumbnail exists and is freshly generated + await queue.genBlurredThumbnail(itemid, isPending).catch(err => console.error(`[BACKGROUND ERROR] genBlurredThumbnail failed:`, err)); // Note: video title metadata is surfaced to the user as a suggestion in the upload form. // Auto-tagging from embedded metadata was removed — the user must select suggestions explicitly.