gfds
This commit is contained in:
@@ -220,7 +220,8 @@
|
||||
}
|
||||
#report-modal .report-modal-content * { border-radius: 0 !important; }
|
||||
#report-modal .rm-header { position: relative; flex-shrink: 0; padding: 20px 64px 14px 24px; border-bottom: 1px solid var(--rm-border); }
|
||||
#report-modal .rm-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 16px 24px; }
|
||||
#report-modal .rm-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 16px 24px; scrollbar-width: none !important; -ms-overflow-style: none; }
|
||||
#report-modal .rm-body::-webkit-scrollbar { display: none; width: 0; height: 0; }
|
||||
#report-modal .rm-body > :last-child { margin-bottom: 0; }
|
||||
#report-modal .rm-header h3 { margin: 0; font-size: 1.25em; font-weight: 700; color: var(--rm-text); }
|
||||
#report-modal .rm-header p { margin: 6px 0 0; font-size: 0.85em; line-height: 1.5; color: var(--rm-muted); }
|
||||
@@ -417,11 +418,17 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="global-sidebar-right-footer">
|
||||
@if(session)
|
||||
<a href="/ranking" data-page-modal title="{{ t('footer.ranking') }}" aria-label="{{ t('footer.ranking') }}"><i class="fa-solid fa-users-between-lines"></i></a>
|
||||
@endif
|
||||
<a href="/rules" data-page-modal title="{{ t('footer.rules') }}" aria-label="{{ t('footer.rules') }}"><i class="fa-solid fa-scale-balanced"></i></a>
|
||||
<a href="/about" data-page-modal title="{{ t('footer.about') }}" aria-label="{{ t('footer.about') }}"><i class="fa-solid fa-info"></i></a>
|
||||
<a href="/privacy" data-page-modal title="Privacy" aria-label="Privacy"><i class="fa-solid fa-shield-halved"></i></a>
|
||||
<div id="help-button" style="color: var(--accent); font-weight: bold; opacity: 0.7;" title="Keyboard Shortcuts" aria-label="Keyboard Shortcuts"><i class="fa-solid fa-question"></i></div>
|
||||
<div id="help-button" style="color: var(--accent); font-weight: bold; opacity: 0.7;" title="Keyboard Shortcuts" aria-label="Keyboard Shortcuts"><i class="fa-solid fa-keyboard"></i></div>
|
||||
@if(!/^\/\d$/.test(url.pathname))
|
||||
{{-- id kept: f0ckm.js / sidebar-activity.js hook the AJAX random transition on #nav-random --}}
|
||||
<a href="/random" id="nav-random" title="{{ t('nav.random') }}" aria-label="{{ t('nav.random') }}"><i class="fa-solid fa-shuffle"></i></a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@@ -653,7 +660,8 @@
|
||||
});
|
||||
const json = await resp.json();
|
||||
if (status) { status.textContent = json.msg || ''; status.className = json.success ? 'flash-success' : 'flash-error'; }
|
||||
if (json.success) setTimeout(() => { close(registerModal); open(loginModal); }, 2000);
|
||||
if (json.success && json.upgraded) setTimeout(() => { location.reload(); }, 1500);
|
||||
else if (json.success) setTimeout(() => { close(registerModal); open(loginModal); }, 2000);
|
||||
} catch (err) {
|
||||
if (status) { status.textContent = 'Network error.'; status.className = 'flash-error'; }
|
||||
} finally { btn.disabled = false; btn.textContent = 'Create Account'; }
|
||||
|
||||
@@ -347,7 +347,12 @@
|
||||
#info-modal .infobox-modal-content .infobox-modal-footer { flex-shrink: 0; }
|
||||
#info-modal .infobox-modal-content .infobox-modal-body {
|
||||
flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto; overscroll-behavior: contain;
|
||||
/* Scrolls (wheel, touch, keyboard) but shows no scrollbar in any browser.
|
||||
NOTE: no backticks or dollar-brace in views, the template engine compiles them as JS template literals */
|
||||
scrollbar-width: none !important;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
#info-modal .infobox-modal-content .infobox-modal-body::-webkit-scrollbar { display: none; width: 0; height: 0; }
|
||||
@media (max-width: 600px) {
|
||||
#info-modal { padding: 0 !important; align-items: stretch !important; }
|
||||
#info-modal .infobox-modal-content {
|
||||
|
||||
+39
-37
@@ -35,9 +35,6 @@
|
||||
<a href="/abyss" title="{{ t('nav.abyss') }}"><i class="fa-solid fa-dice-d6"></i></a>
|
||||
@endif
|
||||
<a href="#" id="nav-search-btn" title="{{ t('nav.search') }}"><i class="fa-solid fa-magnifying-glass"></i></a>
|
||||
@if(!/^\/\d$/.test(url.pathname))
|
||||
<a href="/random" id="nav-random" title="{{ t('nav.random') }}"><i class="fa-solid fa-shuffle"></i></a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -48,7 +45,7 @@
|
||||
<div class="nav-user-dropdown">
|
||||
<button class="nav-user-btn nav-avatar-btn" id="nav-user-toggle">
|
||||
@if(session.is_anon)
|
||||
<span class="nav-avatar-icon" style="font-size: 1.2em; margin-right: 6px; display: inline-flex; align-items: center; cursor: pointer;" onclick="event.stopPropagation(); const u = '{{ session.login.toLowerCase() }}'; if(typeof window.loadPageAjax==='function'){ window.loadPageAjax('/user/' + u, true); } else { window.location.href='/user/' + u; }" title="{{ session.login }}"><i class="fa-solid fa-user-secret"></i></span>
|
||||
<img class="nav-avatar-img" src="/a/default.png" onclick="event.stopPropagation(); const u = '{{ session.login.toLowerCase() }}'; if(typeof window.loadPageAjax==='function'){ window.loadPageAjax('/user/' + u, true); } else { window.location.href='/user/' + u; }" title="{{ session.login }}">
|
||||
@elseif(session.avatar_file)
|
||||
<img class="nav-avatar-img" src="/a/{{ session.avatar_file }}" onerror="this.src='/a/default.png'" onclick="event.stopPropagation(); if(typeof window.loadPageAjax==='function'){ window.loadPageAjax('/user/{!! session.user.toLowerCase() !!}', true); } else { window.location.href='/user/{!! session.user.toLowerCase() !!}'; }" title="{{ session.user }}">
|
||||
@elseif(session.avatar && session.avatar > 0)
|
||||
@@ -68,12 +65,12 @@
|
||||
<a href="/user/{!! session.user.toLowerCase() !!}/halls">{{ t('nav.my_halls') }}</a>
|
||||
@endif
|
||||
@endif
|
||||
<a href="/pending">Pending Uploads</a>
|
||||
<a href="/pending" class="nav-menu-pending">Pending@if(typeof session.own_pending_count === 'number')<span class="nav-menu-count @if(session.own_pending_count === 0)is-zero@endif" title="{{ session.own_pending_count }} upload(s) awaiting approval">{{ session.own_pending_count }}</span>@endif</a>
|
||||
@if(enable_anonymous_access && session.is_anon)
|
||||
<a href="#" id="nav-user-anon-identity-btn" style="white-space: nowrap;" onclick="event.preventDefault(); if(window.f0ckAnonPasskey) { window.f0ckAnonPasskey.openModal(); } else { const m = document.getElementById('anon-passkey-modal'); if (m) m.style.display='flex'; }">Passkey Identity</a>
|
||||
@endif
|
||||
<a href="/user/{{ (session.is_anon && session.login ? session.login : session.user).toLowerCase() }}/favs" class="mobile-only">{{ t('nav.favs') }}</a>
|
||||
<a href="/settings" class="mobile-only">{{ t('nav.settings') }}</a>
|
||||
<a href="/settings" class="mobile-only" data-page-modal title="{{ t('nav.settings') }}">{{ t('nav.settings') }}</a>
|
||||
<div class="nav-user-divider"></div>
|
||||
<a href="/logout" class="mobile-only">{{ t('nav.logout') }}</a>
|
||||
</div>
|
||||
@@ -94,6 +91,9 @@
|
||||
@else
|
||||
<button class="notif-tab active" data-tab="system">{{ t('nav.notif_tab_system') }} <span class="notif-tab-badge" id="notif-tab-badge-system" style="display:none">0</span></button>
|
||||
@endif
|
||||
@if(session && session.admin)
|
||||
<button class="notif-tab" data-tab="admin">Admin <span class="notif-tab-badge" id="notif-tab-badge-admin" style="display:none">0</span></button>
|
||||
@endif
|
||||
</div>
|
||||
<button id="mark-all-read" title="{{ t('nav.mark_all_read') }}"><i class="fa-solid fa-check-double"></i></button>
|
||||
</div>
|
||||
@@ -129,7 +129,7 @@
|
||||
@endif
|
||||
|
||||
<!-- Quick Settings -->
|
||||
<a href="/settings" title="Settings" class="desktop-only"><i class="fa-solid fa-gear"></i></a>
|
||||
<a href="/settings" title="Settings" class="desktop-only" data-page-modal><i class="fa-solid fa-gear"></i></a>
|
||||
|
||||
<!-- Filter -->
|
||||
@if(!session.is_anon || (enable_anonymous_access && anon_permissions.filter))
|
||||
@@ -171,9 +171,9 @@
|
||||
|
||||
</nav>
|
||||
|
||||
@if(session.admin || session._is_impersonating)
|
||||
@if(session.admin || session._is_impersonating || session._preview_role)
|
||||
<!-- Admin Bar (Bottom, hotkey-activated) -->
|
||||
<div class="admin-bar" id="admin-bar">
|
||||
<div class="admin-bar" id="admin-bar" data-preview-role="{{ session._preview_role || 'admin' }}">
|
||||
@if(session._is_impersonating)
|
||||
<!-- Impersonation Banner -->
|
||||
<div class="admin-bar-impersonate-notice">
|
||||
@@ -190,10 +190,6 @@
|
||||
@else
|
||||
<!-- Normal Admin Bar -->
|
||||
<div class="admin-bar-inner">
|
||||
<div class="admin-bar-brand">
|
||||
<i class="fa-solid fa-shield-halved"></i>
|
||||
<span>Admin</span>
|
||||
</div>
|
||||
|
||||
<div class="admin-bar-links">
|
||||
<a href="/admin" class="admin-bar-link" title="Admin panel">
|
||||
@@ -235,7 +231,7 @@
|
||||
@endif
|
||||
|
||||
<!-- Floating exit-preview pill (visible only during role preview) -->
|
||||
@if(session.admin)
|
||||
@if(session.admin || session._preview_role)
|
||||
<div id="admin-preview-exit-pill" style="display:none;">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
<span id="admin-preview-exit-label">Previewing as User</span>
|
||||
@@ -279,9 +275,6 @@
|
||||
@if(abyss_enabled)
|
||||
<a href="/abyss" title="Abyss"><i class="fa-solid fa-dice-d6"></i></a>
|
||||
@endif
|
||||
@if(!/^\/\d$/.test(url.pathname))
|
||||
<a href="/random" id="nav-random" title="Random"><i class="fa-solid fa-shuffle"></i></a>
|
||||
@endif
|
||||
<a href="#" id="nav-search-btn" title="Search"><i class="fa-solid fa-magnifying-glass"></i></a>
|
||||
|
||||
</div>
|
||||
@@ -301,7 +294,7 @@
|
||||
@if(enable_anonymous_access)
|
||||
|
||||
<a href="#" id="nav-anon-identity-btn" @if(!session || !session.is_anon) style="display:none;" @endif onclick="event.preventDefault(); if(window.f0ckAnonPasskey) { window.f0ckAnonPasskey.openModal(); } else { const m = document.getElementById('anon-passkey-modal'); if (m) m.style.display='flex'; }"><i class="fa-solid fa-fingerprint"></i> Passkey Identity</a>
|
||||
<a href="/settings" id="nav-anon-settings-btn" @if(!session || !session.is_anon) style="display:none;" @endif><i class="fa-solid fa-gear"></i> Settings</a>
|
||||
<a href="/settings" id="nav-anon-settings-btn" data-page-modal title="Settings" @if(!session || !session.is_anon) style="display:none;" @endif><i class="fa-solid fa-gear"></i> Settings</a>
|
||||
@endif
|
||||
<a href="#" id="nav-login-btn">{{ t('nav.login') }}</a>
|
||||
@if(registration_open)
|
||||
@@ -1082,6 +1075,9 @@ async function loginWithPasskey() {
|
||||
<div class="shortcut-item"><span><kbd>Ctrl</kbd> + <kbd>Enter</kbd></span><span>{{ t('shortcuts.send_comment') }}</span></div>
|
||||
<div class="shortcut-item"><span><kbd>s</kbd></span><span>{{ t('shortcuts.flash_yank') }}</span></div>
|
||||
@if(session)
|
||||
<div class="shortcut-item"><span><kbd>Shift</kbd> + <kbd>S</kbd></span><span>{{ t('shortcuts.open_settings') }}</span></div>
|
||||
@endif
|
||||
@if(session)
|
||||
<div class="shortcut-item"><span><kbd>e</kbd></span><span>{{ t('shortcuts.tag_exclude') }}</span></div>
|
||||
<div class="shortcut-item"><span><kbd>i</kbd></span><span>{{ t('shortcuts.tag_input') }}</span></div>
|
||||
@endif
|
||||
@@ -1241,8 +1237,8 @@ async function loginWithPasskey() {
|
||||
<button class="modal-close" id="drag-modal-close" title="Cancel Upload">×</button>
|
||||
<div class="modal-body">
|
||||
<div class="upload-container" style="padding: 0; animation: none; opacity: 1;">
|
||||
<div class="upload-title">{{ t('upload.title') }}</div>
|
||||
|
||||
<div class="upload-title">
|
||||
<span class="upload-title-text">{{ t('upload.title') }}</span>
|
||||
<div class="upload-limit-info">
|
||||
@if(session.uploads_remaining === undefined)
|
||||
<span class="limit-unlimited"><i class="fa-solid fa-infinity"></i> {{ t('upload.unlimited') }}</span>
|
||||
@@ -1252,6 +1248,7 @@ async function loginWithPasskey() {
|
||||
<span class="limit-remaining"><i class="fa-solid fa-upload"></i> {{ session.uploads_remaining }}/{{ upload_limit }} {{ t('upload.remaining') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include(snippets/upload-form)
|
||||
</div>
|
||||
@@ -1261,7 +1258,7 @@ async function loginWithPasskey() {
|
||||
|
||||
@endif
|
||||
|
||||
@if(recaptcha_enabled && !session)
|
||||
@if(recaptcha_enabled && (!session || session.is_anon))
|
||||
<script>
|
||||
(function() {
|
||||
var _rcModalWidgetId = null;
|
||||
@@ -1300,7 +1297,7 @@ async function loginWithPasskey() {
|
||||
<script src="https://www.google.com/recaptcha/api.js?onload=onRecaptchaModalReady&render=explicit" async defer></script>
|
||||
@endif
|
||||
|
||||
@if(session && (session.admin || session._is_impersonating))
|
||||
@if(session && (session.admin || session._is_impersonating || session._preview_role))
|
||||
<style>
|
||||
/* ── Admin Bar ──────────────────────────────────────────────────────────────── */
|
||||
.admin-bar {
|
||||
@@ -1730,7 +1727,8 @@ body.preview-as-user .admin-delete-btn,
|
||||
body.preview-as-user .admin-edit-btn,
|
||||
body.preview-as-user .admin-pin-btn,
|
||||
body.preview-as-user .delete-btn,
|
||||
body.preview-as-user .poll-delete-btn,
|
||||
body.preview-as-user .poll-delete-btn { display: none !important; }
|
||||
/* Title stays visible but loses its click-to-edit */
|
||||
body.preview-as-user .item_title_text { display: inline !important; cursor: default !important; pointer-events: none !important; }
|
||||
body.preview-as-user .item_title_text.no-title { display: none !important; }
|
||||
|
||||
@@ -2012,8 +2010,10 @@ body.preview-as-mod .btn-infobox-action { display: none !important; }
|
||||
}
|
||||
|
||||
/* ── Admin bar: Preview As role toggle ──────────────────────────────────── */
|
||||
// The role is applied server-side (cookie preview_role, see src/index.mjs): templates, f0ckSession and
|
||||
// admin/mod-guarded routes all behave as that role. Switching sets the cookie and reloads.
|
||||
(function() {
|
||||
const STORAGE_KEY = 'f0ck_preview_role';
|
||||
const COOKIE = 'preview_role';
|
||||
const pills = document.querySelectorAll('.admin-bar-preview-pill');
|
||||
const exitPill = document.getElementById('admin-preview-exit-pill');
|
||||
const exitLabel = document.getElementById('admin-preview-exit-label');
|
||||
@@ -2040,26 +2040,28 @@ body.preview-as-mod .btn-infobox-action { display: none !important; }
|
||||
}
|
||||
}
|
||||
|
||||
// Init from localStorage
|
||||
const saved = localStorage.getItem(STORAGE_KEY) || 'admin';
|
||||
applyRole(saved);
|
||||
function switchRole(role) {
|
||||
const secure = location.protocol === 'https:' ? '; Secure' : '';
|
||||
// No template literals here: the view engine would evaluate the placeholders server-side
|
||||
document.cookie = role === 'admin'
|
||||
? COOKIE + '=; path=/; max-age=0; SameSite=Lax' + secure
|
||||
: COOKIE + '=' + role + '; path=/; max-age=86400; SameSite=Lax' + secure;
|
||||
location.reload();
|
||||
}
|
||||
|
||||
// The server tells which role this page was rendered as
|
||||
try { localStorage.removeItem('f0ck_preview_role'); } catch {} // old client-only preview
|
||||
const current = (adminBar && adminBar.dataset.previewRole) || 'admin';
|
||||
applyRole(roleLabels[current] ? current : 'admin');
|
||||
|
||||
// Pill click
|
||||
pills.forEach(pill => {
|
||||
pill.addEventListener('click', () => {
|
||||
const role = pill.dataset.role;
|
||||
localStorage.setItem(STORAGE_KEY, role);
|
||||
applyRole(role);
|
||||
if (role !== current) switchRole(role);
|
||||
});
|
||||
});
|
||||
|
||||
// Exit button
|
||||
if (exitBtn) {
|
||||
exitBtn.addEventListener('click', () => {
|
||||
localStorage.setItem(STORAGE_KEY, 'admin');
|
||||
applyRole('admin');
|
||||
});
|
||||
}
|
||||
if (exitBtn) exitBtn.addEventListener('click', () => switchRole('admin'));
|
||||
})();
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@each(notifications as n)
|
||||
@if(n.type === 'approve')
|
||||
<a href="/{{ n.item_slug || n.item_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="/{{ n.item_slug || n.item_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumb" onerror="this.onerror=null;this.src='/pending/t/{{ n.item_id }}.webp';this.onerror=function(){this.onerror=null;this.src='/mod/deleted/t/{{ n.item_id }}.webp';this.onerror=function(){this.style.display='none';};};"/>
|
||||
</div>
|
||||
@@ -11,7 +11,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@elseif(n.type === 'admin_pending')
|
||||
<a href="/mod/approve" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="/mod/approve" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumb" onerror="this.onerror=null;this.src='/t/{{ n.item_id }}.webp';this.onerror=function(){this.style.display='none';};"/>
|
||||
</div>
|
||||
@@ -22,7 +22,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@elseif(n.type === 'report')
|
||||
<a href="/mod/reports" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="/mod/reports" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumb" onerror="this.onerror=null;this.src='/pending/t/{{ n.item_id }}.webp';this.onerror=function(){this.onerror=null;this.src='/mod/deleted/t/{{ n.item_id }}.webp';this.onerror=function(){this.style.display='none';};};"/>
|
||||
</div>
|
||||
@@ -33,7 +33,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@elseif(n.type === 'deny')
|
||||
<a href="/{{ n.item_slug || n.item_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="/{{ n.item_slug || n.item_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumb" onerror="this.onerror=null;this.src='/t/{{ n.item_id }}.webp';this.onerror=function(){this.style.display='none'};" />
|
||||
</div>
|
||||
@@ -47,7 +47,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@elseif(n.type === 'item_deleted')
|
||||
<a href="/{{ n.item_slug || n.item_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="/{{ n.item_slug || n.item_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumb" onerror="this.onerror=null;this.src='/t/{{ n.item_id }}.webp';this.onerror=function(){this.style.display='none'};" />
|
||||
</div>
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@elseif(n.type === 'upload_comment')
|
||||
<a href="/{{ n.item_slug || n.item_id }}#c{{ n.reference_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="/{{ n.item_slug || n.item_id }}#c{{ n.reference_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumbnail" onerror="this.style.display='none'">
|
||||
</div>
|
||||
@@ -72,7 +72,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@elseif(n.type === 'upload_success')
|
||||
<a href="/{{ n.item_slug || n.item_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="/{{ n.item_slug || n.item_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumb" onerror="this.style.display='none'" />
|
||||
</div>
|
||||
@@ -83,7 +83,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@elseif(n.type === 'upload_error')
|
||||
<a href="{{ n.item_id ? '/' + (n.item_slug || n.item_id) : '#' }}" class="notif-item {{ n.is_read ? '' : 'unread' }} {{ n.item_id ? 'notif-with-thumb' : '' }}" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="{{ n.item_id ? '/' + (n.item_slug || n.item_id) : '#' }}" class="notif-item {{ n.is_read ? '' : 'unread' }} {{ n.item_id ? 'notif-with-thumb' : '' }}" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
@if(n.item_id)
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumb" onerror="this.onerror=null;this.src='/pending/t/{{ n.item_id }}.webp';this.onerror=function(){this.style.display='none'};" />
|
||||
@@ -104,7 +104,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@elseif(n.type === 'warning')
|
||||
<div class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<div class="notif-thumb" style="display:flex;align-items:center;justify-content:center;background:var(--bg-lighter);color:var(--danger);font-size:1.5em;"><i class="fa-solid fa-triangle-exclamation"></i></div>
|
||||
<div class="notif-content">
|
||||
<div class="notif-user"><strong>{{ t('notifications.system') }}</strong></div>
|
||||
@@ -116,7 +116,7 @@
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<a href="/{{ n.item_slug || n.item_id }}#c{{ n.comment_id || n.reference_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
<a href="/{{ n.item_slug || n.item_id }}#c{{ n.comment_id || n.reference_id }}" class="notif-item {{ n.is_read ? '' : 'unread' }} notif-with-thumb" data-id="{{ n.id }}" data-type="{{ n.type }}" data-item-id="{{ n.item_id || '' }}" data-item-slug="{{ n.item_slug || '' }}">
|
||||
@if(n.item_id)
|
||||
<div class="notif-thumb" data-mode="{{ n.item_mode || '' }}">
|
||||
<img src="/t/{{ n.item_id }}{{ ((active_mode===0&&(n.item_mode==='nsfw'||n.item_mode==='nsfl'))||(active_mode===1&&n.item_mode==='nsfl')||(active_mode===4&&(n.item_mode==='sfw'||n.item_mode==='nsfw'))) ? '_blur' : '' }}.webp" data-orig-src="/t/{{ n.item_id }}.webp" alt="thumb" onerror="this.style.display='none'" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<button type="button" class="pgm-close" title="Close" aria-label="Close">×</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pgm-body"></div>
|
||||
<div class="pgm-body" tabindex="-1"></div>
|
||||
</div>
|
||||
<style>
|
||||
#page-modal {
|
||||
@@ -17,10 +17,21 @@
|
||||
flex-direction: column;
|
||||
background: var(--bg); color: var(--text-color, #fff);
|
||||
}
|
||||
/* The Onara viewer (10050) lifts the sidebar (10060) and its drag zone (10059) above itself; keep the same
|
||||
order: page over Onara, still under the sidebar controls and the navbar (10070) */
|
||||
body.onara-modal-open #page-modal { z-index: 10055; }
|
||||
#page-modal .pgm-header {
|
||||
flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
||||
padding: 12px 20px; border-bottom: 1px solid var(--accent);
|
||||
}
|
||||
/* Height matched to the sidebar tab row (page-modal.js measures it); the close button scales with it */
|
||||
#page-modal.pgm-header-synced .pgm-header {
|
||||
box-sizing: border-box; height: var(--pgm-header-h); padding-top: 0; padding-bottom: 0;
|
||||
}
|
||||
#page-modal.pgm-header-synced .pgm-close {
|
||||
width: calc(var(--pgm-header-h) - 12px); height: calc(var(--pgm-header-h) - 12px);
|
||||
font-size: 1.3em;
|
||||
}
|
||||
#page-modal .pgm-title {
|
||||
margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
font-size: 1em; font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em;
|
||||
@@ -37,7 +48,14 @@
|
||||
#page-modal .pgm-body {
|
||||
flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
|
||||
padding-bottom: env(safe-area-inset-bottom, 0px);
|
||||
/* Scrollbar hidden, scrolling kept (wheel, touch, keyboard). Firefox only honours scrollbar-width;
|
||||
!important so a site-wide scrollbar style can't bring it back */
|
||||
scrollbar-width: none !important;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
#page-modal .pgm-body::-webkit-scrollbar { display: none; width: 0; height: 0; }
|
||||
/* Focusable so arrow keys / PageUp / PageDown / Space scroll it once clicked into, without an outline */
|
||||
#page-modal .pgm-body:focus { outline: none; }
|
||||
#page-modal .pgm-loading { padding: 60px 20px; text-align: center; color: var(--text-muted, #aaa); }
|
||||
#page-modal .pgm-loading a { color: var(--accent); }
|
||||
</style>
|
||||
|
||||
@@ -22,11 +22,7 @@
|
||||
<div class="drop-zone" id="upload-form-drop-zone">
|
||||
<input type="file" class="file-input" name="file" accept="{{ allowed_mimes }}" multiple>
|
||||
<div class="drop-zone-prompt">
|
||||
<p class="drop-zone-title" style="font-size: 1.1rem; font-weight: 500;">{{ t('upload.drop_here') }}</p>
|
||||
<p style="font-size: 0.9rem; opacity: 0.6;">(max {{ max_file_size }})@if(session.admin) <span style="color: var(--accent);">{{ t('upload.admin_boost') }}</span>@endif</p>
|
||||
<p class="drop-album-hint" style="margin-top: 6px; font-size: 0.85rem; color: var(--accent); opacity: 0.95;">
|
||||
<i class="fa-solid fa-layer-group"></i> {{ t('album.drop_hint') || 'Select or drop multiple files (subf0cks) to create an Album' }}
|
||||
</p>
|
||||
<p class="drop-zone-title" style="font-size: 1.1rem; font-weight: 500;">{{ t('upload.drop_here') }} <span class="drop-zone-max" style="font-size: 0.8em; font-weight: 400; opacity: 0.6;">(max {{ max_file_size }})</span>@if(session.admin) <span style="font-size: 0.8em; font-weight: 400; color: var(--accent);">{{ t('upload.admin_boost') }}</span>@endif</p>
|
||||
</div>
|
||||
<!-- Preview Container -->
|
||||
<div class="file-preview" style="display: none;">
|
||||
@@ -180,6 +176,9 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Footer: upload button, progress and status. Pinned to the bottom of the upload dropdown
|
||||
while the form above it scrolls (f0ckm.css #upload-drag-modal .upload-footer) -->
|
||||
<div class="upload-footer">
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn-upload" disabled>
|
||||
<span class="btn-text">{{ t('upload.select_file') }}</span>
|
||||
@@ -195,4 +194,5 @@
|
||||
</div>
|
||||
|
||||
<div class="upload-status"></div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user