Fix sub-app permissions bug, add Comments app, support Site Editor
- Root-cause fix for "Sorry, you are not allowed to access this page" on Menu Creator/Activity Log/Role Editor: remove_submenu_page() was corrupting WP core's user_can_access_admin_page() capability lookup. Sub-apps now stay registered in $submenu; MenuSerializer filters them out of the sidebar instead. - Add a 6th sub-app, Comments, with a redirect from native edit-comments.php. - Extend the window-chrome/taskbar framing to the Site Editor (site-editor.php), including a fix for a CSS position:fixed over-constraint bug that let its frame run past the viewport. - Rewrite the taskbar from a single sessionStorage slot to a list so multiple minimized windows are each independently restorable. - Extend native-dark.css coverage to the block editor's own chrome. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b0b0a9999a
commit
8153d4397c
+37
-41
@@ -4,7 +4,7 @@ import Sidebar from './components/Sidebar.vue';
|
||||
import Toolbar from './components/Toolbar.vue';
|
||||
import { applyThemePalette, applyFontFamily } from '@/pages/settings/applyLiveTheme.js';
|
||||
import { initWindowChrome } from './windowChrome.js';
|
||||
import { getMinimizedWindow, clearMinimizedWindow } from './taskbar.js';
|
||||
import { getMinimizedWindows, removeMinimizedWindow } from './taskbar.js';
|
||||
|
||||
const props = defineProps({
|
||||
serverData: {
|
||||
@@ -25,47 +25,31 @@ const toggleMenu = () => {
|
||||
localStorage.setItem('aurora-menu-collapsed', collapsed.value ? '1' : '0');
|
||||
};
|
||||
|
||||
// The block editor (Gutenberg) renders its own toolbar (undo/redo,
|
||||
// title, save/publish) directly under Aurora's fixed toolbar — stacking
|
||||
// both left a sliver of page gradient visible as a seam between them.
|
||||
// Skip Aurora's toolbar there and let the editor's own bar sit flush
|
||||
// against the top; shell-frame.css reads the aurora-no-toolbar class to
|
||||
// also close up the top inset it reserves for the (now-absent) toolbar.
|
||||
const isBlockEditor = document.body.classList.contains('block-editor-page');
|
||||
|
||||
// The one minimized window, if any (taskbar.js persists it in
|
||||
// sessionStorage across the page load minimizing triggers). Rendered as a
|
||||
// taskbar item at the bottom of every page since SiteShell mounts on all
|
||||
// of them — clicking it navigates back and clears the entry.
|
||||
const minimizedWindow = ref(null);
|
||||
const restoreWindow = () => {
|
||||
if (!minimizedWindow.value) return;
|
||||
const url = minimizedWindow.value.url;
|
||||
clearMinimizedWindow();
|
||||
window.location.href = url;
|
||||
// Every minimized window (taskbar.js persists the list in sessionStorage
|
||||
// across the page loads minimizing triggers). Rendered as taskbar items at
|
||||
// the bottom of every page since SiteShell mounts on all of them — clicking
|
||||
// one navigates back to it and removes just that entry.
|
||||
const minimizedWindows = ref([]);
|
||||
const restoreWindow = (win) => {
|
||||
removeMinimizedWindow(win.id);
|
||||
window.location.href = win.url;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
minimizedWindow.value = getMinimizedWindow();
|
||||
minimizedWindows.value = getMinimizedWindows();
|
||||
// Reserve bottom space for the taskbar (shell-frame.css) so page content
|
||||
// stops above it instead of running underneath.
|
||||
document.documentElement.classList.toggle('aurora-has-taskbar', !!minimizedWindow.value);
|
||||
document.documentElement.classList.toggle('aurora-has-taskbar', minimizedWindows.value.length > 0);
|
||||
const settings = props.serverData?.settings || {};
|
||||
// Every theme preset is its own self-contained dark-toned palette now —
|
||||
// no separate light/dark mode, so this class is always on. It's kept
|
||||
// (rather than renamed) because shell-frame.css and native-dark.css both
|
||||
// still gate their rules on it.
|
||||
document.documentElement.classList.add('aurora-dark');
|
||||
document.documentElement.classList.toggle('aurora-no-toolbar', isBlockEditor);
|
||||
applyThemePalette(settings.theme_preset || 'indigo');
|
||||
applyCollapsed();
|
||||
applyFontFamily(settings.font_family);
|
||||
// Skipped on the block editor — #wpbody-content is bypassed by the
|
||||
// editor's own fixed skeleton there (see isBlockEditor above), so a
|
||||
// bar injected into it would just be invisible clutter.
|
||||
if (!isBlockEditor) {
|
||||
initWindowChrome(props.serverData?.adminUrl);
|
||||
}
|
||||
initWindowChrome(props.serverData?.adminUrl);
|
||||
// Signal the shell is live: reveals the framed content and commits to
|
||||
// keeping native chrome hidden (the PHP failsafe stops watching once
|
||||
// aurora-ready is present).
|
||||
@@ -85,14 +69,19 @@ onMounted(() => {
|
||||
:server-data="serverData"
|
||||
/>
|
||||
<Toolbar
|
||||
v-if="!isBlockEditor"
|
||||
:server-data="serverData"
|
||||
@toggle-menu="toggleMenu"
|
||||
/>
|
||||
<div v-if="minimizedWindow" class="aurora-taskbar">
|
||||
<button type="button" class="aurora-taskbar__item" @click="restoreWindow">
|
||||
<div v-if="minimizedWindows.length" class="aurora-taskbar">
|
||||
<button
|
||||
v-for="win in minimizedWindows"
|
||||
:key="win.id"
|
||||
type="button"
|
||||
class="aurora-taskbar__item"
|
||||
@click="restoreWindow(win)"
|
||||
>
|
||||
<span class="aurora-taskbar__dot" />
|
||||
{{ minimizedWindow.title }}
|
||||
{{ win.title }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -106,30 +95,37 @@ onMounted(() => {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
/* Full-width docked bar (real taskbar, edge to edge) — page content
|
||||
reserves space above it via html.aurora-has-taskbar in shell-frame.css
|
||||
so nothing renders underneath. The item itself stays pill-shaped. */
|
||||
/* Full-width docked bar, but inset with the same gap the sidebar floats
|
||||
with (not flush against the browser edges or the window above it) and
|
||||
fully rounded + shadowed so it reads as its own separate surface rather
|
||||
than an extension of the content frame it sits under. Page content
|
||||
reserves space above it via html.aurora-has-taskbar in shell-frame.css. */
|
||||
.aurora-taskbar {
|
||||
position: fixed;
|
||||
left: calc(var(--aurora-sidebar-w) + var(--aurora-sidebar-gap) * 2);
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
right: var(--aurora-sidebar-gap);
|
||||
bottom: var(--aurora-sidebar-gap);
|
||||
height: var(--aurora-taskbar-h);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 0 16px;
|
||||
background: var(--aurora-frame-bg);
|
||||
border-top: 1px solid var(--aurora-frame-border);
|
||||
background: var(--aurora-card-bg);
|
||||
border: 1px solid var(--aurora-card-border);
|
||||
border-radius: var(--aurora-radius-lg);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
|
||||
box-sizing: border-box;
|
||||
z-index: 200001;
|
||||
overflow-x: auto;
|
||||
transition: left 0.2s ease;
|
||||
}
|
||||
.aurora-taskbar__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: var(--aurora-card-bg);
|
||||
border: 1px solid var(--aurora-card-border);
|
||||
flex-shrink: 0;
|
||||
background: var(--aurora-bg-subtle);
|
||||
border: 1px solid var(--aurora-border);
|
||||
border-radius: 999px;
|
||||
padding: 8px 18px 8px 10px;
|
||||
color: var(--aurora-text);
|
||||
|
||||
+158
-23
@@ -17,6 +17,10 @@
|
||||
/* SiteShell.vue's taskbar, shown only while a window is minimized
|
||||
(html.aurora-has-taskbar toggles the bottom space reserved for it). */
|
||||
--aurora-taskbar-h: 56px;
|
||||
/* Height of the strip reserved at the top of the block editor's frame
|
||||
for .aurora-winbar--editor's traffic-light dots (a sibling element,
|
||||
not a child of the skeleton — see windowChrome.js). */
|
||||
--aurora-editor-winbar-h: 44px;
|
||||
/* Space between the sidebar card and the browser's left/top/bottom
|
||||
edges (Sidebar.vue) — the toolbar and #wpcontent offsets below add
|
||||
the same amount so nothing overlaps the floating sidebar. */
|
||||
@@ -83,7 +87,14 @@ html.aurora-dark {
|
||||
|
||||
html.aurora-ready,
|
||||
html.aurora-ready body {
|
||||
background: var(--aurora-app-bg);
|
||||
/* !important: WP core ships `body.js.block-editor-page { background:
|
||||
#fff }` on the block editor, which has higher specificity (two
|
||||
classes) than this selector (one) despite this having more type
|
||||
selectors — CSS specificity compares class count before type count.
|
||||
Without !important that rule wins and paints body solid white,
|
||||
hiding the gradient completely on that page (everywhere else this
|
||||
conflict doesn't exist, so it was never needed until now). */
|
||||
background: var(--aurora-app-bg) !important;
|
||||
/* Fixed so the gradient stays pinned to the viewport instead of
|
||||
scrolling with document height — the sidebar/toolbar are also
|
||||
position:fixed and paint no background of their own (see
|
||||
@@ -108,22 +119,72 @@ html.aurora-ready #wpcontent {
|
||||
}
|
||||
|
||||
/* The block editor (Gutenberg) doesn't live inside #wpcontent's normal
|
||||
box model — it renders its own skeleton as position:fixed, inset:0,
|
||||
completely independent of the margin-left above. Left unchecked it
|
||||
spans the full viewport and renders underneath the (higher z-index)
|
||||
sidebar and toolbar. Inset it the same amount #wpcontent gets. */
|
||||
html.aurora-ready .interface-interface-skeleton {
|
||||
left: calc(var(--aurora-sidebar-w) + var(--aurora-sidebar-gap) * 2) !important;
|
||||
top: var(--aurora-toolbar-h) !important;
|
||||
transition: left 0.2s ease;
|
||||
}
|
||||
box model — it renders its own fixed, full-viewport root, completely
|
||||
independent of the margin-left above. Left unchecked it spans the full
|
||||
viewport and renders underneath the (higher z-index) sidebar and
|
||||
toolbar. Framed the same way #wpbody-content is everywhere else — same
|
||||
insets, same card background/border/radius — just expressed as
|
||||
fixed-position offsets instead of margin, since this element can't
|
||||
participate in normal document flow.
|
||||
|
||||
/* Aurora's own toolbar is skipped on the block editor (SiteShell.vue) —
|
||||
its own toolbar sits flush against the top instead, so no toolbar
|
||||
height needs to be reserved here; just the same top gap the sidebar
|
||||
gets, so the two line up. */
|
||||
html.aurora-ready.aurora-no-toolbar .interface-interface-skeleton {
|
||||
top: var(--aurora-sidebar-gap) !important;
|
||||
Two different pages, two different fixed roots, both matched here:
|
||||
- post.php/post-new.php: .interface-interface-skeleton itself is
|
||||
position:fixed, inset:0.
|
||||
- site-editor.php: .interface-interface-skeleton is only
|
||||
position:relative, nested inside #site-editor, which is the actual
|
||||
position:fixed, inset:0 element there — the rule below with
|
||||
"#site-editor .interface-interface-skeleton" resets the nested one
|
||||
back to a plain unpositioned child so the two frames don't stack. */
|
||||
html.aurora-ready .interface-interface-skeleton,
|
||||
html.aurora-ready #site-editor {
|
||||
top: calc(var(--aurora-toolbar-h) + 16px) !important;
|
||||
left: calc(var(--aurora-sidebar-w) + var(--aurora-sidebar-gap) * 2 + 24px) !important;
|
||||
right: var(--aurora-gutter-r) !important;
|
||||
bottom: 24px !important;
|
||||
/* WP core's own .edit-site class (also present on #site-editor) sets
|
||||
height: 100vh. A position:fixed box with top, height, AND bottom all
|
||||
specified is over-constrained — per spec, 'bottom' is then silently
|
||||
recomputed from top+height instead of honoring the value here, which
|
||||
is exactly why the frame ran past the bottom of the viewport instead
|
||||
of stopping at the inset above. Forcing height back to auto lets
|
||||
top+bottom actually determine the box's size again. */
|
||||
height: auto !important;
|
||||
background: var(--aurora-frame-bg);
|
||||
/* No border — an asymmetric one (3 sides, one "none") combined with
|
||||
border-radius and this element's sub-pixel calc()-derived fixed
|
||||
position produced a visible double-edge rendering artifact right at
|
||||
the rounded corners. The background/gradient contrast alone is
|
||||
enough to read as a distinct surface without it. */
|
||||
border-radius: var(--aurora-radius-lg);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
transition: left 0.2s ease;
|
||||
/* Reserves a strip at the top for .aurora-winbar--editor's dots (a
|
||||
sibling, not a child — see windowChrome.js) so they sit in their own
|
||||
clear space instead of overlapping the editor's own logo/toolbar row.
|
||||
border-box so the padding comes out of the top/left/right/bottom
|
||||
inset box already defined above, rather than adding to it. */
|
||||
padding-top: var(--aurora-editor-winbar-h);
|
||||
box-sizing: border-box;
|
||||
/* border-radius alone doesn't clip children — Gutenberg's own white
|
||||
canvas background ran straight past the rounded bottom corners as a
|
||||
hard square edge without this. Floating UI (block toolbars, popovers)
|
||||
portals to document.body rather than nesting here, so this doesn't
|
||||
clip anything that needs to escape the frame. */
|
||||
overflow: hidden;
|
||||
}
|
||||
#site-editor .interface-interface-skeleton {
|
||||
position: relative !important;
|
||||
top: auto !important;
|
||||
left: auto !important;
|
||||
right: auto !important;
|
||||
bottom: auto !important;
|
||||
background: transparent !important;
|
||||
border-radius: 0 !important;
|
||||
box-shadow: none !important;
|
||||
padding-top: 0 !important;
|
||||
overflow: visible !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
html.aurora-ready #wpbody-content {
|
||||
@@ -144,14 +205,60 @@ html.aurora-ready #wpbody-content {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* SiteShell.vue's taskbar docks along the bottom edge only while a window
|
||||
is minimized — push content up by its height so pages stop above it
|
||||
instead of rendering underneath. */
|
||||
html.aurora-has-taskbar #wpbody-content {
|
||||
margin-bottom: calc(24px + var(--aurora-taskbar-h));
|
||||
/* Gutenberg renders in its own fixed skeleton. The regular #wpbody-content
|
||||
wrapper still exists on post-new.php/post.php, but it is inert; if framed
|
||||
like normal native pages, it appears as a stray empty pill above the editor. */
|
||||
html.aurora-ready body.block-editor-page #wpbody-content,
|
||||
html.aurora-ready body.post-new-php #wpbody-content,
|
||||
html.aurora-ready body.post-php #wpbody-content {
|
||||
background: transparent !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
box-shadow: none !important;
|
||||
margin: 0 !important;
|
||||
min-height: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
html.aurora-ready body.block-editor-page #wpbody-content > .aurora-winbar,
|
||||
html.aurora-ready body.post-new-php #wpbody-content > .aurora-winbar,
|
||||
html.aurora-ready body.post-php #wpbody-content > .aurora-winbar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* SiteShell.vue's taskbar floats along the bottom edge (inset by
|
||||
--aurora-sidebar-gap, same as the sidebar) only while a window is
|
||||
minimized. A plain margin-bottom only guarantees a gap once the page is
|
||||
scrolled all the way down — content taller than the viewport still
|
||||
renders underneath the fixed taskbar on first paint, since a fixed
|
||||
element doesn't reserve space from the rest of the page's flow. Instead,
|
||||
cap the content box's own height to whatever's actually left between the
|
||||
toolbar and the taskbar and let *it* scroll internally — the same way
|
||||
the toolbar's reserved space at the top never lets content start behind
|
||||
it, not just "eventually scroll clear of it". */
|
||||
html.aurora-has-taskbar #wpbody-content,
|
||||
html.aurora-has-taskbar .aurora-dashboard-frame {
|
||||
margin-bottom: calc(24px + var(--aurora-taskbar-h));
|
||||
/* #wpbody-content's base rule sets min-height: calc(100vh - toolbar-h -
|
||||
40px) for the normal (no-taskbar) case — per spec, when min-height is
|
||||
larger than max-height, min-height always wins and max-height is
|
||||
silently ignored. Without this override the box kept sizing to that
|
||||
taller min-height regardless of the taskbar, which is why the
|
||||
max-height below appeared to do nothing. */
|
||||
min-height: 0;
|
||||
max-height: calc(
|
||||
100vh - var(--aurora-toolbar-h) - 16px - 24px - var(--aurora-taskbar-h) -
|
||||
var(--aurora-sidebar-gap) * 2
|
||||
);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* The block editor's skeleton is already positioned with fixed insets
|
||||
(top/left/right/bottom) rather than margin, so reserving taskbar space
|
||||
is just moving its bottom inset in — no max-height/overflow trick
|
||||
needed there, unlike the margin-based elements above. */
|
||||
html.aurora-has-taskbar .interface-interface-skeleton,
|
||||
html.aurora-has-taskbar #site-editor {
|
||||
bottom: calc(24px + var(--aurora-taskbar-h) + var(--aurora-sidebar-gap) * 2) !important;
|
||||
}
|
||||
|
||||
/* macOS-style title bar (windowChrome.js). Most pages get it injected as
|
||||
@@ -162,6 +269,24 @@ html.aurora-has-taskbar .aurora-dashboard-frame {
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.aurora-winbar--editor {
|
||||
position: fixed;
|
||||
/* Centered vertically within the skeleton's reserved top strip
|
||||
(--aurora-editor-winbar-h), inset from its left edge to line up with
|
||||
the padding every other title bar uses. */
|
||||
top: calc(
|
||||
var(--aurora-toolbar-h) + 16px + (var(--aurora-editor-winbar-h) - 12px) / 2
|
||||
);
|
||||
left: calc(var(--aurora-sidebar-w) + var(--aurora-sidebar-gap) * 2 + 24px + 20px);
|
||||
height: 12px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
z-index: 100000;
|
||||
transition: left 0.2s ease;
|
||||
}
|
||||
#wpbody-content > .aurora-winbar {
|
||||
margin: -32px -32px 20px -32px;
|
||||
padding: 14px 16px;
|
||||
@@ -227,8 +352,18 @@ html.aurora-maximized .toolbar {
|
||||
html.aurora-ready.aurora-maximized #wpcontent {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
html.aurora-ready.aurora-maximized .interface-interface-skeleton {
|
||||
html.aurora-ready.aurora-maximized .interface-interface-skeleton,
|
||||
html.aurora-ready.aurora-maximized #site-editor {
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
bottom: 0 !important;
|
||||
height: auto !important;
|
||||
border-radius: 0;
|
||||
}
|
||||
html.aurora-maximized .aurora-winbar--editor {
|
||||
top: calc((var(--aurora-editor-winbar-h) - 12px) / 2);
|
||||
left: 20px;
|
||||
}
|
||||
html.aurora-maximized .aurora-taskbar {
|
||||
left: 0 !important;
|
||||
|
||||
+35
-17
@@ -1,39 +1,57 @@
|
||||
/**
|
||||
* Tracks the one "minimized" window across page loads. Aurora is a normal
|
||||
* Tracks every "minimized" window across page loads. Aurora is a normal
|
||||
* multi-page WP admin (each nav is a full page load), so a real taskbar
|
||||
* needs to survive navigation — sessionStorage (tab-scoped, clears when the
|
||||
* tab closes) is enough for that. Only one item is tracked at a time: this
|
||||
* is "minimize sends you home with a way back", not a full window manager.
|
||||
* tab closes) is enough for that. Stored as a list, not a single slot —
|
||||
* minimizing a second page used to silently overwrite the first one's
|
||||
* entry, so only the most recent minimize ever showed up in the taskbar.
|
||||
*/
|
||||
const STORAGE_KEY = 'aurora-minimized-window';
|
||||
const STORAGE_KEY = 'aurora-minimized-windows';
|
||||
|
||||
export function getMinimizedWindow() {
|
||||
export function getMinimizedWindows() {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(STORAGE_KEY);
|
||||
return raw ? JSON.parse(raw) : null;
|
||||
const parsed = raw ? JSON.parse(raw) : [];
|
||||
return Array.isArray(parsed) ? parsed : [];
|
||||
} catch {
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function setMinimizedWindow(title, url) {
|
||||
function saveMinimizedWindows(list) {
|
||||
try {
|
||||
sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ title, url }));
|
||||
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(list));
|
||||
} catch {
|
||||
/* sessionStorage unavailable (e.g. private mode) — minimize just won't persist */
|
||||
}
|
||||
}
|
||||
|
||||
export function clearMinimizedWindow() {
|
||||
try {
|
||||
sessionStorage.removeItem(STORAGE_KEY);
|
||||
} catch {
|
||||
/* noop */
|
||||
}
|
||||
/** Adds (or, if the same page is already minimized, replaces) an entry. */
|
||||
export function addMinimizedWindow(title, url) {
|
||||
const list = getMinimizedWindows().filter((w) => w.url !== url);
|
||||
list.push({ id: `${Date.now()}-${Math.random().toString(36).slice(2)}`, title, url });
|
||||
saveMinimizedWindows(list);
|
||||
}
|
||||
|
||||
/** Best-effort readable label for the current page, used as the taskbar item's title. */
|
||||
export function removeMinimizedWindow(id) {
|
||||
saveMinimizedWindows(getMinimizedWindows().filter((w) => w.id !== id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Best-effort readable label for the current page, used as the taskbar
|
||||
* item's title. Prefers the page's own on-screen <h1> over document.title —
|
||||
* WordPress's title-tag lookup walks the $submenu global to find a page's
|
||||
* title, which comes up empty for Aurora's sub-app pages (SubApps.php
|
||||
* registers each one normally, then immediately remove_submenu_page()s it
|
||||
* to keep it out of the native menu — that breaks WP's own title lookup,
|
||||
* not just this). document.title is still the fallback for pages where
|
||||
* that isn't an issue (Settings, native WP pages, the Dashboard).
|
||||
*/
|
||||
export function currentPageTitle() {
|
||||
const raw = document.title || 'Window';
|
||||
const heading = document.querySelector('#wpbody-content h1, #aurora-admin-dashboard-root h1');
|
||||
if (heading && heading.textContent.trim()) {
|
||||
return heading.textContent.trim();
|
||||
}
|
||||
const raw = document.title || '';
|
||||
return raw.split('‹')[0].trim() || 'Window';
|
||||
}
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
/**
|
||||
* Adds a macOS-style traffic-light title bar to the top of the page content.
|
||||
* Most pages render inside #wpbody-content (native WP pages and all of
|
||||
* Aurora's own Vue pages, since each mounts its root div there). The
|
||||
* Dashboard is the one exception — DashboardTakeover.php renders it into a
|
||||
* separate #aurora-admin-dashboard-root sibling, above #wpbody (which it
|
||||
* hides), to fully replace the native dashboard, so it gets wrapped in its
|
||||
* own frame to match the card treatment #wpbody-content already has. The
|
||||
* block editor bypasses both (see SiteShell.vue isBlockEditor), so it's
|
||||
* skipped there.
|
||||
* Three cases, in priority order:
|
||||
* 1. The Dashboard — DashboardTakeover.php renders it into a separate
|
||||
* #aurora-admin-dashboard-root sibling, above #wpbody (which it hides),
|
||||
* to fully replace the native dashboard. Gets wrapped in a new
|
||||
* .aurora-dashboard-frame div to match the card treatment
|
||||
* #wpbody-content already has everywhere else.
|
||||
* 2. The block editor — gets only the traffic-light controls, overlaid on
|
||||
* the editor frame without a full-width titlebar surface.
|
||||
* 3. Everything else — native WP pages and all of Aurora's own Vue pages,
|
||||
* since each mounts its root div inside #wpbody-content. The bar is
|
||||
* inserted as its first child.
|
||||
*
|
||||
* Red closes (navigates back to the Aurora dashboard). Yellow minimizes —
|
||||
* on any page other than the dashboard, that means "save where I am and
|
||||
* send me home", with SiteShell.vue's taskbar offering a way back; on the
|
||||
* dashboard itself (already home) it just collapses in place instead,
|
||||
* since there's nowhere further back to send it. Green hides Aurora's own
|
||||
* sidebar/toolbar so the content fills the browser window. All of this is
|
||||
* just classes on <html> plus one sessionStorage entry (taskbar.js) — no
|
||||
* server-side state.
|
||||
* sidebar/toolbar so the content fills the browser window. Minimized pages
|
||||
* are tracked as a list (taskbar.js), not a single slot, so minimizing
|
||||
* more than one shows up as separate taskbar items rather than the latest
|
||||
* silently replacing the previous one.
|
||||
*/
|
||||
import { setMinimizedWindow, currentPageTitle } from './taskbar.js';
|
||||
|
||||
export function initWindowChrome(adminUrl) {
|
||||
if (document.querySelector('.aurora-winbar')) {
|
||||
return;
|
||||
}
|
||||
import { addMinimizedWindow, currentPageTitle } from './taskbar.js';
|
||||
|
||||
function buildBar(adminUrl, isDashboard) {
|
||||
const bar = document.createElement('div');
|
||||
bar.className = 'aurora-winbar';
|
||||
|
||||
@@ -39,8 +39,6 @@ export function initWindowChrome(adminUrl) {
|
||||
};
|
||||
|
||||
const root = document.documentElement;
|
||||
const dashboardRoot = document.getElementById('aurora-admin-dashboard-root');
|
||||
const isDashboard = !!dashboardRoot;
|
||||
|
||||
bar.appendChild(
|
||||
makeDot('close', 'Close', () => {
|
||||
@@ -53,7 +51,7 @@ export function initWindowChrome(adminUrl) {
|
||||
root.classList.toggle('aurora-minimized');
|
||||
root.classList.remove('aurora-maximized');
|
||||
} else {
|
||||
setMinimizedWindow(currentPageTitle(), window.location.href);
|
||||
addMinimizedWindow(currentPageTitle(), window.location.href);
|
||||
window.location.href = adminUrl || '/wp-admin/';
|
||||
}
|
||||
})
|
||||
@@ -65,7 +63,26 @@ export function initWindowChrome(adminUrl) {
|
||||
})
|
||||
);
|
||||
|
||||
return bar;
|
||||
}
|
||||
|
||||
function isBlockEditorPage() {
|
||||
const path = window.location.pathname;
|
||||
return (
|
||||
document.body.classList.contains('block-editor-page') ||
|
||||
path.endsWith('/post-new.php') ||
|
||||
path.endsWith('/post.php')
|
||||
);
|
||||
}
|
||||
|
||||
export function initWindowChrome(adminUrl) {
|
||||
if (document.querySelector('.aurora-winbar')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dashboardRoot = document.getElementById('aurora-admin-dashboard-root');
|
||||
if (dashboardRoot) {
|
||||
const bar = buildBar(adminUrl, true);
|
||||
const frame = document.createElement('div');
|
||||
frame.className = 'aurora-dashboard-frame';
|
||||
dashboardRoot.parentNode.insertBefore(frame, dashboardRoot);
|
||||
@@ -74,8 +91,16 @@ export function initWindowChrome(adminUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBlockEditorPage()) {
|
||||
const bar = buildBar(adminUrl, false);
|
||||
bar.classList.add('aurora-winbar--editor');
|
||||
document.body.appendChild(bar);
|
||||
return;
|
||||
}
|
||||
|
||||
const wpbodyContent = document.getElementById('wpbody-content');
|
||||
if (wpbodyContent) {
|
||||
const bar = buildBar(adminUrl, false);
|
||||
wpbodyContent.insertBefore(bar, wpbodyContent.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user