Settings: hidden Admin entry (opens /admin in the app window); admin page keeps a back link on phones
This commit is contained in:
@@ -287,7 +287,7 @@
|
|||||||
}
|
}
|
||||||
.nav { display: none; }
|
.nav { display: none; }
|
||||||
@media (max-width: 760px) {
|
@media (max-width: 760px) {
|
||||||
.tabs, .top .ghost.desk { display: none; }
|
.tabs, .top .desk-only { display: none; }
|
||||||
.top { padding: 10px 14px; }
|
.top { padding: 10px 14px; }
|
||||||
.nav {
|
.nav {
|
||||||
position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
|
position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
|
||||||
@@ -343,7 +343,7 @@
|
|||||||
<a class="brand" href="/admin#editor" data-home style="text-decoration:none;color:inherit"><i><svg viewBox="0 0 24 24"><path d="M9 18V6l10-2v12"/><circle cx="6.5" cy="18" r="2.5"/><circle cx="16.5" cy="16" r="2.5"/></svg></i>Lyrics Studio</a>
|
<a class="brand" href="/admin#editor" data-home style="text-decoration:none;color:inherit"><i><svg viewBox="0 0 24 24"><path d="M9 18V6l10-2v12"/><circle cx="6.5" cy="18" r="2.5"/><circle cx="16.5" cy="16" r="2.5"/></svg></i>Lyrics Studio</a>
|
||||||
<nav class="tabs" role="tablist" id="tabsTop"></nav>
|
<nav class="tabs" role="tablist" id="tabsTop"></nav>
|
||||||
<span class="grow"></span>
|
<span class="grow"></span>
|
||||||
<a class="ghost desk" href="/">← Back to app</a>
|
<a class="ghost back-app" href="/">← <span class="desk-only">Back to </span>App</a>
|
||||||
<button id="logoutBtn" class="ghost">Sign out</button>
|
<button id="logoutBtn" class="ghost">Sign out</button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|||||||
@@ -1074,6 +1074,15 @@ async function renderSettings() {
|
|||||||
</span>
|
</span>
|
||||||
<span id="aboutBuildTime" class="about-version">…</span>
|
<span id="aboutBuildTime" class="about-version">…</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="set-row hidden" id="aboutAdminRow">
|
||||||
|
<span>
|
||||||
|
Admin
|
||||||
|
<small>Lyrics studio, reports, library and server tools. Needs the admin password.</small>
|
||||||
|
</span>
|
||||||
|
<div class="set-actions" style="margin:0">
|
||||||
|
<a class="btn" href="/admin" id="aboutAdminLink" style="text-decoration:none;display:inline-flex;align-items:center">Open admin</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
c.appendChild(wrap);
|
c.appendChild(wrap);
|
||||||
@@ -1456,6 +1465,34 @@ async function renderSettings() {
|
|||||||
});
|
});
|
||||||
updateProfileStatus();
|
updateProfileStatus();
|
||||||
|
|
||||||
|
// ---- About: Admin entry. Shown once this device has signed in as admin,
|
||||||
|
// or after a long-press / five taps on the version (then remembered). It
|
||||||
|
// opens /admin inside the app window, which has no address bar on iPhone.
|
||||||
|
if (WEB) {
|
||||||
|
const ADMIN_KEY = 'ytpAdminEntry';
|
||||||
|
const revealAdmin = (remember) => {
|
||||||
|
const row = $('aboutAdminRow');
|
||||||
|
if (row) row.classList.remove('hidden');
|
||||||
|
if (remember) { try { localStorage.setItem(ADMIN_KEY, '1'); } catch {} }
|
||||||
|
};
|
||||||
|
try { if (localStorage.getItem(ADMIN_KEY) === '1') revealAdmin(false); } catch {}
|
||||||
|
fetch('/api/admin/me', { cache: 'no-store', credentials: 'same-origin' })
|
||||||
|
.then((r) => (r.ok ? r.json() : null)).then((me) => { if (me && me.admin) revealAdmin(true); }).catch(() => {});
|
||||||
|
const ver = $('aboutVersion');
|
||||||
|
if (ver) {
|
||||||
|
let taps = 0, tapTimer = null, holdTimer = null;
|
||||||
|
const unlock = () => { if ($('aboutAdminRow')?.classList.contains('hidden')) { revealAdmin(true); toast('Admin entry shown in About'); } };
|
||||||
|
ver.addEventListener('pointerdown', () => { clearTimeout(holdTimer); holdTimer = setTimeout(unlock, 700); });
|
||||||
|
for (const n of ['pointerup', 'pointerleave', 'pointercancel']) ver.addEventListener(n, () => clearTimeout(holdTimer));
|
||||||
|
ver.addEventListener('click', () => {
|
||||||
|
taps++; clearTimeout(tapTimer); tapTimer = setTimeout(() => { taps = 0; }, 1500);
|
||||||
|
if (taps >= 5) { taps = 0; unlock(); }
|
||||||
|
});
|
||||||
|
ver.addEventListener('contextmenu', (e) => e.preventDefault());
|
||||||
|
ver.style.webkitUserSelect = 'none'; ver.style.userSelect = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---- About: append server build tag + build time (WEB mode only) ----
|
// ---- About: append server build tag + build time (WEB mode only) ----
|
||||||
if (WEB) {
|
if (WEB) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user