jdf
This commit is contained in:
+48
-14
@@ -48,18 +48,30 @@ class CommentSystem {
|
||||
const isHidden = localStorage.getItem('comments_hidden') === 'true';
|
||||
// Force show if hash is present
|
||||
if (window.location.hash && window.location.hash.startsWith('#c')) {
|
||||
this.container.classList.remove('faded-out');
|
||||
this.container.style.display = 'block';
|
||||
this.container.classList.remove('faded-out', 'is-hidden');
|
||||
this.container.style.removeProperty('display');
|
||||
this.container.style.display = '';
|
||||
localStorage.setItem('comments_hidden', 'false');
|
||||
document.body.classList.remove('sidebar-left-hidden');
|
||||
document.body.classList.remove('sidebar-left-hidden', 'comments-hidden');
|
||||
const layout = this.container.closest('.item-layout-container');
|
||||
if (layout) layout.classList.remove('sidebar-hidden');
|
||||
} else if (isHidden && (window.innerWidth >= 1000 || !document.body.classList.contains('layout-modern'))) {
|
||||
this.container.classList.add('faded-out');
|
||||
this.container.style.display = 'none';
|
||||
document.body.classList.add('sidebar-left-hidden');
|
||||
const sidebar = this.container.closest('.item-sidebar-left');
|
||||
if (sidebar) {
|
||||
sidebar.classList.remove('is-hidden');
|
||||
sidebar.style.removeProperty('display');
|
||||
sidebar.style.display = '';
|
||||
}
|
||||
} else if (isHidden) {
|
||||
this.container.classList.add('faded-out', 'is-hidden');
|
||||
this.container.style.setProperty('display', 'none', 'important');
|
||||
document.body.classList.add('sidebar-left-hidden', 'comments-hidden');
|
||||
const layout = this.container.closest('.item-layout-container');
|
||||
if (layout) layout.classList.add('sidebar-hidden');
|
||||
const sidebar = this.container.closest('.item-sidebar-left');
|
||||
if (sidebar) {
|
||||
sidebar.classList.add('is-hidden');
|
||||
sidebar.style.setProperty('display', 'none', 'important');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3878,7 +3890,12 @@ class CommentSystem {
|
||||
e.preventDefault();
|
||||
|
||||
// If comments are hidden, show them first
|
||||
const isHidden = cs.container.classList.contains('faded-out') || cs.container.style.display === 'none';
|
||||
const isHidden = cs.container.classList.contains('faded-out') ||
|
||||
cs.container.classList.contains('is-hidden') ||
|
||||
cs.container.style.display === 'none' ||
|
||||
document.body.classList.contains('sidebar-left-hidden') ||
|
||||
document.body.classList.contains('comments-hidden') ||
|
||||
localStorage.getItem('comments_hidden') === 'true';
|
||||
if (isHidden) cs.toggleComments();
|
||||
|
||||
// Legacy layout: comments are in the normal page flow under .item-main-content
|
||||
@@ -3959,7 +3976,7 @@ class CommentSystem {
|
||||
toggleComments() {
|
||||
if (!this.container) return;
|
||||
|
||||
if (document.body.classList.contains('layout-modern')) {
|
||||
if (document.body.classList.contains('layout-modern') && !document.body.classList.contains('onara-modal-open')) {
|
||||
if (window.innerWidth < 1000) return;
|
||||
if (typeof window.toggleSidebarLeft === 'function') {
|
||||
window.toggleSidebarLeft();
|
||||
@@ -3974,27 +3991,44 @@ class CommentSystem {
|
||||
] : [];
|
||||
|
||||
// Check if currently hidden (or slid out)
|
||||
const isHidden = this.container.classList.contains('faded-out') || this.container.style.display === 'none';
|
||||
const isHidden = this.container.classList.contains('faded-out') ||
|
||||
this.container.classList.contains('is-hidden') ||
|
||||
this.container.style.display === 'none' ||
|
||||
document.body.classList.contains('sidebar-left-hidden') ||
|
||||
document.body.classList.contains('comments-hidden') ||
|
||||
localStorage.getItem('comments_hidden') === 'true';
|
||||
|
||||
if (isHidden) {
|
||||
// SHOW: expand grid first, then slide content in
|
||||
if (layout) layout.classList.remove('sidebar-hidden');
|
||||
document.body.classList.remove('sidebar-left-hidden');
|
||||
document.body.classList.remove('sidebar-left-hidden', 'comments-hidden');
|
||||
this.container.classList.remove('is-hidden');
|
||||
this.container.style.removeProperty('display');
|
||||
this.container.style.display = '';
|
||||
if (sidebar) {
|
||||
sidebar.classList.remove('is-hidden');
|
||||
sidebar.style.removeProperty('display');
|
||||
sidebar.style.display = '';
|
||||
}
|
||||
localStorage.setItem('comments_hidden', 'false');
|
||||
void this.container.offsetWidth; // force reflow so transition fires
|
||||
this.container.classList.remove('faded-out');
|
||||
siblings.forEach(el => el.classList.remove('faded-out'));
|
||||
} else {
|
||||
// HIDE: slide content out first, then collapse grid
|
||||
// HIDE: mark state immediately so quick navigations stay hidden, fade out content, then collapse
|
||||
localStorage.setItem('comments_hidden', 'true');
|
||||
this.container.classList.add('faded-out');
|
||||
siblings.forEach(el => el.classList.add('faded-out'));
|
||||
setTimeout(() => {
|
||||
if (!this.container.classList.contains('faded-out')) return;
|
||||
this.container.style.display = 'none';
|
||||
this.container.classList.add('is-hidden');
|
||||
this.container.style.setProperty('display', 'none', 'important');
|
||||
if (sidebar) {
|
||||
sidebar.classList.add('is-hidden');
|
||||
sidebar.style.setProperty('display', 'none', 'important');
|
||||
}
|
||||
if (layout) layout.classList.add('sidebar-hidden');
|
||||
document.body.classList.add('sidebar-left-hidden');
|
||||
document.body.classList.add('sidebar-left-hidden', 'comments-hidden');
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
+339
-107
@@ -1135,6 +1135,21 @@ window.cancelAnimFrame = (function () {
|
||||
};
|
||||
window.updateOnaraActiveItem = updateOnaraActiveItem;
|
||||
|
||||
const isItemPath = (pathOrUrl) => {
|
||||
try {
|
||||
const p = new URL(pathOrUrl, window.location.origin).pathname;
|
||||
const parts = p.split('/').filter(Boolean);
|
||||
return !p.match(/\/p\//) && (
|
||||
/^\/\d+/.test(p) ||
|
||||
/^\/[a-zA-Z0-9_-]{11}(?:[?#]|$)/.test(p) ||
|
||||
(parts.length >= 3 && (parts[0] === 'tag' || parts[0] === 'user' || parts[0] === 'h') && (/^\d+$/.test(parts[parts.length - 1]) || /^[a-zA-Z0-9_-]{11}$/.test(parts[parts.length - 1])))
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
window.isItemPath = isItemPath;
|
||||
|
||||
const getOnaraBaseUrl = (itemUrl = window.location.href) => {
|
||||
try {
|
||||
const urlObj = new URL(itemUrl, window.location.origin);
|
||||
@@ -1142,7 +1157,8 @@ window.cancelAnimFrame = (function () {
|
||||
path = path.replace(/\/(?:\d+|[a-zA-Z0-9_-]{11})$/, '');
|
||||
const postsEl = document.querySelector('.posts[data-current-page]');
|
||||
const currentPage = postsEl ? parseInt(postsEl.dataset.currentPage, 10) : 1;
|
||||
if (currentPage > 1 && !path.includes('/p/')) {
|
||||
const currentGridPath = window._onaraCurrentGridUrl ? new URL(window._onaraCurrentGridUrl, window.location.origin).pathname.replace(/\/p\/\d+/, '').replace(/\/+$/, '') : '';
|
||||
if (currentPage > 1 && !path.includes('/p/') && (!currentGridPath || currentGridPath === path)) {
|
||||
path = (path ? path : '') + '/p/' + currentPage;
|
||||
}
|
||||
if (!path) path = '/';
|
||||
@@ -1202,15 +1218,30 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
if (!options.skipHistory) {
|
||||
const returnUrl = window._onaraReturnUrl || getOnaraBaseUrl();
|
||||
history.pushState({}, '', returnUrl);
|
||||
if (window._onaraReturnTitle) {
|
||||
document.title = window._onaraReturnTitle;
|
||||
} else if (window.f0ckDomain) {
|
||||
document.title = window.f0ckDomain;
|
||||
const returnTitle = window._onaraReturnTitle || window.f0ckDomain || '';
|
||||
// Always jump directly to the return URL — never step back through stacked item history.
|
||||
// history.back() would re-open the previous item via popstate; replaceState exits cleanly.
|
||||
const depth = window._onaraOpenHistoryLength != null
|
||||
? history.length - window._onaraOpenHistoryLength
|
||||
: 0;
|
||||
if (depth > 0) {
|
||||
// Suppress popstate re-navigation while we jump out
|
||||
window._onaraSuppressPopstate = true;
|
||||
history.go(-depth);
|
||||
// history.go is async — replace the landing state after it fires
|
||||
setTimeout(() => {
|
||||
history.replaceState({}, '', returnUrl);
|
||||
document.title = returnTitle;
|
||||
window._onaraSuppressPopstate = false;
|
||||
}, 50);
|
||||
} else {
|
||||
history.replaceState({}, '', returnUrl);
|
||||
document.title = returnTitle;
|
||||
}
|
||||
}
|
||||
window._onaraReturnUrl = null;
|
||||
window._onaraReturnTitle = null;
|
||||
window._onaraOpenHistoryLength = null;
|
||||
|
||||
// Maintain focus on active item so user TAB navigation seamlessly resumes from current progress
|
||||
const activeThumb = document.querySelector('.posts > a.thumb.onara-active');
|
||||
@@ -1806,6 +1837,21 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
|
||||
const _preloadedMediaUrls = new Set();
|
||||
let _prefetchAbortController = null;
|
||||
let _prefetchDebounceTimer = null;
|
||||
|
||||
const cancelPrefetch = () => {
|
||||
if (_prefetchDebounceTimer) {
|
||||
clearTimeout(_prefetchDebounceTimer);
|
||||
_prefetchDebounceTimer = null;
|
||||
}
|
||||
if (_prefetchAbortController) {
|
||||
try {
|
||||
_prefetchAbortController.abort();
|
||||
} catch (_) {}
|
||||
_prefetchAbortController = null;
|
||||
}
|
||||
};
|
||||
|
||||
const preloadMediaFromHtml = (html) => {
|
||||
if (!html) return;
|
||||
@@ -1813,7 +1859,7 @@ window.cancelAnimFrame = (function () {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, 'text/html');
|
||||
|
||||
// 1. Preload Image
|
||||
// 1. Preload Image only (standard image pipeline, non-blocking)
|
||||
const img = doc.querySelector('#f0ck-image, .embed-responsive-image img, .media-object img');
|
||||
if (img) {
|
||||
const src = img.getAttribute('src');
|
||||
@@ -1837,20 +1883,9 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Preload Video / Audio Media (fetch initial bytes into browser cache)
|
||||
const mediaEl = doc.querySelector('video#my-video, audio#my-video, .media-object video, .media-object audio');
|
||||
if (mediaEl) {
|
||||
const mediaSrc = mediaEl.getAttribute('src');
|
||||
if (mediaSrc && !mediaSrc.startsWith('blob:') && !_preloadedMediaUrls.has(mediaSrc)) {
|
||||
_preloadedMediaUrls.add(mediaSrc);
|
||||
fetch(mediaSrc, {
|
||||
headers: { Range: 'bytes=0-2097151' }, // 2MB initial chunk preload
|
||||
credentials: 'include',
|
||||
priority: 'low'
|
||||
}).catch(() => {});
|
||||
window.f0ckDebug('[prefetch] Preloaded media buffer:', mediaSrc);
|
||||
}
|
||||
}
|
||||
// Note: Video & Audio binary streams are deliberately NOT fetched via fetch() in JS.
|
||||
// HTML5 media elements stream natively upon mounting. Fetching multi-megabyte chunks
|
||||
// in the background exhausts the browser's 6-connection HTTP pool, stalling navigation.
|
||||
|
||||
if (_preloadedMediaUrls.size > 150) {
|
||||
_preloadedMediaUrls.clear();
|
||||
@@ -1861,11 +1896,20 @@ window.cancelAnimFrame = (function () {
|
||||
};
|
||||
|
||||
const prefetchNextPrevItems = () => {
|
||||
// Abort prior in-flight prefetch requests
|
||||
if (_prefetchAbortController) {
|
||||
try { _prefetchAbortController.abort(); } catch (_) {}
|
||||
}
|
||||
_prefetchAbortController = new AbortController();
|
||||
const signal = _prefetchAbortController.signal;
|
||||
|
||||
// Prioritize next item (most frequent user journey), then prev
|
||||
const nextBtn = document.getElementById('next');
|
||||
const prevBtn = document.getElementById('prev');
|
||||
|
||||
[nextBtn, prevBtn].forEach(btn => {
|
||||
if (!btn || !btn.href || btn.href.endsWith('#')) return;
|
||||
if (signal.aborted) return;
|
||||
|
||||
const pathSegments = new URL(btn.href, window.location.origin).pathname.split('/');
|
||||
const keySegments = pathSegments.filter(s => /^\d+$/.test(s) || /^[a-zA-Z0-9_-]{11}$/.test(s));
|
||||
@@ -1907,17 +1951,17 @@ window.cancelAnimFrame = (function () {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(ajaxUrl, { credentials: 'include', priority: 'low' })
|
||||
fetch(ajaxUrl, { credentials: 'include', priority: 'low', signal })
|
||||
.then(r => r.ok ? r.text() : null)
|
||||
.then(rawText => {
|
||||
if (!rawText) return;
|
||||
if (!rawText || signal.aborted) return;
|
||||
let html = rawText;
|
||||
try {
|
||||
const data = JSON.parse(rawText);
|
||||
if (data && typeof data.html === 'string') html = data.html;
|
||||
} catch (_) {}
|
||||
|
||||
if (html) {
|
||||
if (html && !signal.aborted) {
|
||||
itemCacheMap.set(ajaxUrl, { html, ts: Date.now() });
|
||||
if (itemCacheMap.size > ITEM_CACHE_MAX) {
|
||||
itemCacheMap.delete(itemCacheMap.keys().next().value);
|
||||
@@ -1926,10 +1970,26 @@ window.cancelAnimFrame = (function () {
|
||||
preloadMediaFromHtml(html);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch(err => {
|
||||
if (err.name !== 'AbortError') {
|
||||
window.f0ckDebug('[prefetch] Prefetch error or cancelled:', err.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const schedulePrefetch = (delay = 600) => {
|
||||
cancelPrefetch();
|
||||
_prefetchDebounceTimer = setTimeout(() => {
|
||||
_prefetchDebounceTimer = null;
|
||||
if (typeof requestIdleCallback === 'function') {
|
||||
requestIdleCallback(() => prefetchNextPrevItems(), { timeout: 1500 });
|
||||
} else {
|
||||
prefetchNextPrevItems();
|
||||
}
|
||||
}, delay);
|
||||
};
|
||||
|
||||
const setupMedia = () => {
|
||||
const elem = document.querySelector("#my-video") || document.querySelector("audio#my-video");
|
||||
if (elem) {
|
||||
@@ -1948,6 +2008,7 @@ window.cancelAnimFrame = (function () {
|
||||
window._onaraReturnUrl = getOnaraBaseUrl();
|
||||
window._onaraReturnTitle = window.f0ckDomain || 'f0ck';
|
||||
}
|
||||
window._onaraCurrentGridUrl = window._onaraReturnUrl;
|
||||
const pathSegments = window.location.pathname.split('/');
|
||||
const keySegments = pathSegments.filter(s => /^\d+$/.test(s) || /^[a-zA-Z0-9_-]{11}$/.test(s));
|
||||
const activeKey = keySegments.length ? keySegments[keySegments.length - 1] : null;
|
||||
@@ -1957,6 +2018,8 @@ window.cancelAnimFrame = (function () {
|
||||
window.trackVisit(activeKey);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
window._onaraCurrentGridUrl = window.location.pathname + window.location.search;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1964,11 +2027,7 @@ window.cancelAnimFrame = (function () {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setupMedia();
|
||||
initOnaraInitialState();
|
||||
if (typeof requestIdleCallback === 'function') {
|
||||
requestIdleCallback(() => prefetchNextPrevItems());
|
||||
} else {
|
||||
setTimeout(prefetchNextPrevItems, 500);
|
||||
}
|
||||
schedulePrefetch(800);
|
||||
});
|
||||
initOnaraInitialState();
|
||||
|
||||
@@ -2820,6 +2879,10 @@ window.cancelAnimFrame = (function () {
|
||||
const loadPageAjax = async (url, replace = true, options = {}) => {
|
||||
if (isNavigating) return;
|
||||
|
||||
const fromOnaraModal = document.body.classList.contains('onara-modal-open') ||
|
||||
(document.getElementById('onara-modal') && document.getElementById('onara-modal').style.display !== 'none');
|
||||
const shouldReplaceHistory = options.replaceHistory ?? (fromOnaraModal && !options.skipPush);
|
||||
|
||||
// Immediately restore scrollability and hide modals
|
||||
if (window.resetGlobalScrollState) window.resetGlobalScrollState();
|
||||
if (window.hideAllModals) window.hideAllModals();
|
||||
@@ -2882,7 +2945,7 @@ window.cancelAnimFrame = (function () {
|
||||
const currentScroll = currentContainer ? currentContainer.scrollTop : window.scrollY;
|
||||
|
||||
// Save scroll position for the current page before we leave it (only for new navigations)
|
||||
if (!options.skipPush) {
|
||||
if (!options.skipPush && !shouldReplaceHistory) {
|
||||
const currentState = history.state || {};
|
||||
history.replaceState({ ...currentState, scroll: currentScroll }, document.title, window.location.href);
|
||||
}
|
||||
@@ -2977,7 +3040,13 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
|
||||
// Update URL bar (only for explicit clicks, not browser back/forward which already did it)
|
||||
if (!options.skipPush && !document.body.classList.contains('onara-modal-open')) history.pushState({}, '', url);
|
||||
if (!options.skipPush && !document.body.classList.contains('onara-modal-open')) {
|
||||
if (shouldReplaceHistory) {
|
||||
history.replaceState({}, '', url);
|
||||
} else {
|
||||
history.pushState({}, '', url);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore scroll position
|
||||
requestAnimationFrame(() => {
|
||||
@@ -3001,6 +3070,7 @@ window.cancelAnimFrame = (function () {
|
||||
if (window.initSidebarRightToggle) window.initSidebarRightToggle();
|
||||
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
||||
window.NotificationSystemInstance?.pollDebounced?.();
|
||||
window._onaraCurrentGridUrl = urlObj.pathname + urlObj.search;
|
||||
isNavigating = false;
|
||||
return; // SKIP FETCH
|
||||
}
|
||||
@@ -3185,7 +3255,7 @@ window.cancelAnimFrame = (function () {
|
||||
});
|
||||
|
||||
// Sync body classes (CRITICAL for layout triggers)
|
||||
const persistClasses = ['sidebar-right-hidden', 'bg-active'];
|
||||
const persistClasses = ['sidebar-right-hidden', 'bg-active', 'sidebar-left-hidden', 'comments-hidden'];
|
||||
const currentlyActive = persistClasses.filter(c => document.body.classList.contains(c));
|
||||
|
||||
document.body.className = doc.body.className;
|
||||
@@ -3412,7 +3482,11 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
// UPDATE HISTORY BEFORE INITIALIZING SCRIPTS
|
||||
if (!options.skipPush && !document.body.classList.contains('onara-modal-open')) {
|
||||
history.pushState({}, '', url);
|
||||
if (shouldReplaceHistory) {
|
||||
history.replaceState({}, '', url);
|
||||
} else {
|
||||
history.pushState({}, '', url);
|
||||
}
|
||||
}
|
||||
|
||||
// Sync sidebar and comments-list layout (Legacy View Only)
|
||||
@@ -3551,6 +3625,7 @@ window.cancelAnimFrame = (function () {
|
||||
}, 500);
|
||||
}
|
||||
|
||||
window._onaraCurrentGridUrl = urlObj.pathname + urlObj.search;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3618,7 +3693,11 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
history.pushState({}, '', pushUrl);
|
||||
if (shouldReplaceHistory) {
|
||||
history.replaceState({}, '', pushUrl);
|
||||
} else {
|
||||
history.pushState({}, '', pushUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// Update pagination (CRITICAL: Do this BEFORE initializing scroll so it captures fresh HTML)
|
||||
@@ -3655,6 +3734,7 @@ window.cancelAnimFrame = (function () {
|
||||
if (window.initSidebarRightToggle) window.initSidebarRightToggle();
|
||||
// Sync has-notif highlights after grid loads — handles PWA where visibilitychange doesn't fire
|
||||
window.NotificationSystemInstance?.pollDebounced?.();
|
||||
window._onaraCurrentGridUrl = urlObj.pathname + urlObj.search;
|
||||
|
||||
// Instant jump to hash (e.g. #c123)
|
||||
if (hash) {
|
||||
@@ -3781,6 +3861,7 @@ window.cancelAnimFrame = (function () {
|
||||
const loadItemAjax = async (url, inheritContext = true, options = {}) => {
|
||||
|
||||
if (isNavigating) return;
|
||||
cancelPrefetch();
|
||||
|
||||
// Immediately restore scrollability and hide modals
|
||||
if (window.resetGlobalScrollState) window.resetGlobalScrollState();
|
||||
@@ -3793,8 +3874,14 @@ window.cancelAnimFrame = (function () {
|
||||
const useOnara = isOnaraActive() && (isGridPage || isModalOpen);
|
||||
|
||||
if (useOnara && !isModalOpen) {
|
||||
window._onaraReturnUrl = window.location.href;
|
||||
if (options.skipPush || isItemPath(window.location.href)) {
|
||||
window._onaraReturnUrl = getOnaraBaseUrl(url);
|
||||
} else {
|
||||
window._onaraReturnUrl = window.location.href;
|
||||
}
|
||||
window._onaraReturnTitle = document.title;
|
||||
// Record history depth so we can jump past all stacked item entries on close
|
||||
window._onaraOpenHistoryLength = history.length;
|
||||
}
|
||||
|
||||
// ── Scroller-active cleanup (same as loadPageAjax) ───────────────────
|
||||
@@ -4000,8 +4087,8 @@ window.cancelAnimFrame = (function () {
|
||||
const _itemCacheKey = ajaxUrl;
|
||||
const _cachedItem = !options.skipCache ? itemCacheMap.get(_itemCacheKey) : null;
|
||||
|
||||
// Allow slide-out animation to visibly start before content swap
|
||||
if (options.direction && document.querySelector('.content')) {
|
||||
// Allow slide-out or fade-out animation to visibly start before content swap
|
||||
if ((options.direction || options.transition === 'fade-zoom') && document.querySelector('.content')) {
|
||||
await new Promise(r => setTimeout(r, 180));
|
||||
}
|
||||
|
||||
@@ -4065,13 +4152,39 @@ window.cancelAnimFrame = (function () {
|
||||
if (_o && _n) _o.replaceWith(_n.cloneNode(true));
|
||||
});
|
||||
} else {
|
||||
const isCommentsHidden = localStorage.getItem('comments_hidden') === 'true';
|
||||
if (isCommentsHidden) {
|
||||
document.body.classList.add('sidebar-left-hidden', 'comments-hidden');
|
||||
} else {
|
||||
document.body.classList.remove('sidebar-left-hidden', 'comments-hidden');
|
||||
}
|
||||
_container.insertAdjacentHTML('beforeend', _html);
|
||||
if (isCommentsHidden) {
|
||||
const _newLayout = _container.querySelector('.item-layout-container');
|
||||
if (_newLayout) _newLayout.classList.add('sidebar-hidden');
|
||||
const _newComments = _container.querySelector('#comments-container');
|
||||
if (_newComments) {
|
||||
_newComments.classList.add('faded-out', 'is-hidden');
|
||||
_newComments.style.setProperty('display', 'none', 'important');
|
||||
}
|
||||
const _newLeftSb = _container.querySelector('.item-sidebar-left');
|
||||
if (_newLeftSb) {
|
||||
_newLeftSb.classList.add('is-hidden');
|
||||
_newLeftSb.style.setProperty('display', 'none', 'important');
|
||||
}
|
||||
}
|
||||
if (options.direction) {
|
||||
const _newEls = _container.querySelectorAll('.content, ._204863, .item_title');
|
||||
_newEls.forEach(el => {
|
||||
el.classList.remove('slide-next', 'slide-prev', 'slide-out-left', 'slide-out-right');
|
||||
el.classList.remove('slide-next', 'slide-prev', 'slide-out-left', 'slide-out-right', 'fade-out-zoom', 'fade-in-zoom');
|
||||
el.classList.add(options.direction === 'next' ? 'slide-next' : 'slide-prev');
|
||||
});
|
||||
} else if (options.transition === 'fade-zoom') {
|
||||
const _newEls = _container.querySelectorAll('.content, ._204863, .item_title');
|
||||
_newEls.forEach(el => {
|
||||
el.classList.remove('slide-next', 'slide-prev', 'slide-out-left', 'slide-out-right', 'fade-out-zoom', 'fade-in-zoom');
|
||||
el.classList.add('fade-in-zoom');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4135,11 +4248,7 @@ window.cancelAnimFrame = (function () {
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
if (typeof requestIdleCallback === 'function') {
|
||||
requestIdleCallback(() => prefetchNextPrevItems());
|
||||
} else {
|
||||
setTimeout(prefetchNextPrevItems, 100);
|
||||
}
|
||||
schedulePrefetch(600);
|
||||
|
||||
return; // Done — served from cache
|
||||
}
|
||||
@@ -4279,13 +4388,39 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const isCommentsHidden = localStorage.getItem('comments_hidden') === 'true';
|
||||
if (isCommentsHidden) {
|
||||
document.body.classList.add('sidebar-left-hidden', 'comments-hidden');
|
||||
} else {
|
||||
document.body.classList.remove('sidebar-left-hidden', 'comments-hidden');
|
||||
}
|
||||
container.insertAdjacentHTML('beforeend', html);
|
||||
if (isCommentsHidden) {
|
||||
const newLayout = container.querySelector('.item-layout-container');
|
||||
if (newLayout) newLayout.classList.add('sidebar-hidden');
|
||||
const newComments = container.querySelector('#comments-container');
|
||||
if (newComments) {
|
||||
newComments.classList.add('faded-out', 'is-hidden');
|
||||
newComments.style.setProperty('display', 'none', 'important');
|
||||
}
|
||||
const newLeftSb = container.querySelector('.item-sidebar-left');
|
||||
if (newLeftSb) {
|
||||
newLeftSb.classList.add('is-hidden');
|
||||
newLeftSb.style.setProperty('display', 'none', 'important');
|
||||
}
|
||||
}
|
||||
if (options.direction) {
|
||||
const newEls = container.querySelectorAll('.content, ._204863, .item_title');
|
||||
newEls.forEach(el => {
|
||||
el.classList.remove('slide-next', 'slide-prev', 'slide-out-left', 'slide-out-right');
|
||||
el.classList.remove('slide-next', 'slide-prev', 'slide-out-left', 'slide-out-right', 'fade-out-zoom', 'fade-in-zoom');
|
||||
el.classList.add(options.direction === 'next' ? 'slide-next' : 'slide-prev');
|
||||
});
|
||||
} else if (options.transition === 'fade-zoom') {
|
||||
const newEls = container.querySelectorAll('.content, ._204863, .item_title');
|
||||
newEls.forEach(el => {
|
||||
el.classList.remove('slide-next', 'slide-prev', 'slide-out-left', 'slide-out-right', 'fade-out-zoom', 'fade-in-zoom');
|
||||
el.classList.add('fade-in-zoom');
|
||||
});
|
||||
}
|
||||
|
||||
// Note: Prefetching video src immediately after DOM injection has been removed
|
||||
@@ -4365,11 +4500,7 @@ window.cancelAnimFrame = (function () {
|
||||
console.error("updateStrictLinks error:", err);
|
||||
}
|
||||
|
||||
if (typeof requestIdleCallback === 'function') {
|
||||
requestIdleCallback(() => prefetchNextPrevItems());
|
||||
} else {
|
||||
setTimeout(prefetchNextPrevItems, 200);
|
||||
}
|
||||
schedulePrefetch(600);
|
||||
|
||||
// After comments have rendered (f0ck:contentLoaded above triggers synchronous render),
|
||||
// constrain the comments-list height via direct measurement (flex chain unreliable in AJAX).
|
||||
@@ -4496,25 +4627,14 @@ window.cancelAnimFrame = (function () {
|
||||
if (link.id === 'random' || link.id === 'nav-random') {
|
||||
e.preventDefault();
|
||||
|
||||
// In Onara mode with a background grid, pick a random item from the grid so it reflects on the main page
|
||||
if (isOnaraActive()) {
|
||||
const gridThumbs = Array.from(document.querySelectorAll('.posts > a:not(.notif-item)'));
|
||||
if (gridThumbs.length > 0) {
|
||||
const pool = gridThumbs.filter(t => !t.classList.contains('onara-active'));
|
||||
const chosen = (pool.length > 0 ? pool : gridThumbs)[Math.floor(Math.random() * (pool.length > 0 ? pool : gridThumbs).length)];
|
||||
if (chosen) {
|
||||
document.querySelectorAll('.onara-active').forEach(el => el.classList.remove('onara-active'));
|
||||
chosen.classList.add('onara-active');
|
||||
if (document.activeElement && document.activeElement !== chosen && typeof document.activeElement.blur === 'function') {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
loadItemAjax(chosen.href, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
const outEls = document.querySelectorAll('.content, ._204863, .item_title');
|
||||
outEls.forEach(el => {
|
||||
el.classList.remove('slide-out-left', 'slide-out-right', 'slide-next', 'slide-prev', 'fade-out-zoom', 'fade-in-zoom');
|
||||
el.classList.add('fade-out-zoom');
|
||||
});
|
||||
|
||||
stopMedia(); // Abort media BEFORE fetching random item
|
||||
// Pause media without stripping src so it doesn't flash black before fetch returns
|
||||
document.querySelectorAll('video, audio').forEach(m => { try { m.pause(); } catch (e) {} });
|
||||
|
||||
// Fade out background canvas for smooth transition
|
||||
const canvas = document.getElementById('bg');
|
||||
@@ -4595,14 +4715,79 @@ window.cancelAnimFrame = (function () {
|
||||
.then(data => {
|
||||
if (data.success && data.items && (data.items.slug || data.items.id)) {
|
||||
const targetKey = data.items.slug || data.items.id;
|
||||
// Navigate in the same context (user hall, favs, tag, etc.)
|
||||
const targetId = data.items.id;
|
||||
|
||||
// Navigate immediately — don't wait for grid sync
|
||||
if (wUserHall && wUserHallOwner) {
|
||||
loadItemAjax(`/user/${encodeURIComponent(wUserHallOwner)}/hall/${encodeURIComponent(wUserHall)}/${targetKey}`, true);
|
||||
loadItemAjax(`/user/${encodeURIComponent(wUserHallOwner)}/hall/${encodeURIComponent(wUserHall)}/${targetKey}`, true, { transition: 'fade-zoom' });
|
||||
} else if (wFavsUser) {
|
||||
// Preserve /user/:name/favs/:id context so next/prev arrows stay within favs
|
||||
loadItemAjax(`/user/${encodeURIComponent(wFavsUser)}/favs/${targetKey}`, true);
|
||||
loadItemAjax(`/user/${encodeURIComponent(wFavsUser)}/favs/${targetKey}`, true, { transition: 'fade-zoom' });
|
||||
} else {
|
||||
loadItemAjax(`/${targetKey}`, true);
|
||||
loadItemAjax(`/${targetKey}`, true, { transition: 'fade-zoom' });
|
||||
}
|
||||
|
||||
// Background grid sync for Onara — fire and forget, user never waits for this
|
||||
if (isOnaraActive() && targetId) {
|
||||
const gridThumbs = Array.from(document.querySelectorAll('.posts > a:not(.notif-item)'));
|
||||
const alreadyInGrid = gridThumbs.some(a => {
|
||||
const k = a.pathname.replace(/\/$/, '').split('/').pop();
|
||||
return k == targetId || (data.items.slug && k === data.items.slug);
|
||||
});
|
||||
console.log('[random-gridsync] isOnaraActive:', true, 'alreadyInGrid:', alreadyInGrid, 'targetId:', targetId, '_onaraCurrentGridUrl:', window._onaraCurrentGridUrl);
|
||||
|
||||
if (!alreadyInGrid) {
|
||||
const pageParams = new URLSearchParams(params);
|
||||
pageParams.set('id', targetId);
|
||||
console.log('[random-gridsync] fetching item-page:', `/api/v2/item-page?${pageParams}`);
|
||||
fetch(`/api/v2/item-page?${pageParams}`)
|
||||
.then(r => r.json())
|
||||
.then(pd => {
|
||||
console.log('[random-gridsync] item-page response:', pd);
|
||||
if (!pd.success || !pd.page) return;
|
||||
const targetPage = pd.page;
|
||||
const postsEl = document.querySelector('.posts[data-current-page]');
|
||||
const currentPage = postsEl ? parseInt(postsEl.dataset.currentPage, 10) : 1;
|
||||
console.log('[random-gridsync] targetPage:', targetPage, 'currentPage:', currentPage, '_onaraCurrentGridUrl:', window._onaraCurrentGridUrl);
|
||||
if (targetPage === currentPage) return;
|
||||
|
||||
let gridBase;
|
||||
if (window._onaraCurrentGridUrl) {
|
||||
// Strip trailing slash — root '/' becomes '' so '/p/N' builds correctly
|
||||
gridBase = window._onaraCurrentGridUrl.replace(/\/p\/\d+/, '').replace(/\/$/, '');
|
||||
} else {
|
||||
gridBase = window.location.pathname
|
||||
.replace(/\/[a-zA-Z0-9_-]{11}$/, '')
|
||||
.replace(/\/\d+$/, '')
|
||||
.replace(/\/p\/\d+/, '')
|
||||
.replace(/\/$/, '');
|
||||
}
|
||||
const pageUrl = targetPage === 1 ? (gridBase || '/') : `${gridBase}/p/${targetPage}`;
|
||||
console.log('[random-gridsync] fetching grid page:', pageUrl);
|
||||
|
||||
fetch(pageUrl)
|
||||
.then(r => r.text())
|
||||
.then(html => {
|
||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
const newPosts = doc.querySelector('.posts');
|
||||
const oldPosts = document.querySelector('.posts');
|
||||
console.log('[random-gridsync] grid swap: newPosts found:', !!newPosts, 'oldPosts found:', !!oldPosts);
|
||||
if (newPosts && oldPosts) {
|
||||
oldPosts.innerHTML = newPosts.innerHTML;
|
||||
oldPosts.dataset.currentPage = targetPage;
|
||||
if (typeof window.initLazyLoading === 'function') window.initLazyLoading();
|
||||
}
|
||||
window._onaraCurrentGridUrl = pageUrl;
|
||||
// Highlight after grid swapped
|
||||
if (typeof updateOnaraActiveItem === 'function') {
|
||||
updateOnaraActiveItem(targetId, `/${targetKey}`);
|
||||
}
|
||||
})
|
||||
.catch((e) => { console.warn('[random-gridsync] grid fetch failed', e); });
|
||||
})
|
||||
.catch((e) => { console.warn('[random-gridsync] item-page fetch failed', e); });
|
||||
}
|
||||
} else {
|
||||
console.log('[random-gridsync] skipped: isOnaraActive=', isOnaraActive(), 'targetId=', targetId);
|
||||
}
|
||||
} else {
|
||||
window.location.href = link.href;
|
||||
@@ -4697,20 +4882,15 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
|
||||
const parts = pathname.split('/').filter(Boolean);
|
||||
const isItemLink = !pathname.match(/\/p\//) && (
|
||||
pathname.match(/^\/\d+/) ||
|
||||
pathname.match(/^\/[a-zA-Z0-9_-]{11}(?:[?#]|$)/) ||
|
||||
(parts.length >= 3 && parts[0] === 'tag' && (/^\d+$/.test(parts[parts.length - 1]) || /^[a-zA-Z0-9_-]{11}$/.test(parts[parts.length - 1]))) ||
|
||||
(parts.length >= 3 && parts[0] === 'user' && (/^\d+$/.test(parts[parts.length - 1]) || /^[a-zA-Z0-9_-]{11}$/.test(parts[parts.length - 1]))) ||
|
||||
(parts.length >= 3 && parts[0] === 'h' && (/^\d+$/.test(parts[parts.length - 1]) || /^[a-zA-Z0-9_-]{11}$/.test(parts[parts.length - 1])))
|
||||
);
|
||||
const isItemLink = isItemPath(pathname);
|
||||
if (isItemLink) {
|
||||
// Links inside comment bodies or MOTD should not inherit tag/hall/user context
|
||||
const _inComment = anyLink.closest(".comment, .comment-content, .comment-body, .motd-content");
|
||||
loadItemAjax(targetUrl, !_inComment);
|
||||
} else {
|
||||
const isBrand = anyLink.classList.contains('navbar-brand');
|
||||
loadPageAjax(targetUrl, true, { bypassCache: isBrand });
|
||||
const fromModal = document.body.classList.contains('onara-modal-open') || !!anyLink.closest('#onara-modal');
|
||||
loadPageAjax(targetUrl, true, { bypassCache: isBrand, replaceHistory: fromModal });
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -5134,6 +5314,9 @@ window.cancelAnimFrame = (function () {
|
||||
});
|
||||
|
||||
window.addEventListener('popstate', (e) => {
|
||||
// Swallow popstate events fired during Onara close (history.go(-N) unwinding)
|
||||
if (window._onaraSuppressPopstate) return;
|
||||
|
||||
const url = window.location.href;
|
||||
const p = window.location.pathname;
|
||||
|
||||
@@ -5158,30 +5341,51 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
// Item detection logic MUST match loadPageAjax/loadItemAjax analysis
|
||||
// Priorities: Item first, then Special/Grid
|
||||
const parts = p.split('/').filter(Boolean);
|
||||
const isItem = !p.match(/\/p\//) && (
|
||||
p.match(/^\/\d+/) ||
|
||||
p.match(/^\/[a-zA-Z0-9_-]{11}(?:[?#]|$)/) ||
|
||||
(parts.length >= 3 && parts[0] === 'tag' && (/^\d+$/.test(parts[parts.length - 1]) || /^[a-zA-Z0-9_-]{11}$/.test(parts[parts.length - 1]))) ||
|
||||
(parts.length >= 3 && parts[0] === 'user' && (/^\d+$/.test(parts[parts.length - 1]) || /^[a-zA-Z0-9_-]{11}$/.test(parts[parts.length - 1]))) ||
|
||||
(parts.length >= 3 && parts[0] === 'h' && (/^\d+$/.test(parts[parts.length - 1]) || /^[a-zA-Z0-9_-]{11}$/.test(parts[parts.length - 1])))
|
||||
);
|
||||
const isItem = isItemPath(p);
|
||||
const isSpecial = p.startsWith('/notifications') || p.startsWith('/tags') || p.startsWith('/user/') || p.startsWith('/subscriptions') || p.startsWith('/ranking');
|
||||
const isGridLike = url.match(/\/p\/\d+/) || url.match(/[?&]page=\d+/) || p === '/';
|
||||
|
||||
window.f0ckDebug("[popstate] Navigation to:", url, { isItem, isSpecial, isGridLike });
|
||||
|
||||
if (document.body.classList.contains('onara-modal-open') && !isItem) {
|
||||
const isOnaraModalCurrentlyOpen = document.body.classList.contains('onara-modal-open') ||
|
||||
(document.getElementById('onara-modal') && document.getElementById('onara-modal').style.display !== 'none');
|
||||
|
||||
if (isOnaraModalCurrentlyOpen && !isItem) {
|
||||
closeOnaraModal({ skipHistory: true });
|
||||
if (isOnaraActive()) {
|
||||
const currentGrid = window._onaraCurrentGridUrl || (document.querySelector('.posts') ? (document.querySelector('.posts').dataset.currentUrl || '/') : '/');
|
||||
const targetPath = new URL(url, window.location.origin).pathname;
|
||||
const currentPath = new URL(currentGrid, window.location.origin).pathname;
|
||||
if (currentPath !== targetPath) {
|
||||
window._onaraCurrentGridUrl = url;
|
||||
loadPageAjax(url, true, { skipPush: true });
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isItem) {
|
||||
if (isOnaraActive()) {
|
||||
const expectedBaseUrl = getOnaraBaseUrl(url);
|
||||
const currentGrid = window._onaraCurrentGridUrl || (document.querySelector('.posts') ? (document.querySelector('.posts').dataset.currentUrl || '/') : '/');
|
||||
const expectedPath = new URL(expectedBaseUrl, window.location.origin).pathname;
|
||||
const currentPath = new URL(currentGrid, window.location.origin).pathname;
|
||||
if (currentPath !== expectedPath) {
|
||||
window._onaraCurrentGridUrl = expectedBaseUrl;
|
||||
loadPageAjax(expectedBaseUrl, true, { skipPush: true });
|
||||
}
|
||||
}
|
||||
loadItemAjax(url, true, { skipPush: true });
|
||||
} else if (isSpecial || isGridLike) {
|
||||
if (isOnaraActive()) {
|
||||
window._onaraCurrentGridUrl = url;
|
||||
}
|
||||
loadPageAjax(url, true, { skipPush: true });
|
||||
} else {
|
||||
// Fallback
|
||||
if (isOnaraActive()) {
|
||||
window._onaraCurrentGridUrl = url;
|
||||
}
|
||||
loadPageAjax(url, true, { skipPush: true });
|
||||
}
|
||||
});
|
||||
@@ -5358,17 +5562,32 @@ window.cancelAnimFrame = (function () {
|
||||
const imageModal = document.getElementById('image-modal');
|
||||
if (imageModal && imageModal.classList.contains('visible')) return;
|
||||
|
||||
const navBtn = event.target.closest('.nav-next, .nav-prev');
|
||||
const isNavHover = !!navBtn;
|
||||
const isMediaHover = !isNavHover && !!event.target.closest('.media-object') && !event.target.closest('#favs');
|
||||
// Yield if scroller/abyss page is active
|
||||
if (document.body && document.body.classList.contains('scroller-active')) return;
|
||||
|
||||
// For media-object, user preference 'wheelNavEnabled' must be enabled.
|
||||
// For .nav-next / .nav-prev, scrolling always triggers next/prev navigation directly.
|
||||
if (!isNavHover && (!isMediaHover || localStorage.getItem('wheelNavEnabled') !== 'true')) {
|
||||
// Don't hijack if user is inside an input, textarea, or contenteditable element
|
||||
if (event.target && (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA' || event.target.isContentEditable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always prevent default page scroll when scrolling over nav-next / nav-prev or media
|
||||
const isShiftWheel = event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey;
|
||||
const navBtn = event.target.closest('.nav-next, .nav-prev');
|
||||
const isNavHover = !!navBtn;
|
||||
const isMediaHover = !isNavHover && !isShiftWheel && !!event.target.closest('.media-object') && !event.target.closest('#favs');
|
||||
|
||||
// Trigger conditions:
|
||||
// 1. Shift + scrollwheel shortcut anywhere on post view
|
||||
// 2. Hovering over .nav-next / .nav-prev
|
||||
// 3. Hovering over media-object when 'wheelNavEnabled' preference is true
|
||||
if (!isShiftWheel && !isNavHover && (!isMediaHover || localStorage.getItem('wheelNavEnabled') !== 'true')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only intercept if item navigation buttons exist on the page
|
||||
const hasNav = !!document.querySelector("#next:not([href='#']), .nav-next:not([href='#']), #prev:not([href='#']), .nav-prev:not([href='#'])");
|
||||
if (!hasNav) return;
|
||||
|
||||
// Always prevent default page scroll when shortcut or target is matched
|
||||
event.preventDefault();
|
||||
|
||||
// Prevent rapid multi-firing while navigating or during throttle cooldown
|
||||
@@ -7519,11 +7738,20 @@ window.cancelAnimFrame = (function () {
|
||||
sb.style.setProperty('transition', 'none', 'important');
|
||||
if (isHidden) {
|
||||
layout.classList.remove('sidebar-hidden');
|
||||
document.body.classList.remove('sidebar-left-hidden');
|
||||
document.body.classList.remove('sidebar-left-hidden', 'comments-hidden');
|
||||
sb.style.removeProperty('display');
|
||||
sb.style.display = '';
|
||||
sb.querySelectorAll('.faded-out').forEach(el => el.classList.remove('faded-out'));
|
||||
sb.classList.remove('is-hidden');
|
||||
sb.querySelectorAll('.faded-out, .is-hidden').forEach(el => {
|
||||
el.classList.remove('faded-out', 'is-hidden');
|
||||
el.style.removeProperty('display');
|
||||
});
|
||||
const c = sb.querySelector('#comments-container');
|
||||
if (c) { c.classList.remove('faded-out'); c.style.display = ''; }
|
||||
if (c) {
|
||||
c.classList.remove('faded-out', 'is-hidden');
|
||||
c.style.removeProperty('display');
|
||||
c.style.display = '';
|
||||
}
|
||||
void sb.offsetWidth; // commit display + class change before setting transform
|
||||
sb.style.transform = `translateX(${-sw}px)`;
|
||||
} else {
|
||||
@@ -7544,14 +7772,15 @@ window.cancelAnimFrame = (function () {
|
||||
sb.style.removeProperty('transition');
|
||||
if (shouldOpen) {
|
||||
sb.style.removeProperty('transform');
|
||||
sb.style.removeProperty('display');
|
||||
localStorage.setItem('comments_hidden', 'false');
|
||||
document.body.classList.remove('sidebar-left-hidden');
|
||||
document.body.classList.remove('sidebar-left-hidden', 'comments-hidden');
|
||||
} else {
|
||||
// Hide BEFORE removing transform to prevent snap-back flash
|
||||
sb.style.display = 'none';
|
||||
sb.style.setProperty('display', 'none', 'important');
|
||||
layout.classList.add('sidebar-hidden');
|
||||
localStorage.setItem('comments_hidden', 'true');
|
||||
document.body.classList.add('sidebar-left-hidden');
|
||||
document.body.classList.add('sidebar-left-hidden', 'comments-hidden');
|
||||
sb.style.removeProperty('transform');
|
||||
}
|
||||
requestAnimationFrame(() => syncLeftEdgeZone());
|
||||
@@ -7772,7 +8001,11 @@ window.cancelAnimFrame = (function () {
|
||||
if (window.innerWidth < 1000) return;
|
||||
const { sb, layout } = getLS();
|
||||
if (!sb || !layout) return;
|
||||
const isHidden = layout.classList.contains('sidebar-hidden');
|
||||
const isHidden = layout.classList.contains('sidebar-hidden') ||
|
||||
document.body.classList.contains('sidebar-left-hidden') ||
|
||||
document.body.classList.contains('comments-hidden') ||
|
||||
localStorage.getItem('comments_hidden') === 'true';
|
||||
localStorage.setItem('comments_hidden', isHidden ? 'false' : 'true');
|
||||
const sw = isHidden ? Math.round(Math.min(400, window.innerWidth * 0.30)) : sb.offsetWidth;
|
||||
prepareDrag(sb, layout, isHidden, sw);
|
||||
// rAF ensures the initial transform state is painted before the transition starts
|
||||
@@ -9569,9 +9802,8 @@ class NotificationSystem {
|
||||
btn.style.visibility = 'visible';
|
||||
});
|
||||
|
||||
if (typeof prefetchNextPrevItems === 'function') {
|
||||
if (typeof requestIdleCallback === 'function') requestIdleCallback(() => prefetchNextPrevItems());
|
||||
else setTimeout(prefetchNextPrevItems, 200);
|
||||
if (typeof schedulePrefetch === 'function') {
|
||||
schedulePrefetch(800);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user