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; --metadata-bg: #2b2b2b;
--badge-bg: #171717; --badge-bg: #171717;
--posts-meta-bg: #000000b8; --posts-meta-bg: #000000b8;
--badge-sfw: #68a728; --badge-sfw: #02500b;
--badge-nsfw: #E10DC3; --badge-nsfw: #E10DC3;
--badge-nsfl: #660000; --badge-nsfl: #660000;
--badge-tag: #090909; --badge-tag: #090909;
@@ -132,7 +132,7 @@ html[theme='p1nk'] {
--pagination-background-hover: #333; --pagination-background-hover: #333;
--pagination-border-color: rgba(0, 0, 0, .8) rgba(0, 0, 0, .65) rgba(0, 0, 0, .5); --pagination-border-color: rgba(0, 0, 0, .8) rgba(0, 0, 0, .65) rgba(0, 0, 0, .5);
--badge-bg: #171717; --badge-bg: #171717;
--badge-sfw: #68a728; --badge-sfw: #02500b;
--badge-nsfw: #E10DC3; --badge-nsfw: #E10DC3;
--badge-nsfl: #660000; --badge-nsfl: #660000;
--badge-tag: #090909; --badge-tag: #090909;
@@ -193,7 +193,7 @@ html[theme='orange'] {
--badge-bg: #151515; --badge-bg: #151515;
--posts-meta-bg: #000000b8; --posts-meta-bg: #000000b8;
--badge-tag: #090909; --badge-tag: #090909;
--badge-sfw: #68a728; --badge-sfw: #02500b;
--badge-nsfw: #E10DC3; --badge-nsfw: #E10DC3;
--badge-nsfl: #660000; --badge-nsfl: #660000;
--scrollbar-color: #555; --scrollbar-color: #555;
@@ -250,7 +250,7 @@ html[theme='amoled'] {
--metadata-bg: #000; --metadata-bg: #000;
--badge-bg: #000; --badge-bg: #000;
--posts-meta-bg: #000000b8; --posts-meta-bg: #000000b8;
--badge-sfw: #68a728; --badge-sfw: #02500b;
--badge-nsfw: #E10DC3; --badge-nsfw: #E10DC3;
--badge-nsfl: #660000; --badge-nsfl: #660000;
--badge-tag: #1a1a1a; --badge-tag: #1a1a1a;
@@ -347,7 +347,7 @@ html[theme='paper'],
--metadata-bg: #ffffff; --metadata-bg: #ffffff;
--badge-bg: #f1f5f9; --badge-bg: #f1f5f9;
--posts-meta-bg: rgba(255, 255, 255, 0.94); --posts-meta-bg: rgba(255, 255, 255, 0.94);
--badge-sfw: #16a34a; --badge-sfw: #02500b;
--badge-nsfw: #db2777; --badge-nsfw: #db2777;
--badge-nsfl: #dc2626; --badge-nsfl: #dc2626;
--badge-tag: #f1f5f9; --badge-tag: #f1f5f9;
@@ -5192,10 +5192,17 @@ h5 {
margin-right: 0.5rem !important; 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 { div.posts {
width: 100%; width: 100%;
display: grid; 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; grid-auto-flow: dense;
justify-items: center; justify-items: center;
grid-gap: 5px; grid-gap: 5px;
@@ -5204,9 +5211,9 @@ div.posts {
margin-bottom: 35px; 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) { @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); grid-template-columns: repeat(3, 1fr);
} }
} }
@@ -6918,6 +6925,7 @@ a.removetag i {
.badge-german { .badge-german {
background: linear-gradient(180deg, black 33.33%, red 33.33%, red 66.66%, yellow 66.66%) !important; 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 { .badge-dutch {
@@ -15789,6 +15797,53 @@ body.layout-modern .xd-score-wrapper {
background: rgba(0, 0, 0, 0.2); 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 ─────────────────────────────────────────────── */
.xd-score-wrapper { .xd-score-wrapper {
text-align: right; text-align: right;
@@ -18892,6 +18947,7 @@ html:has(body.onara-modal-open) {
body.onara-modal-open .pagewrapper { body.onara-modal-open .pagewrapper {
pointer-events: none !important; pointer-events: none !important;
user-select: none !important; user-select: none !important;
margin-top: var(--navbar-h, 50px) !important;
} }
body.onara-modal-open .pagewrapper > *:not(.index-layout-wrapper):not(#main), body.onara-modal-open .pagewrapper > *:not(.index-layout-wrapper):not(#main),
@@ -18938,7 +18994,7 @@ body.onara-modal-open nav.navbar {
filter: none !important; filter: none !important;
pointer-events: auto !important; pointer-events: auto !important;
z-index: 10060 !important; z-index: 10060 !important;
position: sticky !important; position: fixed !important;
top: 0 !important; top: 0 !important;
left: 0 !important; left: 0 !important;
width: 100% !important; width: 100% !important;
@@ -18975,7 +19031,7 @@ body.onara-modal-open #sidebar-drag-zone {
z-index: 10050 !important; z-index: 10050 !important;
display: none; display: none;
flex-direction: column !important; 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; backdrop-filter: blur(5px) saturate(130%) !important;
-webkit-backdrop-filter: blur(5px) saturate(130%) !important; -webkit-backdrop-filter: blur(5px) saturate(130%) !important;
overflow-y: auto !important; overflow-y: auto !important;
+103 -12
View File
@@ -1155,10 +1155,26 @@ window.cancelAnimFrame = (function () {
const urlObj = new URL(itemUrl, window.location.origin); const urlObj = new URL(itemUrl, window.location.origin);
let path = urlObj.pathname.replace(/\/+$/, ''); let path = urlObj.pathname.replace(/\/+$/, '');
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 currentPage = postsEl ? parseInt(postsEl.dataset.currentPage, 10) : 1; // Check current grid URL if available and matching base path
const currentGridPath = window._onaraCurrentGridUrl ? new URL(window._onaraCurrentGridUrl, window.location.origin).pathname.replace(/\/p\/\d+/, '').replace(/\/+$/, '') : ''; if (window._onaraCurrentGridUrl) {
if (currentPage > 1 && !path.includes('/p/') && (!currentGridPath || currentGridPath === path)) { 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; path = (path ? path : '') + '/p/' + currentPage;
} }
if (!path) path = '/'; if (!path) path = '/';
@@ -1216,6 +1232,14 @@ window.cancelAnimFrame = (function () {
if (window.initBackground) window.initBackground(); 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) { if (!options.skipHistory) {
const returnUrl = window._onaraReturnUrl || getOnaraBaseUrl(); const returnUrl = window._onaraReturnUrl || getOnaraBaseUrl();
const returnTitle = window._onaraReturnTitle || window.f0ckDomain || ''; 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) // 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-wrapper').forEach(el => el.innerHTML = ''); // Don't destroy content (cached grid needs it)
if (!useOnara) {
document.querySelectorAll('.pagination-container-fluid').forEach(el => el.style.display = 'none'); 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) { if (keySegments.length === 0) {
console.warn("loadItemAjax: No ID or slug match found in URL", url); 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 // Track initially loaded page
@@ -5823,6 +5856,7 @@ window.cancelAnimFrame = (function () {
// Update URL // Update URL
infiniteState.visiblePage = newPage; infiniteState.visiblePage = newPage;
if (postsContainer) postsContainer.dataset.currentPage = newPage;
history.replaceState({}, '', buildUrl(newPage)); history.replaceState({}, '', buildUrl(newPage));
// Update Pagination // 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', () => { document.addEventListener('DOMContentLoaded', () => {
@@ -7662,8 +7723,8 @@ window.cancelAnimFrame = (function () {
// At ≤599px the sidebar is a pure overlay — never animate wrapper padding // At ≤599px the sidebar is a pure overlay — never animate wrapper padding
const animateWrappers = window.innerWidth > 599; const animateWrappers = window.innerWidth > 599;
// Grid/pagewrapper: snap instantly in both directions (no animated reflow). // All wrappers animate in sync with the sidebar so content and sidebar
// Pagination always animates — it tracks sidebar position with no reflow cost. // expand/collapse together rather than staggering.
const wrappers = getSidebarWrappers(); const wrappers = getSidebarWrappers();
if (animateWrappers) { if (animateWrappers) {
wrappers.forEach(w => { wrappers.forEach(w => {
@@ -7673,15 +7734,38 @@ window.cancelAnimFrame = (function () {
const prop = (isPagination || isMessages) ? 'right' : 'padding-right'; const prop = (isPagination || isMessages) ? 'right' : 'padding-right';
const targetVal = isHidden ? sidebarWidth + 'px' : '0px'; const targetVal = isHidden ? sidebarWidth + 'px' : '0px';
// Lightweight layouts (pagination, messages) animate smoothly. w.style.setProperty('transition', `${prop} 0.3s ease-in-out`, 'important');
// 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(prop, targetVal, 'important'); w.style.setProperty(prop, targetVal, 'important');
}); });
void sidebar.offsetWidth; // settle layout before sidebar transform begins 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.setProperty('transition', 'transform 0.3s ease-in-out', 'important');
sidebar.style.transform = `translateX(${targetTranslate}px)`; sidebar.style.transform = `translateX(${targetTranslate}px)`;
@@ -7689,9 +7773,11 @@ window.cancelAnimFrame = (function () {
const settle = () => { const settle = () => {
if (settled) return; if (settled) return;
settled = true; 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')); wrappers.forEach(w => w.style.setProperty('transition', 'none', 'important'));
sidebar.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; const toHidden = !isHidden;
document.body.classList.toggle('sidebar-right-hidden', toHidden); document.body.classList.toggle('sidebar-right-hidden', toHidden);
localStorage.setItem('sidebarRightHidden', toHidden); localStorage.setItem('sidebarRightHidden', toHidden);
@@ -7699,6 +7785,11 @@ window.cancelAnimFrame = (function () {
sidebar.style.transform = ''; sidebar.style.transform = '';
requestAnimationFrame(() => { requestAnimationFrame(() => {
sidebar.style.removeProperty('transition'); sidebar.style.removeProperty('transition');
edgeZone.style.removeProperty('transition');
if (onaraModal) {
onaraModal.style.removeProperty('transition');
onaraModal.style.removeProperty('right');
}
wrappers.forEach(w => { wrappers.forEach(w => {
w.style.removeProperty('transition'); w.style.removeProperty('transition');
w.style.removeProperty('padding-right'); w.style.removeProperty('padding-right');
+29
View File
@@ -81,6 +81,7 @@
const VOL_KEY = 'scroller_volume'; const VOL_KEY = 'scroller_volume';
const PREFS_KEY = 'scroller_prefs'; const PREFS_KEY = 'scroller_prefs';
const PRESETS_KEY = 'scroller_presets'; const PRESETS_KEY = 'scroller_presets';
const THUMB_SIZE_KEY = 'scroller_thumb_size';
// ── User Preferences ────────────────────────────────────────────────────── // ── User Preferences ──────────────────────────────────────────────────────
function loadPrefs() { function loadPrefs() {
@@ -97,6 +98,33 @@
let autoNextLoops = Math.max(0, parseInt(prefs.autoNextLoops ?? 1, 10)); let autoNextLoops = Math.max(0, parseInt(prefs.autoNextLoops ?? 1, 10));
let leftHandEnabled = prefs.leftHand === true; 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 applied = { mode: defaultMode, mime: '', order: 'random', tags: [], externalUrl: null };
let pending = { ...applied, tags: [] }; 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('#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('#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('#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 || ''; if (externalUrlInput) externalUrlInput.value = pending.externalUrl || '';
renderActiveTags(); renderActiveTags();
} }
+6 -2
View File
@@ -153,7 +153,11 @@ export default (router, tpl) => {
}; };
userData.age_days = Math.floor((Date.now() - new Date(userData.created_at).getTime()) / 86400000); userData.age_days = Math.floor((Date.now() - new Date(userData.created_at).getTime()) / 86400000);
if (userData.banned) { if (!req.session) {
userData.banned = false;
delete userData.ban_expires;
delete userData.ban_duration;
} else if (userData.banned) {
if (!userData.ban_expires) { if (!userData.ban_expires) {
userData.ban_duration = "Permanent"; userData.ban_duration = "Permanent";
} else { } else {
@@ -412,7 +416,7 @@ export default (router, tpl) => {
if (mode === 'item' && isOnara) { if (mode === 'item' && isOnara) {
const itemHtml = tpl.render('ajax-item', data, req); const itemHtml = tpl.render('ajax-item', data, req);
const isRandom = req.cookies.random_mode === '1'; const isRandom = req.cookies.random_mode === '1' || req.url.qs?.random === '1' || req.query?.random === '1';
let itemPage = 1; let itemPage = 1;
if (req.params.page) { if (req.params.page) {
itemPage = parseInt(req.params.page, 10) || 1; itemPage = parseInt(req.params.page, 10) || 1;
+1 -1
View File
@@ -68,7 +68,7 @@ export default (router, tpl) => {
}); });
} }
res.redirect(encodeURI(`${data.link.main}${data.link.path}${data.itemid}${data.link.suffix || ''}`)); res.redirect(encodeURI(`${data.link.main}${data.link.path}${data.itemid}${data.link.suffix || ''}`) + '?random=1');
}); });
return router; return router;
+1 -1
View File
@@ -174,7 +174,7 @@
<span class="tags-inner"> <span class="tags-inner">
@if(!item.is_sfw && !item.is_nsfw && !item.is_nsfl) @if(!item.is_sfw && !item.is_nsfw && !item.is_nsfl)
<span class="badge badge-untagged rating-tag is-untagged @if(can_manage_item) can-cycle @endif" data-rating="untagged"> <span class="badge badge-untagged rating-tag is-untagged @if(can_manage_item) can-cycle @endif" data-rating="untagged">
<span class="rating-label">untagged</span> <span class="rating-label">?</span>
</span> </span>
@endif @endif
@if(typeof item.tags !== "undefined") @if(typeof item.tags !== "undefined")
+1 -1
View File
@@ -43,7 +43,7 @@
<span class="badge badge-dark" id="tags" data-can-manage="{{ can_manage_item ? 'true' : 'false' }}" style="display: flex; flex-wrap: wrap; gap: 5px; background: transparent; padding: 0; text-align: left; white-space: normal;"> <span class="badge badge-dark" id="tags" data-can-manage="{{ can_manage_item ? 'true' : 'false' }}" style="display: flex; flex-wrap: wrap; gap: 5px; background: transparent; padding: 0; text-align: left; white-space: normal;">
@if(!item.is_sfw && !item.is_nsfw && !item.is_nsfl) @if(!item.is_sfw && !item.is_nsfw && !item.is_nsfl)
<span class="badge badge-untagged rating-tag is-untagged @if(can_manage_item) can-cycle @endif" data-rating="untagged"> <span class="badge badge-untagged rating-tag is-untagged @if(can_manage_item) can-cycle @endif" data-rating="untagged">
<span class="rating-label">untagged</span> <span class="rating-label">?</span>
</span> </span>
@endif @endif
@if(typeof item.tags !== "undefined") @if(typeof item.tags !== "undefined")
+10
View File
@@ -1152,6 +1152,16 @@
</div> </div>
</div> </div>
<div class="filter-section" id="grid-mode-section">
<div class="filter-section-label"><i class="fa-solid fa-grid-2" style="margin-right:5px;font-size:.72rem"></i>Grid Mode</div>
<div class="pill-group" id="thumb-size-pills">
<button class="filter-pill" data-thumb-size="s"><i class="fa-solid fa-table-cells"></i>S</button>
<button class="filter-pill active" data-thumb-size="m"><i class="fa-solid fa-table-cells-large"></i>M</button>
<button class="filter-pill" data-thumb-size="l"><i class="fa-solid fa-table-list"></i>L</button>
<button class="filter-pill" data-thumb-size="xl"><i class="fa-solid fa-square"></i>XL</button>
</div>
</div>
<div class="filter-section"> <div class="filter-section">
<div class="filter-section-label">{{ t('scroller.tags') }}</div> <div class="filter-section-label">{{ t('scroller.tags') }}</div>
<div class="tag-search-wrap"> <div class="tag-search-wrap">
+10
View File
@@ -52,5 +52,15 @@
<div id="nav_xd_status" style="font-size: 0.8em; color: #9f0; min-height: 1em; margin-top: 3px;"></div> <div id="nav_xd_status" style="font-size: 0.8em; color: #9f0; min-height: 1em; margin-top: 3px;"></div>
</div> </div>
@endif @endif
<!-- grid mode / thumbnail size -->
<div class="nav-grid-mode">
<label class="nav-grid-mode-label"><i class="fa-solid fa-grip" style="margin-right:5px"></i>{{ t('filter.grid_mode') || 'Grid Mode' }}</label>
<div class="nav-grid-size-btns">
<button class="nav-grid-size-btn" data-thumb-size="s" title="Small thumbnails">S</button>
<button class="nav-grid-size-btn" data-thumb-size="m" title="Medium thumbnails (default)">M</button>
<button class="nav-grid-size-btn" data-thumb-size="l" title="Large thumbnails">L</button>
<button class="nav-grid-size-btn" data-thumb-size="xl" title="Extra large thumbnails">XL</button>
</div>
</div>
</div> </div>
</div> </div>
+1 -1
View File
@@ -48,7 +48,7 @@
<div class="profile_head_username"> <div class="profile_head_username">
<div style="display: flex; justify-content: space-between; align-items: flex-start; gap: 10px;"> <div style="display: flex; justify-content: space-between; align-items: flex-start; gap: 10px;">
<div style="flex: 1; min-width: 0; word-break: break-word; line-height: 1.2; align-self: flex-start; margin-top: 0; display: flex; align-items: center; gap: 5px;" id="profile-name-container"> <div style="flex: 1; min-width: 0; word-break: break-word; line-height: 1.2; align-self: flex-start; margin-top: 0; display: flex; align-items: center; gap: 5px;" id="profile-name-container">
<span id="profile-display-name" @if(user.username_color) style="color: {{ user.username_color }}" @endif>@if(user.admin)&#9889;&nbsp;@elseif(user.is_moderator)&#128737;&nbsp;@endif{!! user.display_name || user.user !!}@if(user.is_ghost) <span class="badge badge-secondary" style="font-size: 0.5em; vertical-align: middle; background-color: #5bc0de; color: #fff; padding: 2px 5px; border-radius: 3px; margin-left: 5px;">LEGACY</span>@endif @if(user.banned) <span class="badge badge-danger" tooltip="{{ user.ban_duration }}" style="font-size: 0.5em; vertical-align: middle; background-color: #d9534f; color: #fff; padding: 2px 5px; border-radius: 3px; margin-left: 5px;">BANNED</span>@endif</span>@if(user.display_name) <span style="font-size: 0.65em; color: #666; font-weight: 400; margin-left: 5px; letter-spacing: 0.5px;" id="username-bracket">({!! user.user !!})</span>@endif <span id="profile-display-name" @if(user.username_color) style="color: {{ user.username_color }}" @endif>@if(user.admin)&#9889;&nbsp;@elseif(user.is_moderator)&#128737;&nbsp;@endif{!! user.display_name || user.user !!}@if(user.is_ghost) <span class="badge badge-secondary" style="font-size: 0.5em; vertical-align: middle; background-color: #5bc0de; color: #fff; padding: 2px 5px; border-radius: 3px; margin-left: 5px;">LEGACY</span>@endif @if(session && user.banned) <span class="badge badge-danger" tooltip="{{ user.ban_duration }}" style="font-size: 0.5em; vertical-align: middle; background-color: #d9534f; color: #fff; padding: 2px 5px; border-radius: 3px; margin-left: 5px;">BANNED</span>@endif</span>@if(user.display_name) <span style="font-size: 0.65em; color: #666; font-weight: 400; margin-left: 5px; letter-spacing: 0.5px;" id="username-bracket">({!! user.user !!})</span>@endif
@if(session && session.id === user.user_id) @if(session && session.id === user.user_id)
<button id="inline-name-edit-btn" style="background: transparent; border:none; color: var(--text-muted); cursor: pointer; font-size: 0.7em; padding: 0;" title="Edit Name & Color"> <button id="inline-name-edit-btn" style="background: transparent; border:none; color: var(--text-muted); cursor: pointer; font-size: 0.7em; padding: 0;" title="Edit Name & Color">
<i class="fa-solid fa-pen"></i> <i class="fa-solid fa-pen"></i>