This commit is contained in:
2026-09-11 21:45:54 +02:00
parent 52ed9fd7bd
commit fe5763efe4
10 changed files with 233 additions and 33 deletions
+66 -10
View File
@@ -71,7 +71,7 @@ html[theme='f0ck'] {
--metadata-bg: #2b2b2b;
--badge-bg: #171717;
--posts-meta-bg: #000000b8;
--badge-sfw: #68a728;
--badge-sfw: #02500b;
--badge-nsfw: #E10DC3;
--badge-nsfl: #660000;
--badge-tag: #090909;
@@ -132,7 +132,7 @@ html[theme='p1nk'] {
--pagination-background-hover: #333;
--pagination-border-color: rgba(0, 0, 0, .8) rgba(0, 0, 0, .65) rgba(0, 0, 0, .5);
--badge-bg: #171717;
--badge-sfw: #68a728;
--badge-sfw: #02500b;
--badge-nsfw: #E10DC3;
--badge-nsfl: #660000;
--badge-tag: #090909;
@@ -193,7 +193,7 @@ html[theme='orange'] {
--badge-bg: #151515;
--posts-meta-bg: #000000b8;
--badge-tag: #090909;
--badge-sfw: #68a728;
--badge-sfw: #02500b;
--badge-nsfw: #E10DC3;
--badge-nsfl: #660000;
--scrollbar-color: #555;
@@ -250,7 +250,7 @@ html[theme='amoled'] {
--metadata-bg: #000;
--badge-bg: #000;
--posts-meta-bg: #000000b8;
--badge-sfw: #68a728;
--badge-sfw: #02500b;
--badge-nsfw: #E10DC3;
--badge-nsfl: #660000;
--badge-tag: #1a1a1a;
@@ -347,7 +347,7 @@ html[theme='paper'],
--metadata-bg: #ffffff;
--badge-bg: #f1f5f9;
--posts-meta-bg: rgba(255, 255, 255, 0.94);
--badge-sfw: #16a34a;
--badge-sfw: #02500b;
--badge-nsfw: #db2777;
--badge-nsfl: #dc2626;
--badge-tag: #f1f5f9;
@@ -5192,10 +5192,17 @@ h5 {
margin-right: 0.5rem !important;
}
/* Thumbnail size — driven by data-thumb-size on <html> (set by scroller grid-mode picker) */
:root { --thumb-min: 118px; }
html[data-thumb-size="s"] { --thumb-min: 80px; }
html[data-thumb-size="m"] { --thumb-min: 118px; }
html[data-thumb-size="l"] { --thumb-min: 180px; }
html[data-thumb-size="xl"] { --thumb-min: 260px; }
div.posts {
width: 100%;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(var(--thumb-min, 118px), 1fr));
grid-auto-flow: dense;
justify-items: center;
grid-gap: 5px;
@@ -5204,9 +5211,9 @@ div.posts {
margin-bottom: 35px;
}
/* Mobile: Ensure 3 columns of thumbnails */
/* Mobile: Ensure at least 3 columns unless user picked a larger size */
@media (max-width: 600px) {
div.posts {
html:not([data-thumb-size="l"]):not([data-thumb-size="xl"]) div.posts {
grid-template-columns: repeat(3, 1fr);
}
}
@@ -6918,6 +6925,7 @@ a.removetag i {
.badge-german {
background: linear-gradient(180deg, black 33.33%, red 33.33%, red 66.66%, yellow 66.66%) !important;
box-shadow: 0px 0px 1px white;
}
.badge-dutch {
@@ -15789,6 +15797,53 @@ body.layout-modern .xd-score-wrapper {
background: rgba(0, 0, 0, 0.2);
}
/* ─── Grid mode / thumbnail size picker (filter modal) ────────────── */
.nav-grid-mode {
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.nav-grid-mode-label {
display: block;
font-size: 0.8em;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #888;
margin-bottom: 8px;
}
.nav-grid-size-btns {
display: flex;
gap: 6px;
}
.nav-grid-size-btn {
flex: 1;
padding: 7px 10px;
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.12);
color: rgba(255, 255, 255, 0.75);
font-size: 0.82em;
font-weight: 700;
font-family: var(--font, monospace);
cursor: pointer;
border-radius: 4px;
transition: background 0.14s, border-color 0.14s, color 0.14s;
letter-spacing: 0.04em;
}
.nav-grid-size-btn:hover {
background: rgba(255, 255, 255, 0.13);
color: #fff;
}
.nav-grid-size-btn.active {
background: var(--accent);
border-color: var(--accent);
color: #000;
}
/* ─── xD score wrapper ─────────────────────────────────────────────── */
.xd-score-wrapper {
text-align: right;
@@ -18892,6 +18947,7 @@ html:has(body.onara-modal-open) {
body.onara-modal-open .pagewrapper {
pointer-events: none !important;
user-select: none !important;
margin-top: var(--navbar-h, 50px) !important;
}
body.onara-modal-open .pagewrapper > *:not(.index-layout-wrapper):not(#main),
@@ -18938,7 +18994,7 @@ body.onara-modal-open nav.navbar {
filter: none !important;
pointer-events: auto !important;
z-index: 10060 !important;
position: sticky !important;
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
@@ -18975,7 +19031,7 @@ body.onara-modal-open #sidebar-drag-zone {
z-index: 10050 !important;
display: none;
flex-direction: column !important;
background: rgba(10, 12, 16, 0.72) !important;
background: rgba(0, 0, 0, 0.70) !important;
backdrop-filter: blur(5px) saturate(130%) !important;
-webkit-backdrop-filter: blur(5px) saturate(130%) !important;
overflow-y: auto !important;
+106 -15
View File
@@ -1155,10 +1155,26 @@ window.cancelAnimFrame = (function () {
const urlObj = new URL(itemUrl, window.location.origin);
let path = urlObj.pathname.replace(/\/+$/, '');
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;
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)) {
// Check current grid URL if available and matching base path
if (window._onaraCurrentGridUrl) {
try {
const gridObj = new URL(window._onaraCurrentGridUrl, window.location.origin);
const gridBasePath = gridObj.pathname.replace(/\/p\/\d+/, '').replace(/\/+$/, '');
if (gridBasePath === path) {
return gridObj.pathname + (gridObj.search || '') + (gridObj.hash || '');
}
} catch {}
}
const postsEl = document.querySelector('.posts');
const activePagSpan = document.querySelector('.pagination span.btn.disabled, .pagination span.disabled');
const pagPage = activePagSpan ? parseInt(activePagSpan.textContent.trim(), 10) : 0;
const currentPage = (postsEl && postsEl.dataset.currentPage)
? parseInt(postsEl.dataset.currentPage, 10)
: (pagPage || postsEl?._infiniteState?.currentPage || postsEl?._infiniteState?.visiblePage || 1);
if (currentPage > 1 && !path.includes('/p/')) {
path = (path ? path : '') + '/p/' + currentPage;
}
if (!path) path = '/';
@@ -1216,6 +1232,14 @@ window.cancelAnimFrame = (function () {
if (window.initBackground) window.initBackground();
}
// Restore pagination container visibility on background grid
document.querySelectorAll('.pagination-container-fluid').forEach(el => {
const pagWrapper = el.querySelector('.pagination-wrapper');
if (!pagWrapper || pagWrapper.innerHTML.trim().length > 0) {
el.style.display = '';
}
});
if (!options.skipHistory) {
const returnUrl = window._onaraReturnUrl || getOnaraBaseUrl();
const returnTitle = window._onaraReturnTitle || window.f0ckDomain || '';
@@ -3971,7 +3995,16 @@ window.cancelAnimFrame = (function () {
// Clear and Hide navbar pagination for Item View (Never show grid pagination on item view)
// document.querySelectorAll('.pagination-wrapper').forEach(el => el.innerHTML = ''); // Don't destroy content (cached grid needs it)
document.querySelectorAll('.pagination-container-fluid').forEach(el => el.style.display = 'none');
if (!useOnara) {
document.querySelectorAll('.pagination-container-fluid').forEach(el => el.style.display = 'none');
} else {
document.querySelectorAll('.pagination-container-fluid').forEach(el => {
const pagWrapper = el.querySelector('.pagination-wrapper');
if (!pagWrapper || pagWrapper.innerHTML.trim().length > 0) {
el.style.display = '';
}
});
}
if (keySegments.length === 0) {
console.warn("loadItemAjax: No ID or slug match found in URL", url);
@@ -5740,7 +5773,7 @@ window.cancelAnimFrame = (function () {
}
}
delete postsContainer.dataset.currentPage; // Clear after reading
postsContainer.dataset.currentPage = p;
}
// Track initially loaded page
@@ -5823,6 +5856,7 @@ window.cancelAnimFrame = (function () {
// Update URL
infiniteState.visiblePage = newPage;
if (postsContainer) postsContainer.dataset.currentPage = newPage;
history.replaceState({}, '', buildUrl(newPage));
// Update Pagination
@@ -6882,6 +6916,33 @@ window.cancelAnimFrame = (function () {
}
});
}
// ── Grid Mode / thumbnail size picker ────────────────────────────────
const THUMB_SIZE_KEY = 'scroller_thumb_size';
const THUMB_SIZES = ['s', 'm', 'l', 'xl'];
const gridSizeBtns = overlay.querySelectorAll('.nav-grid-size-btn');
const applyNavThumbSize = (size) => {
if (!THUMB_SIZES.includes(size)) size = 'm';
document.documentElement.dataset.thumbSize = size;
localStorage.setItem(THUMB_SIZE_KEY, size);
gridSizeBtns.forEach(b => b.classList.toggle('active', b.dataset.thumbSize === size));
};
// Sync active state each time the modal opens
if (filterBtn) {
filterBtn.addEventListener('click', () => {
const cur = localStorage.getItem(THUMB_SIZE_KEY) || 'm';
gridSizeBtns.forEach(b => b.classList.toggle('active', b.dataset.thumbSize === cur));
});
}
gridSizeBtns.forEach(btn => {
btn.addEventListener('click', () => applyNavThumbSize(btn.dataset.thumbSize));
});
// Apply persisted size immediately on init (every page load)
applyNavThumbSize(localStorage.getItem(THUMB_SIZE_KEY) || 'm');
};
document.addEventListener('DOMContentLoaded', () => {
@@ -7662,26 +7723,49 @@ window.cancelAnimFrame = (function () {
// At ≤599px the sidebar is a pure overlay — never animate wrapper padding
const animateWrappers = window.innerWidth > 599;
// Grid/pagewrapper: snap instantly in both directions (no animated reflow).
// Pagination always animates — it tracks sidebar position with no reflow cost.
// All wrappers animate in sync with the sidebar so content and sidebar
// expand/collapse together rather than staggering.
const wrappers = getSidebarWrappers();
if (animateWrappers) {
wrappers.forEach(w => {
const isPagination = w.classList.contains('pagination-container-fluid');
const isMessages = w.classList.contains('messages-convo-page');
const prop = (isPagination || isMessages) ? 'right' : 'padding-right';
const targetVal = isHidden ? sidebarWidth + 'px' : '0px';
// Lightweight layouts (pagination, messages) animate smoothly.
// Heavy/reflow-intensive layouts snap instantly to avoid reflow lag.
const shouldAnimate = (isPagination || isMessages);
w.style.setProperty('transition', shouldAnimate ? `${prop} 0.3s ease-in-out` : 'none', 'important');
w.style.setProperty('transition', `${prop} 0.3s ease-in-out`, 'important');
w.style.setProperty(prop, targetVal, 'important');
});
void sidebar.offsetWidth; // settle layout before sidebar transform begins
}
// Animate the drag-zone pill in sync with the sidebar so it stays
// glued to the sidebar's left edge throughout the transition.
edgeZone.style.setProperty('transition', 'right 0.3s ease-in-out', 'important');
if (isHidden) {
// Opening: pill moves from right-edge → left of sidebar
edgeZone.style.right = sidebarWidth + 'px';
edgeZone.style.width = '25px';
edgeZone.style.pointerEvents = 'all';
} else {
// Closing: pill moves toward right-edge
edgeZone.style.right = '0px';
edgeZone.style.width = '30px';
edgeZone.style.pointerEvents = 'all';
}
// Animate the Onara modal wrapper's right edge in sync with the sidebar
// so the modal resizes at the same time instead of waiting for settle.
const onaraModal = document.getElementById('onara-modal');
if (onaraModal && animateWrappers) {
const targetModalRight = isHidden ? sidebarWidth + 'px' : '0px';
onaraModal.style.setProperty('transition',
'opacity 0.28s cubic-bezier(0.16,1,0.3,1), transform 0.28s cubic-bezier(0.16,1,0.3,1), right 0.3s ease-in-out',
'important');
onaraModal.style.setProperty('right', targetModalRight, 'important');
}
sidebar.style.setProperty('transition', 'transform 0.3s ease-in-out', 'important');
sidebar.style.transform = `translateX(${targetTranslate}px)`;
@@ -7689,9 +7773,11 @@ window.cancelAnimFrame = (function () {
const settle = () => {
if (settled) return;
settled = true;
// Freeze wrapper transitions so the class commit doesn't re-trigger them
// Freeze wrapper and edgeZone transitions so the class commit doesn't re-trigger them
wrappers.forEach(w => w.style.setProperty('transition', 'none', 'important'));
sidebar.style.setProperty('transition', 'none', 'important');
edgeZone.style.setProperty('transition', 'none', 'important');
if (onaraModal) onaraModal.style.setProperty('transition', 'none', 'important');
const toHidden = !isHidden;
document.body.classList.toggle('sidebar-right-hidden', toHidden);
localStorage.setItem('sidebarRightHidden', toHidden);
@@ -7699,6 +7785,11 @@ window.cancelAnimFrame = (function () {
sidebar.style.transform = '';
requestAnimationFrame(() => {
sidebar.style.removeProperty('transition');
edgeZone.style.removeProperty('transition');
if (onaraModal) {
onaraModal.style.removeProperty('transition');
onaraModal.style.removeProperty('right');
}
wrappers.forEach(w => {
w.style.removeProperty('transition');
w.style.removeProperty('padding-right');
+31 -2
View File
@@ -79,8 +79,9 @@
const CACHE_MAX = 200;
const CACHE_TTL = 30 * 60 * 1000;
const VOL_KEY = 'scroller_volume';
const PREFS_KEY = 'scroller_prefs';
const PRESETS_KEY = 'scroller_presets';
const PREFS_KEY = 'scroller_prefs';
const PRESETS_KEY = 'scroller_presets';
const THUMB_SIZE_KEY = 'scroller_thumb_size';
// ── User Preferences ──────────────────────────────────────────────────────
function loadPrefs() {
@@ -97,6 +98,33 @@
let autoNextLoops = Math.max(0, parseInt(prefs.autoNextLoops ?? 1, 10));
let leftHandEnabled = prefs.leftHand === true;
// ── Grid / Thumbnail size ─────────────────────────────────────────────────
const THUMB_SIZES = ['s', 'm', 'l', 'xl'];
let thumbSize = localStorage.getItem(THUMB_SIZE_KEY) || 'm';
if (!THUMB_SIZES.includes(thumbSize)) thumbSize = 'm';
function applyThumbSize(size) {
thumbSize = size;
document.documentElement.dataset.thumbSize = size;
localStorage.setItem(THUMB_SIZE_KEY, size);
// Sync pill active state whenever called outside the click handler
document.querySelectorAll('#thumb-size-pills .filter-pill').forEach(p =>
p.classList.toggle('active', p.dataset.thumbSize === size)
);
}
// Apply persisted size on load
applyThumbSize(thumbSize);
// Wire pill click events
const thumbSizePillsEl = document.getElementById('thumb-size-pills');
if (thumbSizePillsEl) {
thumbSizePillsEl.querySelectorAll('.filter-pill').forEach(pill => {
pill.addEventListener('click', () => {
applyThumbSize(pill.dataset.thumbSize);
});
});
}
let applied = { mode: defaultMode, mime: '', order: 'random', tags: [], externalUrl: null };
let pending = { ...applied, tags: [] };
@@ -2988,6 +3016,7 @@
document.querySelectorAll('#mode-pills .filter-pill').forEach(p => p.classList.toggle('active', +p.dataset.mode === pending.mode));
document.querySelectorAll('#mime-pills .filter-pill').forEach(p => p.classList.toggle('active', p.dataset.mime === pending.mime));
document.querySelectorAll('#order-pills .filter-pill').forEach(p => p.classList.toggle('active', p.dataset.order === pending.order));
document.querySelectorAll('#thumb-size-pills .filter-pill').forEach(p => p.classList.toggle('active', p.dataset.thumbSize === thumbSize));
if (externalUrlInput) externalUrlInput.value = pending.externalUrl || '';
renderActiveTags();
}