gfds
This commit is contained in:
+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'));
|
||||
})();
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user