jdf
This commit is contained in:
+76
-8
@@ -2777,19 +2777,23 @@ body.sidebar-right-hidden #sidebar-drag-zone {
|
|||||||
/* Body-level left-sidebar hide — set by blocking inline script before first paint
|
/* Body-level left-sidebar hide — set by blocking inline script before first paint
|
||||||
to prevent the sidebar from flashing visible. Mirrors the .sidebar-hidden rules above
|
to prevent the sidebar from flashing visible. Mirrors the .sidebar-hidden rules above
|
||||||
but activates from the body class so it works before the container element exists. */
|
but activates from the body class so it works before the container element exists. */
|
||||||
body.layout-modern.sidebar-left-hidden .item-layout-container {
|
body.layout-modern.sidebar-left-hidden .item-layout-container,
|
||||||
|
body.layout-modern.comments-hidden .item-layout-container {
|
||||||
grid-template-columns: 0px minmax(0, 1fr) 400px;
|
grid-template-columns: 0px minmax(0, 1fr) 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.layout-modern.sidebar-left-hidden.sidebar-right-hidden .item-layout-container {
|
body.layout-modern.sidebar-left-hidden.sidebar-right-hidden .item-layout-container,
|
||||||
|
body.layout-modern.comments-hidden.sidebar-right-hidden .item-layout-container {
|
||||||
grid-template-columns: 0px minmax(0, 1fr) 0px;
|
grid-template-columns: 0px minmax(0, 1fr) 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.layout-modern.sidebar-left-hidden .item-layout-container .item-sidebar-left {
|
body.layout-modern.sidebar-left-hidden .item-layout-container .item-sidebar-left,
|
||||||
display: none;
|
body.layout-modern.comments-hidden .item-layout-container .item-sidebar-left {
|
||||||
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.layout-modern.sidebar-left-hidden .item-layout-container .item-main-content {
|
body.layout-modern.sidebar-left-hidden .item-layout-container .item-main-content,
|
||||||
|
body.layout-modern.comments-hidden .item-layout-container .item-main-content {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3324,6 +3328,27 @@ body.layout-legacy #comments-container.faded-out {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Full hidden state for comments & left sidebar — overrides flex !important so no plopping or ghost spacing occurs */
|
||||||
|
body.sidebar-left-hidden #comments-container,
|
||||||
|
body.comments-hidden #comments-container,
|
||||||
|
body.layout-legacy.sidebar-left-hidden #comments-container,
|
||||||
|
body.layout-legacy.comments-hidden #comments-container,
|
||||||
|
body.layout-legacy .item-layout-container.sidebar-hidden #comments-container,
|
||||||
|
body.layout-modern.sidebar-left-hidden #comments-container,
|
||||||
|
body.layout-modern.comments-hidden #comments-container,
|
||||||
|
body.layout-modern.sidebar-left-hidden .item-sidebar-left,
|
||||||
|
body.layout-modern.comments-hidden .item-sidebar-left,
|
||||||
|
body.layout-modern .item-layout-container.sidebar-hidden .item-sidebar-left,
|
||||||
|
body.sidebar-left-hidden #onara-modal #comments-container,
|
||||||
|
body.comments-hidden #onara-modal #comments-container,
|
||||||
|
body.sidebar-left-hidden #onara-modal .item-sidebar-left,
|
||||||
|
body.comments-hidden #onara-modal .item-sidebar-left,
|
||||||
|
#onara-modal #comments-container.is-hidden,
|
||||||
|
#comments-container.is-hidden,
|
||||||
|
.item-sidebar-left.is-hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
body.layout-legacy .comment-input {
|
body.layout-legacy .comment-input {
|
||||||
border-top: 1px solid var(--nav-border-color);
|
border-top: 1px solid var(--nav-border-color);
|
||||||
border-left: 1px solid var(--nav-border-color);
|
border-left: 1px solid var(--nav-border-color);
|
||||||
@@ -5772,6 +5797,49 @@ body.layout-modern.sidebar-right-hidden .pagination-container-fluid {
|
|||||||
will-change: transform, opacity;
|
will-change: transform, opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content.fade-in-zoom,
|
||||||
|
._204863.fade-in-zoom,
|
||||||
|
.item_title.fade-in-zoom,
|
||||||
|
#onara-modal .content.fade-in-zoom,
|
||||||
|
#onara-modal ._204863.fade-in-zoom,
|
||||||
|
#onara-modal .item_title.fade-in-zoom {
|
||||||
|
animation: contentFadeInZoom 0.35s cubic-bezier(0.16, 1, 0.3, 1) both !important;
|
||||||
|
will-change: transform, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content.fade-out-zoom,
|
||||||
|
._204863.fade-out-zoom,
|
||||||
|
.item_title.fade-out-zoom,
|
||||||
|
#onara-modal .content.fade-out-zoom,
|
||||||
|
#onara-modal ._204863.fade-out-zoom,
|
||||||
|
#onara-modal .item_title.fade-out-zoom {
|
||||||
|
animation: contentFadeOutZoom 0.18s cubic-bezier(0.3, 0, 0.8, 1) forwards !important;
|
||||||
|
pointer-events: none;
|
||||||
|
will-change: transform, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes contentFadeInZoom {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(1.03);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes contentFadeOutZoom {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.97);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes contentSlideIn {
|
@keyframes contentSlideIn {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -19028,9 +19096,9 @@ body.layout-modern #onara-modal .item-layout-container .item-main-content {
|
|||||||
margin-right: auto !important;
|
margin-right: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#onara-modal .content:not(.slide-next):not(.slide-prev):not(.slide-out-left):not(.slide-out-right),
|
#onara-modal .content:not(.slide-next):not(.slide-prev):not(.slide-out-left):not(.slide-out-right):not(.fade-in-zoom):not(.fade-out-zoom),
|
||||||
#onara-modal ._204863:not(.slide-next):not(.slide-prev):not(.slide-out-left):not(.slide-out-right),
|
#onara-modal ._204863:not(.slide-next):not(.slide-prev):not(.slide-out-left):not(.slide-out-right):not(.fade-in-zoom):not(.fade-out-zoom),
|
||||||
#onara-modal .item_title:not(.slide-next):not(.slide-prev):not(.slide-out-left):not(.slide-out-right) {
|
#onara-modal .item_title:not(.slide-next):not(.slide-prev):not(.slide-out-left):not(.slide-out-right):not(.fade-in-zoom):not(.fade-out-zoom) {
|
||||||
animation: contentSlideIn 0.55s cubic-bezier(0.16, 1, 0.3, 1) both !important;
|
animation: contentSlideIn 0.55s cubic-bezier(0.16, 1, 0.3, 1) both !important;
|
||||||
will-change: transform, opacity;
|
will-change: transform, opacity;
|
||||||
}
|
}
|
||||||
|
|||||||
+48
-14
@@ -48,18 +48,30 @@ class CommentSystem {
|
|||||||
const isHidden = localStorage.getItem('comments_hidden') === 'true';
|
const isHidden = localStorage.getItem('comments_hidden') === 'true';
|
||||||
// Force show if hash is present
|
// Force show if hash is present
|
||||||
if (window.location.hash && window.location.hash.startsWith('#c')) {
|
if (window.location.hash && window.location.hash.startsWith('#c')) {
|
||||||
this.container.classList.remove('faded-out');
|
this.container.classList.remove('faded-out', 'is-hidden');
|
||||||
this.container.style.display = 'block';
|
this.container.style.removeProperty('display');
|
||||||
|
this.container.style.display = '';
|
||||||
localStorage.setItem('comments_hidden', 'false');
|
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');
|
const layout = this.container.closest('.item-layout-container');
|
||||||
if (layout) layout.classList.remove('sidebar-hidden');
|
if (layout) layout.classList.remove('sidebar-hidden');
|
||||||
} else if (isHidden && (window.innerWidth >= 1000 || !document.body.classList.contains('layout-modern'))) {
|
const sidebar = this.container.closest('.item-sidebar-left');
|
||||||
this.container.classList.add('faded-out');
|
if (sidebar) {
|
||||||
this.container.style.display = 'none';
|
sidebar.classList.remove('is-hidden');
|
||||||
document.body.classList.add('sidebar-left-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');
|
const layout = this.container.closest('.item-layout-container');
|
||||||
if (layout) layout.classList.add('sidebar-hidden');
|
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();
|
e.preventDefault();
|
||||||
|
|
||||||
// If comments are hidden, show them first
|
// 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();
|
if (isHidden) cs.toggleComments();
|
||||||
|
|
||||||
// Legacy layout: comments are in the normal page flow under .item-main-content
|
// Legacy layout: comments are in the normal page flow under .item-main-content
|
||||||
@@ -3959,7 +3976,7 @@ class CommentSystem {
|
|||||||
toggleComments() {
|
toggleComments() {
|
||||||
if (!this.container) return;
|
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 (window.innerWidth < 1000) return;
|
||||||
if (typeof window.toggleSidebarLeft === 'function') {
|
if (typeof window.toggleSidebarLeft === 'function') {
|
||||||
window.toggleSidebarLeft();
|
window.toggleSidebarLeft();
|
||||||
@@ -3974,27 +3991,44 @@ class CommentSystem {
|
|||||||
] : [];
|
] : [];
|
||||||
|
|
||||||
// Check if currently hidden (or slid out)
|
// 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) {
|
if (isHidden) {
|
||||||
// SHOW: expand grid first, then slide content in
|
// SHOW: expand grid first, then slide content in
|
||||||
if (layout) layout.classList.remove('sidebar-hidden');
|
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 = '';
|
this.container.style.display = '';
|
||||||
|
if (sidebar) {
|
||||||
|
sidebar.classList.remove('is-hidden');
|
||||||
|
sidebar.style.removeProperty('display');
|
||||||
|
sidebar.style.display = '';
|
||||||
|
}
|
||||||
localStorage.setItem('comments_hidden', 'false');
|
localStorage.setItem('comments_hidden', 'false');
|
||||||
void this.container.offsetWidth; // force reflow so transition fires
|
void this.container.offsetWidth; // force reflow so transition fires
|
||||||
this.container.classList.remove('faded-out');
|
this.container.classList.remove('faded-out');
|
||||||
siblings.forEach(el => el.classList.remove('faded-out'));
|
siblings.forEach(el => el.classList.remove('faded-out'));
|
||||||
} else {
|
} 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');
|
localStorage.setItem('comments_hidden', 'true');
|
||||||
this.container.classList.add('faded-out');
|
this.container.classList.add('faded-out');
|
||||||
siblings.forEach(el => el.classList.add('faded-out'));
|
siblings.forEach(el => el.classList.add('faded-out'));
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!this.container.classList.contains('faded-out')) return;
|
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');
|
if (layout) layout.classList.add('sidebar-hidden');
|
||||||
document.body.classList.add('sidebar-left-hidden');
|
document.body.classList.add('sidebar-left-hidden', 'comments-hidden');
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+339
-107
@@ -1135,6 +1135,21 @@ window.cancelAnimFrame = (function () {
|
|||||||
};
|
};
|
||||||
window.updateOnaraActiveItem = updateOnaraActiveItem;
|
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) => {
|
const getOnaraBaseUrl = (itemUrl = window.location.href) => {
|
||||||
try {
|
try {
|
||||||
const urlObj = new URL(itemUrl, window.location.origin);
|
const urlObj = new URL(itemUrl, window.location.origin);
|
||||||
@@ -1142,7 +1157,8 @@ window.cancelAnimFrame = (function () {
|
|||||||
path = path.replace(/\/(?:\d+|[a-zA-Z0-9_-]{11})$/, '');
|
path = path.replace(/\/(?:\d+|[a-zA-Z0-9_-]{11})$/, '');
|
||||||
const postsEl = document.querySelector('.posts[data-current-page]');
|
const postsEl = document.querySelector('.posts[data-current-page]');
|
||||||
const currentPage = postsEl ? parseInt(postsEl.dataset.currentPage, 10) : 1;
|
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;
|
path = (path ? path : '') + '/p/' + currentPage;
|
||||||
}
|
}
|
||||||
if (!path) path = '/';
|
if (!path) path = '/';
|
||||||
@@ -1202,15 +1218,30 @@ window.cancelAnimFrame = (function () {
|
|||||||
|
|
||||||
if (!options.skipHistory) {
|
if (!options.skipHistory) {
|
||||||
const returnUrl = window._onaraReturnUrl || getOnaraBaseUrl();
|
const returnUrl = window._onaraReturnUrl || getOnaraBaseUrl();
|
||||||
history.pushState({}, '', returnUrl);
|
const returnTitle = window._onaraReturnTitle || window.f0ckDomain || '';
|
||||||
if (window._onaraReturnTitle) {
|
// Always jump directly to the return URL — never step back through stacked item history.
|
||||||
document.title = window._onaraReturnTitle;
|
// history.back() would re-open the previous item via popstate; replaceState exits cleanly.
|
||||||
} else if (window.f0ckDomain) {
|
const depth = window._onaraOpenHistoryLength != null
|
||||||
document.title = window.f0ckDomain;
|
? 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._onaraReturnUrl = null;
|
||||||
window._onaraReturnTitle = null;
|
window._onaraReturnTitle = null;
|
||||||
|
window._onaraOpenHistoryLength = null;
|
||||||
|
|
||||||
// Maintain focus on active item so user TAB navigation seamlessly resumes from current progress
|
// Maintain focus on active item so user TAB navigation seamlessly resumes from current progress
|
||||||
const activeThumb = document.querySelector('.posts > a.thumb.onara-active');
|
const activeThumb = document.querySelector('.posts > a.thumb.onara-active');
|
||||||
@@ -1806,6 +1837,21 @@ window.cancelAnimFrame = (function () {
|
|||||||
|
|
||||||
|
|
||||||
const _preloadedMediaUrls = new Set();
|
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) => {
|
const preloadMediaFromHtml = (html) => {
|
||||||
if (!html) return;
|
if (!html) return;
|
||||||
@@ -1813,7 +1859,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const doc = parser.parseFromString(html, 'text/html');
|
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');
|
const img = doc.querySelector('#f0ck-image, .embed-responsive-image img, .media-object img');
|
||||||
if (img) {
|
if (img) {
|
||||||
const src = img.getAttribute('src');
|
const src = img.getAttribute('src');
|
||||||
@@ -1837,20 +1883,9 @@ window.cancelAnimFrame = (function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Preload Video / Audio Media (fetch initial bytes into browser cache)
|
// Note: Video & Audio binary streams are deliberately NOT fetched via fetch() in JS.
|
||||||
const mediaEl = doc.querySelector('video#my-video, audio#my-video, .media-object video, .media-object audio');
|
// HTML5 media elements stream natively upon mounting. Fetching multi-megabyte chunks
|
||||||
if (mediaEl) {
|
// in the background exhausts the browser's 6-connection HTTP pool, stalling navigation.
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_preloadedMediaUrls.size > 150) {
|
if (_preloadedMediaUrls.size > 150) {
|
||||||
_preloadedMediaUrls.clear();
|
_preloadedMediaUrls.clear();
|
||||||
@@ -1861,11 +1896,20 @@ window.cancelAnimFrame = (function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const prefetchNextPrevItems = () => {
|
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 nextBtn = document.getElementById('next');
|
||||||
const prevBtn = document.getElementById('prev');
|
const prevBtn = document.getElementById('prev');
|
||||||
|
|
||||||
[nextBtn, prevBtn].forEach(btn => {
|
[nextBtn, prevBtn].forEach(btn => {
|
||||||
if (!btn || !btn.href || btn.href.endsWith('#')) return;
|
if (!btn || !btn.href || btn.href.endsWith('#')) return;
|
||||||
|
if (signal.aborted) return;
|
||||||
|
|
||||||
const pathSegments = new URL(btn.href, window.location.origin).pathname.split('/');
|
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));
|
const keySegments = pathSegments.filter(s => /^\d+$/.test(s) || /^[a-zA-Z0-9_-]{11}$/.test(s));
|
||||||
@@ -1907,17 +1951,17 @@ window.cancelAnimFrame = (function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(ajaxUrl, { credentials: 'include', priority: 'low' })
|
fetch(ajaxUrl, { credentials: 'include', priority: 'low', signal })
|
||||||
.then(r => r.ok ? r.text() : null)
|
.then(r => r.ok ? r.text() : null)
|
||||||
.then(rawText => {
|
.then(rawText => {
|
||||||
if (!rawText) return;
|
if (!rawText || signal.aborted) return;
|
||||||
let html = rawText;
|
let html = rawText;
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(rawText);
|
const data = JSON.parse(rawText);
|
||||||
if (data && typeof data.html === 'string') html = data.html;
|
if (data && typeof data.html === 'string') html = data.html;
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
if (html) {
|
if (html && !signal.aborted) {
|
||||||
itemCacheMap.set(ajaxUrl, { html, ts: Date.now() });
|
itemCacheMap.set(ajaxUrl, { html, ts: Date.now() });
|
||||||
if (itemCacheMap.size > ITEM_CACHE_MAX) {
|
if (itemCacheMap.size > ITEM_CACHE_MAX) {
|
||||||
itemCacheMap.delete(itemCacheMap.keys().next().value);
|
itemCacheMap.delete(itemCacheMap.keys().next().value);
|
||||||
@@ -1926,10 +1970,26 @@ window.cancelAnimFrame = (function () {
|
|||||||
preloadMediaFromHtml(html);
|
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 setupMedia = () => {
|
||||||
const elem = document.querySelector("#my-video") || document.querySelector("audio#my-video");
|
const elem = document.querySelector("#my-video") || document.querySelector("audio#my-video");
|
||||||
if (elem) {
|
if (elem) {
|
||||||
@@ -1948,6 +2008,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
window._onaraReturnUrl = getOnaraBaseUrl();
|
window._onaraReturnUrl = getOnaraBaseUrl();
|
||||||
window._onaraReturnTitle = window.f0ckDomain || 'f0ck';
|
window._onaraReturnTitle = window.f0ckDomain || 'f0ck';
|
||||||
}
|
}
|
||||||
|
window._onaraCurrentGridUrl = window._onaraReturnUrl;
|
||||||
const pathSegments = window.location.pathname.split('/');
|
const pathSegments = window.location.pathname.split('/');
|
||||||
const keySegments = pathSegments.filter(s => /^\d+$/.test(s) || /^[a-zA-Z0-9_-]{11}$/.test(s));
|
const keySegments = pathSegments.filter(s => /^\d+$/.test(s) || /^[a-zA-Z0-9_-]{11}$/.test(s));
|
||||||
const activeKey = keySegments.length ? keySegments[keySegments.length - 1] : null;
|
const activeKey = keySegments.length ? keySegments[keySegments.length - 1] : null;
|
||||||
@@ -1957,6 +2018,8 @@ window.cancelAnimFrame = (function () {
|
|||||||
window.trackVisit(activeKey);
|
window.trackVisit(activeKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
window._onaraCurrentGridUrl = window.location.pathname + window.location.search;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1964,11 +2027,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
setupMedia();
|
setupMedia();
|
||||||
initOnaraInitialState();
|
initOnaraInitialState();
|
||||||
if (typeof requestIdleCallback === 'function') {
|
schedulePrefetch(800);
|
||||||
requestIdleCallback(() => prefetchNextPrevItems());
|
|
||||||
} else {
|
|
||||||
setTimeout(prefetchNextPrevItems, 500);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
initOnaraInitialState();
|
initOnaraInitialState();
|
||||||
|
|
||||||
@@ -2820,6 +2879,10 @@ window.cancelAnimFrame = (function () {
|
|||||||
const loadPageAjax = async (url, replace = true, options = {}) => {
|
const loadPageAjax = async (url, replace = true, options = {}) => {
|
||||||
if (isNavigating) return;
|
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
|
// Immediately restore scrollability and hide modals
|
||||||
if (window.resetGlobalScrollState) window.resetGlobalScrollState();
|
if (window.resetGlobalScrollState) window.resetGlobalScrollState();
|
||||||
if (window.hideAllModals) window.hideAllModals();
|
if (window.hideAllModals) window.hideAllModals();
|
||||||
@@ -2882,7 +2945,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
const currentScroll = currentContainer ? currentContainer.scrollTop : window.scrollY;
|
const currentScroll = currentContainer ? currentContainer.scrollTop : window.scrollY;
|
||||||
|
|
||||||
// Save scroll position for the current page before we leave it (only for new navigations)
|
// 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 || {};
|
const currentState = history.state || {};
|
||||||
history.replaceState({ ...currentState, scroll: currentScroll }, document.title, window.location.href);
|
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)
|
// 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
|
// Restore scroll position
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
@@ -3001,6 +3070,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
if (window.initSidebarRightToggle) window.initSidebarRightToggle();
|
if (window.initSidebarRightToggle) window.initSidebarRightToggle();
|
||||||
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
||||||
window.NotificationSystemInstance?.pollDebounced?.();
|
window.NotificationSystemInstance?.pollDebounced?.();
|
||||||
|
window._onaraCurrentGridUrl = urlObj.pathname + urlObj.search;
|
||||||
isNavigating = false;
|
isNavigating = false;
|
||||||
return; // SKIP FETCH
|
return; // SKIP FETCH
|
||||||
}
|
}
|
||||||
@@ -3185,7 +3255,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Sync body classes (CRITICAL for layout triggers)
|
// 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));
|
const currentlyActive = persistClasses.filter(c => document.body.classList.contains(c));
|
||||||
|
|
||||||
document.body.className = doc.body.className;
|
document.body.className = doc.body.className;
|
||||||
@@ -3412,7 +3482,11 @@ window.cancelAnimFrame = (function () {
|
|||||||
|
|
||||||
// UPDATE HISTORY BEFORE INITIALIZING SCRIPTS
|
// UPDATE HISTORY BEFORE INITIALIZING SCRIPTS
|
||||||
if (!options.skipPush && !document.body.classList.contains('onara-modal-open')) {
|
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)
|
// Sync sidebar and comments-list layout (Legacy View Only)
|
||||||
@@ -3551,6 +3625,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window._onaraCurrentGridUrl = urlObj.pathname + urlObj.search;
|
||||||
return;
|
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)
|
// 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();
|
if (window.initSidebarRightToggle) window.initSidebarRightToggle();
|
||||||
// Sync has-notif highlights after grid loads — handles PWA where visibilitychange doesn't fire
|
// Sync has-notif highlights after grid loads — handles PWA where visibilitychange doesn't fire
|
||||||
window.NotificationSystemInstance?.pollDebounced?.();
|
window.NotificationSystemInstance?.pollDebounced?.();
|
||||||
|
window._onaraCurrentGridUrl = urlObj.pathname + urlObj.search;
|
||||||
|
|
||||||
// Instant jump to hash (e.g. #c123)
|
// Instant jump to hash (e.g. #c123)
|
||||||
if (hash) {
|
if (hash) {
|
||||||
@@ -3781,6 +3861,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
const loadItemAjax = async (url, inheritContext = true, options = {}) => {
|
const loadItemAjax = async (url, inheritContext = true, options = {}) => {
|
||||||
|
|
||||||
if (isNavigating) return;
|
if (isNavigating) return;
|
||||||
|
cancelPrefetch();
|
||||||
|
|
||||||
// Immediately restore scrollability and hide modals
|
// Immediately restore scrollability and hide modals
|
||||||
if (window.resetGlobalScrollState) window.resetGlobalScrollState();
|
if (window.resetGlobalScrollState) window.resetGlobalScrollState();
|
||||||
@@ -3793,8 +3874,14 @@ window.cancelAnimFrame = (function () {
|
|||||||
const useOnara = isOnaraActive() && (isGridPage || isModalOpen);
|
const useOnara = isOnaraActive() && (isGridPage || isModalOpen);
|
||||||
|
|
||||||
if (useOnara && !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;
|
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) ───────────────────
|
// ── Scroller-active cleanup (same as loadPageAjax) ───────────────────
|
||||||
@@ -4000,8 +4087,8 @@ window.cancelAnimFrame = (function () {
|
|||||||
const _itemCacheKey = ajaxUrl;
|
const _itemCacheKey = ajaxUrl;
|
||||||
const _cachedItem = !options.skipCache ? itemCacheMap.get(_itemCacheKey) : null;
|
const _cachedItem = !options.skipCache ? itemCacheMap.get(_itemCacheKey) : null;
|
||||||
|
|
||||||
// Allow slide-out animation to visibly start before content swap
|
// Allow slide-out or fade-out animation to visibly start before content swap
|
||||||
if (options.direction && document.querySelector('.content')) {
|
if ((options.direction || options.transition === 'fade-zoom') && document.querySelector('.content')) {
|
||||||
await new Promise(r => setTimeout(r, 180));
|
await new Promise(r => setTimeout(r, 180));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4065,13 +4152,39 @@ window.cancelAnimFrame = (function () {
|
|||||||
if (_o && _n) _o.replaceWith(_n.cloneNode(true));
|
if (_o && _n) _o.replaceWith(_n.cloneNode(true));
|
||||||
});
|
});
|
||||||
} else {
|
} 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);
|
_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) {
|
if (options.direction) {
|
||||||
const _newEls = _container.querySelectorAll('.content, ._204863, .item_title');
|
const _newEls = _container.querySelectorAll('.content, ._204863, .item_title');
|
||||||
_newEls.forEach(el => {
|
_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');
|
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(() => {});
|
.catch(() => {});
|
||||||
|
|
||||||
if (typeof requestIdleCallback === 'function') {
|
schedulePrefetch(600);
|
||||||
requestIdleCallback(() => prefetchNextPrevItems());
|
|
||||||
} else {
|
|
||||||
setTimeout(prefetchNextPrevItems, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
return; // Done — served from cache
|
return; // Done — served from cache
|
||||||
}
|
}
|
||||||
@@ -4279,13 +4388,39 @@ window.cancelAnimFrame = (function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} 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);
|
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) {
|
if (options.direction) {
|
||||||
const newEls = container.querySelectorAll('.content, ._204863, .item_title');
|
const newEls = container.querySelectorAll('.content, ._204863, .item_title');
|
||||||
newEls.forEach(el => {
|
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');
|
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
|
// Note: Prefetching video src immediately after DOM injection has been removed
|
||||||
@@ -4365,11 +4500,7 @@ window.cancelAnimFrame = (function () {
|
|||||||
console.error("updateStrictLinks error:", err);
|
console.error("updateStrictLinks error:", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof requestIdleCallback === 'function') {
|
schedulePrefetch(600);
|
||||||
requestIdleCallback(() => prefetchNextPrevItems());
|
|
||||||
} else {
|
|
||||||
setTimeout(prefetchNextPrevItems, 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
// After comments have rendered (f0ck:contentLoaded above triggers synchronous render),
|
// After comments have rendered (f0ck:contentLoaded above triggers synchronous render),
|
||||||
// constrain the comments-list height via direct measurement (flex chain unreliable in AJAX).
|
// 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') {
|
if (link.id === 'random' || link.id === 'nav-random') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// In Onara mode with a background grid, pick a random item from the grid so it reflects on the main page
|
const outEls = document.querySelectorAll('.content, ._204863, .item_title');
|
||||||
if (isOnaraActive()) {
|
outEls.forEach(el => {
|
||||||
const gridThumbs = Array.from(document.querySelectorAll('.posts > a:not(.notif-item)'));
|
el.classList.remove('slide-out-left', 'slide-out-right', 'slide-next', 'slide-prev', 'fade-out-zoom', 'fade-in-zoom');
|
||||||
if (gridThumbs.length > 0) {
|
el.classList.add('fade-out-zoom');
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
// Fade out background canvas for smooth transition
|
||||||
const canvas = document.getElementById('bg');
|
const canvas = document.getElementById('bg');
|
||||||
@@ -4595,14 +4715,79 @@ window.cancelAnimFrame = (function () {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success && data.items && (data.items.slug || data.items.id)) {
|
if (data.success && data.items && (data.items.slug || data.items.id)) {
|
||||||
const targetKey = 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) {
|
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) {
|
} else if (wFavsUser) {
|
||||||
// Preserve /user/:name/favs/:id context so next/prev arrows stay within favs
|
loadItemAjax(`/user/${encodeURIComponent(wFavsUser)}/favs/${targetKey}`, true, { transition: 'fade-zoom' });
|
||||||
loadItemAjax(`/user/${encodeURIComponent(wFavsUser)}/favs/${targetKey}`, true);
|
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
window.location.href = link.href;
|
window.location.href = link.href;
|
||||||
@@ -4697,20 +4882,15 @@ window.cancelAnimFrame = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parts = pathname.split('/').filter(Boolean);
|
const parts = pathname.split('/').filter(Boolean);
|
||||||
const isItemLink = !pathname.match(/\/p\//) && (
|
const isItemLink = isItemPath(pathname);
|
||||||
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])))
|
|
||||||
);
|
|
||||||
if (isItemLink) {
|
if (isItemLink) {
|
||||||
// Links inside comment bodies or MOTD should not inherit tag/hall/user context
|
// Links inside comment bodies or MOTD should not inherit tag/hall/user context
|
||||||
const _inComment = anyLink.closest(".comment, .comment-content, .comment-body, .motd-content");
|
const _inComment = anyLink.closest(".comment, .comment-content, .comment-body, .motd-content");
|
||||||
loadItemAjax(targetUrl, !_inComment);
|
loadItemAjax(targetUrl, !_inComment);
|
||||||
} else {
|
} else {
|
||||||
const isBrand = anyLink.classList.contains('navbar-brand');
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5134,6 +5314,9 @@ window.cancelAnimFrame = (function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('popstate', (e) => {
|
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 url = window.location.href;
|
||||||
const p = window.location.pathname;
|
const p = window.location.pathname;
|
||||||
|
|
||||||
@@ -5158,30 +5341,51 @@ window.cancelAnimFrame = (function () {
|
|||||||
|
|
||||||
// Item detection logic MUST match loadPageAjax/loadItemAjax analysis
|
// Item detection logic MUST match loadPageAjax/loadItemAjax analysis
|
||||||
// Priorities: Item first, then Special/Grid
|
// Priorities: Item first, then Special/Grid
|
||||||
const parts = p.split('/').filter(Boolean);
|
const isItem = isItemPath(p);
|
||||||
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 isSpecial = p.startsWith('/notifications') || p.startsWith('/tags') || p.startsWith('/user/') || p.startsWith('/subscriptions') || p.startsWith('/ranking');
|
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 === '/';
|
const isGridLike = url.match(/\/p\/\d+/) || url.match(/[?&]page=\d+/) || p === '/';
|
||||||
|
|
||||||
window.f0ckDebug("[popstate] Navigation to:", url, { isItem, isSpecial, isGridLike });
|
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 });
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isItem) {
|
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 });
|
loadItemAjax(url, true, { skipPush: true });
|
||||||
} else if (isSpecial || isGridLike) {
|
} else if (isSpecial || isGridLike) {
|
||||||
|
if (isOnaraActive()) {
|
||||||
|
window._onaraCurrentGridUrl = url;
|
||||||
|
}
|
||||||
loadPageAjax(url, true, { skipPush: true });
|
loadPageAjax(url, true, { skipPush: true });
|
||||||
} else {
|
} else {
|
||||||
// Fallback
|
// Fallback
|
||||||
|
if (isOnaraActive()) {
|
||||||
|
window._onaraCurrentGridUrl = url;
|
||||||
|
}
|
||||||
loadPageAjax(url, true, { skipPush: true });
|
loadPageAjax(url, true, { skipPush: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -5358,17 +5562,32 @@ window.cancelAnimFrame = (function () {
|
|||||||
const imageModal = document.getElementById('image-modal');
|
const imageModal = document.getElementById('image-modal');
|
||||||
if (imageModal && imageModal.classList.contains('visible')) return;
|
if (imageModal && imageModal.classList.contains('visible')) return;
|
||||||
|
|
||||||
const navBtn = event.target.closest('.nav-next, .nav-prev');
|
// Yield if scroller/abyss page is active
|
||||||
const isNavHover = !!navBtn;
|
if (document.body && document.body.classList.contains('scroller-active')) return;
|
||||||
const isMediaHover = !isNavHover && !!event.target.closest('.media-object') && !event.target.closest('#favs');
|
|
||||||
|
|
||||||
// For media-object, user preference 'wheelNavEnabled' must be enabled.
|
// Don't hijack if user is inside an input, textarea, or contenteditable element
|
||||||
// For .nav-next / .nav-prev, scrolling always triggers next/prev navigation directly.
|
if (event.target && (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA' || event.target.isContentEditable)) {
|
||||||
if (!isNavHover && (!isMediaHover || localStorage.getItem('wheelNavEnabled') !== 'true')) {
|
|
||||||
return;
|
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();
|
event.preventDefault();
|
||||||
|
|
||||||
// Prevent rapid multi-firing while navigating or during throttle cooldown
|
// Prevent rapid multi-firing while navigating or during throttle cooldown
|
||||||
@@ -7519,11 +7738,20 @@ window.cancelAnimFrame = (function () {
|
|||||||
sb.style.setProperty('transition', 'none', 'important');
|
sb.style.setProperty('transition', 'none', 'important');
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
layout.classList.remove('sidebar-hidden');
|
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.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');
|
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
|
void sb.offsetWidth; // commit display + class change before setting transform
|
||||||
sb.style.transform = `translateX(${-sw}px)`;
|
sb.style.transform = `translateX(${-sw}px)`;
|
||||||
} else {
|
} else {
|
||||||
@@ -7544,14 +7772,15 @@ window.cancelAnimFrame = (function () {
|
|||||||
sb.style.removeProperty('transition');
|
sb.style.removeProperty('transition');
|
||||||
if (shouldOpen) {
|
if (shouldOpen) {
|
||||||
sb.style.removeProperty('transform');
|
sb.style.removeProperty('transform');
|
||||||
|
sb.style.removeProperty('display');
|
||||||
localStorage.setItem('comments_hidden', 'false');
|
localStorage.setItem('comments_hidden', 'false');
|
||||||
document.body.classList.remove('sidebar-left-hidden');
|
document.body.classList.remove('sidebar-left-hidden', 'comments-hidden');
|
||||||
} else {
|
} else {
|
||||||
// Hide BEFORE removing transform to prevent snap-back flash
|
// Hide BEFORE removing transform to prevent snap-back flash
|
||||||
sb.style.display = 'none';
|
sb.style.setProperty('display', 'none', 'important');
|
||||||
layout.classList.add('sidebar-hidden');
|
layout.classList.add('sidebar-hidden');
|
||||||
localStorage.setItem('comments_hidden', 'true');
|
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');
|
sb.style.removeProperty('transform');
|
||||||
}
|
}
|
||||||
requestAnimationFrame(() => syncLeftEdgeZone());
|
requestAnimationFrame(() => syncLeftEdgeZone());
|
||||||
@@ -7772,7 +8001,11 @@ window.cancelAnimFrame = (function () {
|
|||||||
if (window.innerWidth < 1000) return;
|
if (window.innerWidth < 1000) return;
|
||||||
const { sb, layout } = getLS();
|
const { sb, layout } = getLS();
|
||||||
if (!sb || !layout) return;
|
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;
|
const sw = isHidden ? Math.round(Math.min(400, window.innerWidth * 0.30)) : sb.offsetWidth;
|
||||||
prepareDrag(sb, layout, isHidden, sw);
|
prepareDrag(sb, layout, isHidden, sw);
|
||||||
// rAF ensures the initial transform state is painted before the transition starts
|
// rAF ensures the initial transform state is painted before the transition starts
|
||||||
@@ -9569,9 +9802,8 @@ class NotificationSystem {
|
|||||||
btn.style.visibility = 'visible';
|
btn.style.visibility = 'visible';
|
||||||
});
|
});
|
||||||
|
|
||||||
if (typeof prefetchNextPrevItems === 'function') {
|
if (typeof schedulePrefetch === 'function') {
|
||||||
if (typeof requestIdleCallback === 'function') requestIdleCallback(() => prefetchNextPrevItems());
|
schedulePrefetch(800);
|
||||||
else setTimeout(prefetchNextPrevItems, 200);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -570,6 +570,43 @@ export default router => {
|
|||||||
res.end("api lol");
|
res.end("api lol");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Lightweight page-lookup for Onara grid sync.
|
||||||
|
// Called async after random navigation — user never waits for this.
|
||||||
|
group.get(/\/item-page$/, async (req, res) => {
|
||||||
|
const id = parseInt(req.url.qs.id, 10) || 0;
|
||||||
|
if (!id) return res.json({ success: false, page: 1 });
|
||||||
|
|
||||||
|
const tag = req.url.qs.tag || null;
|
||||||
|
const hall = req.url.qs.hall || null;
|
||||||
|
const userHall = req.url.qs.userHall || null;
|
||||||
|
const userHallOwner= req.url.qs.userHallOwner|| null;
|
||||||
|
const user = req.url.qs.user || null;
|
||||||
|
const mime = req.url.qs.mime || null;
|
||||||
|
const isFav = req.url.qs.fav === 'true';
|
||||||
|
const isStrict = req.url.qs.strict === '1';
|
||||||
|
const mode = req.mode ?? 0;
|
||||||
|
const ratingsRaw = req.cookies.ratings;
|
||||||
|
const ratingsArr = ratingsRaw ? decodeURIComponent(ratingsRaw).split(/[|,]/).filter(r => ['sfw','nsfw','nsfl','untagged'].includes(r)) : null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const page = await f0cklib.getItemPage({
|
||||||
|
targetItemId: id,
|
||||||
|
user, tag, hall, userHall, userHallOwner, mime,
|
||||||
|
fav: isFav,
|
||||||
|
mode,
|
||||||
|
ratings: ratingsArr && ratingsArr.length > 0 ? ratingsArr : null,
|
||||||
|
strict: isStrict,
|
||||||
|
session: !!req.session,
|
||||||
|
exclude: req.session?.excluded_tags || [],
|
||||||
|
user_id: req.session?.id,
|
||||||
|
is_admin: req.session?.admin
|
||||||
|
});
|
||||||
|
return res.json({ success: true, page });
|
||||||
|
} catch (e) {
|
||||||
|
return res.json({ success: false, page: 1 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
group.get(/\/random(\/user\/.+|\/image|\/video|\/audio)?$/, async (req, res) => {
|
group.get(/\/random(\/user\/.+|\/image|\/video|\/audio)?$/, async (req, res) => {
|
||||||
const pathParts = req.url.pathname.split('/');
|
const pathParts = req.url.pathname.split('/');
|
||||||
// /api/v2/random/user/name -> segments are ["", "api", "v2", "random", "user", "name"]
|
// /api/v2/random/user/name -> segments are ["", "api", "v2", "random", "user", "name"]
|
||||||
@@ -629,7 +666,7 @@ export default router => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isYouTube = item.mime === 'video/youtube';
|
const isYouTube = item.mime === 'video/youtube';
|
||||||
const ytSrcRegex = /(?:youtube\.com\/\S*(?:(?:\/e(?:mbed))?\/|watch\/?\/?\?(?:\S*?&?v=))|youtu\.be\/)([a-zA-Z0-9_-]{6,11})/i;
|
const ytSrcRegex = /(?:youtube\.com\/\S*(?:(?:\/e(?:mbed))?\/|watch\/?\/?\?(?:\S*?&v=))|youtu\.be\/)([a-zA-Z0-9_-]{6,11})/i;
|
||||||
let ytDest = item.dest;
|
let ytDest = item.dest;
|
||||||
if (isYouTube && (!ytDest || !ytDest.startsWith('yt:'))) {
|
if (isYouTube && (!ytDest || !ytDest.startsWith('yt:'))) {
|
||||||
const m = item.src && item.src.match(ytSrcRegex);
|
const m = item.src && item.src.match(ytSrcRegex);
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="@if(session)@if(session.use_new_layout)layout-modern@else layout-legacy @endif@else @if(default_layout === 'legacy')layout-legacy@else layout-modern@endif @endif @if(private_society && !session)private-gate-active@endif @if(is_onara_item) onara-modal-open @endif">
|
<body class="@if(session)@if(session.use_new_layout)layout-modern@else layout-legacy @endif@else @if(default_layout === 'legacy')layout-legacy@else layout-modern@endif @endif @if(private_society && !session)private-gate-active@endif @if(is_onara_item) onara-modal-open @endif">
|
||||||
<script>var sRH = localStorage.getItem('sidebarRightHidden'); if(sRH==='true' || (sRH===null && @if(hide_sidebar_default) true @else false @endif)) document.body.classList.add('sidebar-right-hidden'); if(localStorage.getItem('comments_hidden')==='true')document.body.classList.add('sidebar-left-hidden');(function(){var d=window.devicePixelRatio||1;console.log('[DPR] devicePixelRatio='+d);var t='dpr-1x';if(d>=1.55)t='dpr-high';else if(d>=1.39)t='dpr-150';else if(d>=1.26)t='dpr-130';else if(d>=1.20)t='dpr-120';else if(d>=1.05)t='dpr-110';document.documentElement.setAttribute('data-dpr',t);})();</script>
|
<script>var sRH = localStorage.getItem('sidebarRightHidden'); if(sRH==='true' || (sRH===null && @if(hide_sidebar_default) true @else false @endif)) document.body.classList.add('sidebar-right-hidden'); if(localStorage.getItem('comments_hidden')==='true')document.body.classList.add('sidebar-left-hidden', 'comments-hidden');(function(){var d=window.devicePixelRatio||1;console.log('[DPR] devicePixelRatio='+d);var t='dpr-1x';if(d>=1.55)t='dpr-high';else if(d>=1.39)t='dpr-150';else if(d>=1.26)t='dpr-130';else if(d>=1.20)t='dpr-120';else if(d>=1.05)t='dpr-110';document.documentElement.setAttribute('data-dpr',t);})();</script>
|
||||||
@if(!private_society || session)
|
@if(!private_society || session)
|
||||||
<canvas class="hidden-xs" id="bg"></canvas>
|
<canvas class="hidden-xs" id="bg"></canvas>
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
@@ -319,6 +319,7 @@
|
|||||||
<div class="shortcut-item"><span><kbd>←</kbd> <kbd>→</kbd></span><span>{{ t('shortcuts.next_prev') }}</span></div>
|
<div class="shortcut-item"><span><kbd>←</kbd> <kbd>→</kbd></span><span>{{ t('shortcuts.next_prev') }}</span></div>
|
||||||
<div class="shortcut-item"><span><kbd>↑</kbd> <kbd>↓</kbd></span><span>{{ t('shortcuts.volume') }}</span></div>
|
<div class="shortcut-item"><span><kbd>↑</kbd> <kbd>↓</kbd></span><span>{{ t('shortcuts.volume') }}</span></div>
|
||||||
<div class="shortcut-item"><span><kbd>Scroll</kbd></span><span>{{ t('shortcuts.scroll_nav') }}</span></div>
|
<div class="shortcut-item"><span><kbd>Scroll</kbd></span><span>{{ t('shortcuts.scroll_nav') }}</span></div>
|
||||||
|
<div class="shortcut-item"><span><kbd>Shift</kbd> + <kbd>Scroll</kbd></span><span>{{ t('shortcuts.next_prev') }}</span></div>
|
||||||
<div class="shortcut-item"><span><kbd>,</kbd> <kbd>.</kbd></span><span>{{ t('shortcuts.frame_skip') }}</span></div>
|
<div class="shortcut-item"><span><kbd>,</kbd> <kbd>.</kbd></span><span>{{ t('shortcuts.frame_skip') }}</span></div>
|
||||||
<div class="shortcut-item"><span><kbd>?</kbd></span><span>{{ t('shortcuts.show_help') }}</span></div>
|
<div class="shortcut-item"><span><kbd>?</kbd></span><span>{{ t('shortcuts.show_help') }}</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user