diff --git a/partials/desktop/shell.php b/partials/desktop/shell.php index a32a2345..3a4337c2 100644 --- a/partials/desktop/shell.php +++ b/partials/desktop/shell.php @@ -67,6 +67,7 @@ $wallpaper = $desktopPayload['desktop']['wallpaper']; +
diff --git a/public/assets/desktop/desktop.css b/public/assets/desktop/desktop.css index 8bbefd97..67ccaed3 100644 --- a/public/assets/desktop/desktop.css +++ b/public/assets/desktop/desktop.css @@ -71,11 +71,13 @@ h1 { position: relative; overflow: hidden; min-height: 100vh; - padding: 24px 24px 120px; + padding: 0; } .desktop-icons { - position: relative; + position: absolute; + top: 24px; + left: 24px; z-index: 10; display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); @@ -180,10 +182,23 @@ h1 { display: none; } +.window.is-maximized { + border-radius: 0; + border: 0; + box-shadow: none; + max-width: none; + max-height: none; +} + .window.is-maximized .window-header { cursor: default; } +.window.is-maximized .window-content { + height: 100%; + overflow: auto; +} + .window-header { display: flex; justify-content: space-between; @@ -363,6 +378,27 @@ h1 { white-space: nowrap; } +.tray-skins { + display: flex; + align-items: center; + gap: 6px; +} + +.tray-skin-button { + border: 0; + border-radius: 999px; + padding: 8px 10px; + background: rgba(255, 255, 255, 0.08); + color: inherit; + cursor: pointer; + font-size: 12px; +} + +.tray-skin-button.is-active { + background: var(--accent); + color: #0f172a; +} + .tray-pill { padding: 8px 10px; border-radius: 999px; @@ -376,6 +412,14 @@ h1 { padding-bottom: 120px; } + .desktop-icons { + position: relative; + top: auto; + left: auto; + margin: 24px; + width: calc(100% - 48px); + } + .widget-zone { position: static; width: 100%; diff --git a/public/assets/desktop/desktop.js b/public/assets/desktop/desktop.js index e2bd8609..c9c8c4de 100644 --- a/public/assets/desktop/desktop.js +++ b/public/assets/desktop/desktop.js @@ -11,12 +11,14 @@ if (payloadNode) { const startMenuApps = document.getElementById('start-menu-apps'); const startMenuWidgets = document.getElementById('start-menu-widgets'); const startMenuActions = document.getElementById('start-menu-actions'); + const traySkins = document.getElementById('tray-skins'); const clockNode = document.getElementById('clock'); const windows = new Map(); const activeWidgets = new Set(payload.widgets.active_ids); + const activeSkin = payload.meta.active_skin; let zIndex = 20; - let topDesktopInset = 24; - let sideDesktopInset = 24; + let topDesktopInset = 0; + let sideDesktopInset = 0; let bottomDesktopInset = 120; const measureDesktopBounds = () => { @@ -28,10 +30,10 @@ if (payloadNode) { const stageRect = windowsRoot.getBoundingClientRect(); const taskbarRect = taskbar ? taskbar.getBoundingClientRect() : null; - topDesktopInset = 24; - sideDesktopInset = 24; + topDesktopInset = 0; + sideDesktopInset = 0; bottomDesktopInset = taskbarRect - ? Math.max(24, Math.round(stageRect.bottom - taskbarRect.top + 8)) + ? Math.max(0, Math.round(stageRect.bottom - taskbarRect.top)) : 120; }; @@ -61,6 +63,28 @@ if (payloadNode) { }).format(new Date()); }; + const navigateToSkin = (skin) => { + window.location.search = `?skin=${encodeURIComponent(skin)}`; + }; + + const renderTraySkins = () => { + if (!traySkins) { + return; + } + + traySkins.innerHTML = ''; + + payload.meta.available_skins.forEach((skin) => { + const button = document.createElement('button'); + button.type = 'button'; + button.className = `tray-skin-button${skin === activeSkin ? ' is-active' : ''}`; + button.textContent = skin.slice(0, 3).toUpperCase(); + button.title = skin; + button.addEventListener('click', () => navigateToSkin(skin)); + traySkins.appendChild(button); + }); + }; + const focusWindow = (windowId) => { windows.forEach((record) => { record.node.classList.remove('is-focused'); @@ -74,7 +98,7 @@ if (payloadNode) { record.state.minimized = false; record.node.classList.remove('is-minimized'); zIndex += 1; - record.node.style.zIndex = String(zIndex); + record.node.style.zIndex = String(record.state.maximized && activeSkin === 'apple' ? 1000 + zIndex : zIndex); record.node.classList.add('is-focused'); syncTaskbar(); }; @@ -120,8 +144,10 @@ if (payloadNode) { measureDesktopBounds(); record.node.style.left = `${sideDesktopInset}px`; record.node.style.top = `${topDesktopInset}px`; - record.node.style.width = `calc(100% - ${sideDesktopInset * 2}px)`; - record.node.style.height = `calc(100% - ${topDesktopInset + bottomDesktopInset}px)`; + record.node.style.width = sideDesktopInset === 0 ? '100%' : `calc(100% - ${sideDesktopInset * 2}px)`; + record.node.style.height = activeSkin === 'apple' + ? '100%' + : `calc(100% - ${topDesktopInset + bottomDesktopInset}px)`; focusWindow(windowId); return; } @@ -392,9 +418,9 @@ if (payloadNode) { if (actionId === 'cycle-skin') { const skins = payload.meta.available_skins; - const currentIndex = skins.indexOf(payload.meta.active_skin); + const currentIndex = skins.indexOf(activeSkin); const nextSkin = skins[(currentIndex + 1) % skins.length]; - window.location.search = `?skin=${encodeURIComponent(nextSkin)}`; + navigateToSkin(nextSkin); } }; @@ -468,6 +494,7 @@ if (payloadNode) { renderWidgets(); renderStartMenu(); + renderTraySkins(); setStartMenuOpen(false); measureDesktopBounds(); payload.windows.forEach(createWindow); @@ -480,8 +507,10 @@ if (payloadNode) { if (record.state.maximized) { record.node.style.left = `${sideDesktopInset}px`; record.node.style.top = `${topDesktopInset}px`; - record.node.style.width = `calc(100% - ${sideDesktopInset * 2}px)`; - record.node.style.height = `calc(100% - ${topDesktopInset + bottomDesktopInset}px)`; + record.node.style.width = sideDesktopInset === 0 ? '100%' : `calc(100% - ${sideDesktopInset * 2}px)`; + record.node.style.height = activeSkin === 'apple' + ? '100%' + : `calc(100% - ${topDesktopInset + bottomDesktopInset}px)`; } }); });