From 89c151355bc15abef634249c71d56fa5317abf3e Mon Sep 17 00:00:00 2001 From: EnderXie23 <3142007828@qq.com> Date: Thu, 23 Jul 2026 01:05:54 -0700 Subject: [PATCH 1/2] feat(windows): polish tray and route transitions --- macos/CHANGELOG.md | 6 + macos/assets/dream-skin.css | 80 ++++- macos/assets/renderer-inject.js | 49 ++- runtime/dream-skin.css | 80 ++++- runtime/renderer-inject.js | 49 ++- tools/renderer-runtime.test.mjs | 32 +- windows/CHANGELOG.md | 8 + windows/README.en.md | 1 + windows/README.md | 1 + windows/assets/dream-skin.css | 80 ++++- windows/assets/renderer-inject.js | 49 ++- windows/scripts/start-dream-skin.ps1 | 13 + windows/scripts/tray-dream-skin.ps1 | 486 ++++++++++++++++++++++++--- windows/tests/run-tests.ps1 | 58 +++- 14 files changed, 919 insertions(+), 73 deletions(-) diff --git a/macos/CHANGELOG.md b/macos/CHANGELOG.md index 7b5315d7..c0a3b18d 100644 --- a/macos/CHANGELOG.md +++ b/macos/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### 改进 + +- 路由可读性层不再等待 180ms 后才更新。统一 runtime 在 Navigation API 事件同一轮写入 `data-dream-route-phase`,下一动画帧按选择器契约复测 scope,并以 380ms 曲线驱动单一继承进度;侧栏与主区使用同一数值叠加任务页 veil,避免两列透明度不同步或梯度瞬间跳变。实现不监听 DOM subtree、不写业务 class、不读布局,并遵守 reduced-motion。 + ## 1.3.3 — 2026-07-23 ### 修复 diff --git a/macos/assets/dream-skin.css b/macos/assets/dream-skin.css index d020d73a..a6843dbf 100644 --- a/macos/assets/dream-skin.css +++ b/macos/assets/dream-skin.css @@ -1,3 +1,9 @@ +@property --ds-route-progress { + syntax: ""; + inherits: true; + initial-value: 1; +} + /* Canonical cross-platform skin. Run tools/sync-runtime-assets.mjs after editing. */ :root[data-dream-skin="active"] { color-scheme: dark !important; @@ -56,6 +62,14 @@ --ds-task-immersive-edge: rgb(var(--ds-bg-rgb) / .82); --ds-task-immersive-mid: rgb(var(--ds-bg-rgb) / .74); --ds-task-immersive-far: rgb(var(--ds-bg-rgb) / .60); + --ds-task-sidebar-overlay: rgb(var(--ds-panel-rgb) / .44); + --ds-task-sidebar-edge-overlay: rgb(var(--ds-bg-rgb) / .70); + --ds-task-overlay-edge: rgb(var(--ds-bg-rgb) / .70); + --ds-task-overlay-mid: rgb(var(--ds-bg-rgb) / .65); + --ds-task-overlay-far: rgb(var(--ds-bg-rgb) / .52); + --ds-route-progress: 1; + --ds-route-transition: 380ms cubic-bezier(.25, .32, .25, 1); + transition: --ds-route-progress var(--ds-route-transition); } html[data-dream-skin="active"][data-dream-shell="light"] { @@ -101,6 +115,23 @@ html[data-dream-skin="active"][data-dream-shell="light"] { --ds-task-immersive-edge: rgb(var(--ds-panel-rgb) / .86); --ds-task-immersive-mid: rgb(var(--ds-panel-rgb) / .78); --ds-task-immersive-far: rgb(var(--ds-panel-rgb) / .66); + --ds-task-sidebar-overlay: rgb(var(--ds-panel-rgb) / .46); + --ds-task-sidebar-edge-overlay: rgb(var(--ds-panel-rgb) / .75); + --ds-task-overlay-edge: rgb(var(--ds-panel-rgb) / .75); + --ds-task-overlay-mid: rgb(var(--ds-panel-rgb) / .69); + --ds-task-overlay-far: rgb(var(--ds-panel-rgb) / .60); +} + +/* Navigation begins at the click/navigation event, not after route DOM settles. + The renderer advances to "settling" on the next animation frame so Chromium + can interpolate one inherited value without layout reads or subtree watches. */ +html[data-dream-skin="active"][data-dream-route-phase="prepare"] { + --ds-route-progress: 0; + transition: none !important; +} + +html[data-dream-skin="active"][data-dream-route-phase="settling"] { + --ds-route-progress: 1; } html[data-dream-skin="active"]:is([data-dream-art-safe="left"], [data-dream-art-safe-area="left"]) { @@ -316,12 +347,35 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) aside.app-shell-left-panel { background: linear-gradient(90deg, - var(--ds-task-immersive-sidebar), - var(--ds-task-immersive-edge) 100%) !important; + var(--ds-immersive-sidebar), + var(--ds-immersive-edge) 100%) !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; backdrop-filter: none !important; + isolation: isolate; +} + +/* The sidebar and main surface share this inherited progress value. Keeping the + stronger task wash in separate overlays avoids a discrete gradient swap. */ +html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) + aside.app-shell-left-panel::before { + content: ""; + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + background: linear-gradient(90deg, + var(--ds-task-sidebar-overlay), + var(--ds-task-sidebar-edge-overlay)); + opacity: var(--ds-route-progress); + will-change: opacity; +} + +html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) + aside.app-shell-left-panel > :first-child { + position: relative; + z-index: 1; } /* Native sidebar resize chrome inherits the sidebar background and extends @@ -334,9 +388,9 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) main.main-surface:not(:has([role="main"])) { background: linear-gradient(90deg, - var(--ds-task-immersive-edge), - var(--ds-task-immersive-mid) 64%, - var(--ds-task-immersive-far)) !important; + var(--ds-immersive-edge), + var(--ds-immersive-mid) 64%, + var(--ds-immersive-far)) !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; @@ -344,7 +398,17 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"] main.main-surface:not(:has([role="main"]))::before { - content: none; + content: ""; + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + background: linear-gradient(90deg, + var(--ds-task-overlay-edge), + var(--ds-task-overlay-mid) 64%, + var(--ds-task-overlay-far)); + opacity: var(--ds-route-progress); + will-change: opacity; } html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) @@ -1084,6 +1148,10 @@ html[data-dream-skin="active"] [data-message-author-role] { border-radius: 16px; } @media (prefers-reduced-motion: reduce) { + :root[data-dream-skin="active"] { + --ds-route-transition: 0ms linear; + } + html[data-dream-skin="active"] *, html[data-dream-skin="active"] *::before, html[data-dream-skin="active"] *::after { diff --git a/macos/assets/renderer-inject.js b/macos/assets/renderer-inject.js index bf2bb1cb..99a76df2 100644 --- a/macos/assets/renderer-inject.js +++ b/macos/assets/renderer-inject.js @@ -10,8 +10,9 @@ "data-dream-skin", SHELL_ATTR, "data-dream-art-wide", "data-dream-art-safe", "data-dream-task-mode", "data-dream-art-safe-area", "data-dream-art-task-mode", "data-dream-art-aspect", - "data-dream-art-ready", + "data-dream-art-ready", "data-dream-route-phase", ]; + const ROUTE_TRANSITION_MS = 380; const VERSION = __DREAM_SKIN_VERSION_JSON__; const STYLE_REVISION = __DREAM_SKIN_STYLE_REVISION_JSON__; const PAYLOAD_REVISION = __DREAM_SKIN_PAYLOAD_REVISION_JSON__; @@ -58,6 +59,7 @@ styleWrites: 0, styleRepairs: 0, navigationEvents: 0, + routeTransitions: 0, safetyPasses: 0, analysisRuns: 0, analysisCacheHits: artAnalysis ? 1 : 0, @@ -586,6 +588,16 @@ } if (state?.timer) clearInterval(state.timer); if (state?.scheduler?.timeout) clearTimeout(state.scheduler.timeout); + if (state?.routeTransition?.frame !== null) { + if (typeof window.cancelAnimationFrame === "function") { + window.cancelAnimationFrame(state.routeTransition.frame); + } else { + clearTimeout(state.routeTransition.frame); + } + } + if (state?.routeTransition?.timeout !== null) { + clearTimeout(state.routeTransition.timeout); + } if (analysisTimer) clearTimeout(analysisTimer); if (state?.mediaHandler && state?.mediaQuery) { try { state.mediaQuery.removeEventListener("change", state.mediaHandler); } catch {} @@ -623,6 +635,37 @@ if (scheduler.timeout) return; scheduler.timeout = setTimeout(flushScheduledEnsure, delay); }; + const routeTransition = { frame: null, timeout: null }; + const requestRouteFrame = (callback) => typeof window.requestAnimationFrame === "function" + ? window.requestAnimationFrame(callback) + : setTimeout(callback, 0); + const cancelRouteFrame = (frame) => { + if (frame === null) return; + if (typeof window.cancelAnimationFrame === "function") window.cancelAnimationFrame(frame); + else clearTimeout(frame); + }; + const beginRouteTransition = () => { + const root = document.documentElement; + if (!root) return; + cancelRouteFrame(routeTransition.frame); + routeTransition.frame = null; + if (routeTransition.timeout !== null) clearTimeout(routeTransition.timeout); + routeTransition.timeout = null; + setAttribute(root, "data-dream-route-phase", "prepare"); + metrics.routeTransitions += 1; + routeTransition.frame = requestRouteFrame(() => { + routeTransition.frame = null; + if (window[DISABLED_KEY] || window[STATE_KEY]?.installToken !== installToken) return; + setAttribute(root, "data-dream-route-phase", "settling"); + ensure({ scope: true }); + routeTransition.timeout = setTimeout(() => { + routeTransition.timeout = null; + if (window[STATE_KEY]?.installToken === installToken) { + root.removeAttribute("data-dream-route-phase"); + } + }, ROUTE_TRANSITION_MS); + }); + }; if (typeof MutationObserver === "function") { rootObserver = new MutationObserver(() => scheduleEnsure({ root: true })); } @@ -638,7 +681,7 @@ ? window.navigation : null; const navigationHandler = navigationApi ? () => { metrics.navigationEvents += 1; - scheduleEnsure({ scope: true }, 180); + beginRouteTransition(); } : null; window[STATE_KEY] = { @@ -647,6 +690,7 @@ rootObserver, timer: null, scheduler, + routeTransition, mediaQuery, mediaHandler, navigation: navigationApi, @@ -666,6 +710,7 @@ themeId: THEME.id || "custom", revision: PAYLOAD_REVISION, detectShellAppearance, + beginRouteTransition, }; const firstEnsureStartedAt = now(); ensure({ root: true }); diff --git a/runtime/dream-skin.css b/runtime/dream-skin.css index 77e6d5d5..fabac57c 100644 --- a/runtime/dream-skin.css +++ b/runtime/dream-skin.css @@ -1,3 +1,9 @@ +@property --ds-route-progress { + syntax: ""; + inherits: true; + initial-value: 1; +} + /* Canonical cross-platform skin. Run tools/sync-runtime-assets.mjs after editing. */ :root[data-dream-skin="active"] { color-scheme: dark !important; @@ -56,6 +62,14 @@ --ds-task-immersive-edge: rgb(var(--ds-bg-rgb) / .82); --ds-task-immersive-mid: rgb(var(--ds-bg-rgb) / .74); --ds-task-immersive-far: rgb(var(--ds-bg-rgb) / .60); + --ds-task-sidebar-overlay: rgb(var(--ds-panel-rgb) / .44); + --ds-task-sidebar-edge-overlay: rgb(var(--ds-bg-rgb) / .70); + --ds-task-overlay-edge: rgb(var(--ds-bg-rgb) / .70); + --ds-task-overlay-mid: rgb(var(--ds-bg-rgb) / .65); + --ds-task-overlay-far: rgb(var(--ds-bg-rgb) / .52); + --ds-route-progress: 1; + --ds-route-transition: 380ms cubic-bezier(.25, .32, .25, 1); + transition: --ds-route-progress var(--ds-route-transition); } html[data-dream-skin="active"][data-dream-shell="light"] { @@ -101,6 +115,23 @@ html[data-dream-skin="active"][data-dream-shell="light"] { --ds-task-immersive-edge: rgb(var(--ds-panel-rgb) / .86); --ds-task-immersive-mid: rgb(var(--ds-panel-rgb) / .78); --ds-task-immersive-far: rgb(var(--ds-panel-rgb) / .66); + --ds-task-sidebar-overlay: rgb(var(--ds-panel-rgb) / .46); + --ds-task-sidebar-edge-overlay: rgb(var(--ds-panel-rgb) / .75); + --ds-task-overlay-edge: rgb(var(--ds-panel-rgb) / .75); + --ds-task-overlay-mid: rgb(var(--ds-panel-rgb) / .69); + --ds-task-overlay-far: rgb(var(--ds-panel-rgb) / .60); +} + +/* Navigation begins at the click/navigation event, not after route DOM settles. + The renderer advances to "settling" on the next animation frame so Chromium + can interpolate one inherited value without layout reads or subtree watches. */ +html[data-dream-skin="active"][data-dream-route-phase="prepare"] { + --ds-route-progress: 0; + transition: none !important; +} + +html[data-dream-skin="active"][data-dream-route-phase="settling"] { + --ds-route-progress: 1; } html[data-dream-skin="active"]:is([data-dream-art-safe="left"], [data-dream-art-safe-area="left"]) { @@ -316,12 +347,35 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(__DREAM_SELECTOR_SHELL_MAIN__):not(:has(__DREAM_SELECTOR_SHELL_MAIN__ __DREAM_SELECTOR_HOME_ROUTE_CSS__)) __DREAM_SELECTOR_LEFT_PANEL__ { background: linear-gradient(90deg, - var(--ds-task-immersive-sidebar), - var(--ds-task-immersive-edge) 100%) !important; + var(--ds-immersive-sidebar), + var(--ds-immersive-edge) 100%) !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; backdrop-filter: none !important; + isolation: isolate; +} + +/* The sidebar and main surface share this inherited progress value. Keeping the + stronger task wash in separate overlays avoids a discrete gradient swap. */ +html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(__DREAM_SELECTOR_SHELL_MAIN__):not(:has(__DREAM_SELECTOR_SHELL_MAIN__ __DREAM_SELECTOR_HOME_ROUTE_CSS__)) + __DREAM_SELECTOR_LEFT_PANEL__::before { + content: ""; + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + background: linear-gradient(90deg, + var(--ds-task-sidebar-overlay), + var(--ds-task-sidebar-edge-overlay)); + opacity: var(--ds-route-progress); + will-change: opacity; +} + +html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(__DREAM_SELECTOR_SHELL_MAIN__):not(:has(__DREAM_SELECTOR_SHELL_MAIN__ __DREAM_SELECTOR_HOME_ROUTE_CSS__)) + __DREAM_SELECTOR_LEFT_PANEL__ > :first-child { + position: relative; + z-index: 1; } /* Native sidebar resize chrome inherits the sidebar background and extends @@ -334,9 +388,9 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(__DREAM_SELECTOR_SHELL_MAIN__):not(:has(__DREAM_SELECTOR_SHELL_MAIN__ __DREAM_SELECTOR_HOME_ROUTE_CSS__)) __DREAM_SELECTOR_SHELL_MAIN__:not(:has(__DREAM_SELECTOR_HOME_ROUTE_CSS__)) { background: linear-gradient(90deg, - var(--ds-task-immersive-edge), - var(--ds-task-immersive-mid) 64%, - var(--ds-task-immersive-far)) !important; + var(--ds-immersive-edge), + var(--ds-immersive-mid) 64%, + var(--ds-immersive-far)) !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; @@ -344,7 +398,17 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"] __DREAM_SELECTOR_SHELL_MAIN__:not(:has(__DREAM_SELECTOR_HOME_ROUTE_CSS__))::before { - content: none; + content: ""; + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + background: linear-gradient(90deg, + var(--ds-task-overlay-edge), + var(--ds-task-overlay-mid) 64%, + var(--ds-task-overlay-far)); + opacity: var(--ds-route-progress); + will-change: opacity; } html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(__DREAM_SELECTOR_SHELL_MAIN__):not(:has(__DREAM_SELECTOR_SHELL_MAIN__ __DREAM_SELECTOR_HOME_ROUTE_CSS__)) @@ -1084,6 +1148,10 @@ html[data-dream-skin="active"] [data-message-author-role] { border-radius: 16px; } @media (prefers-reduced-motion: reduce) { + :root[data-dream-skin="active"] { + --ds-route-transition: 0ms linear; + } + html[data-dream-skin="active"] *, html[data-dream-skin="active"] *::before, html[data-dream-skin="active"] *::after { diff --git a/runtime/renderer-inject.js b/runtime/renderer-inject.js index b0b868f4..8af964f0 100644 --- a/runtime/renderer-inject.js +++ b/runtime/renderer-inject.js @@ -10,8 +10,9 @@ "data-dream-skin", SHELL_ATTR, "data-dream-art-wide", "data-dream-art-safe", "data-dream-task-mode", "data-dream-art-safe-area", "data-dream-art-task-mode", "data-dream-art-aspect", - "data-dream-art-ready", + "data-dream-art-ready", "data-dream-route-phase", ]; + const ROUTE_TRANSITION_MS = 380; const VERSION = __DREAM_SKIN_VERSION_JSON__; const STYLE_REVISION = __DREAM_SKIN_STYLE_REVISION_JSON__; const PAYLOAD_REVISION = __DREAM_SKIN_PAYLOAD_REVISION_JSON__; @@ -58,6 +59,7 @@ styleWrites: 0, styleRepairs: 0, navigationEvents: 0, + routeTransitions: 0, safetyPasses: 0, analysisRuns: 0, analysisCacheHits: artAnalysis ? 1 : 0, @@ -586,6 +588,16 @@ } if (state?.timer) clearInterval(state.timer); if (state?.scheduler?.timeout) clearTimeout(state.scheduler.timeout); + if (state?.routeTransition?.frame !== null) { + if (typeof window.cancelAnimationFrame === "function") { + window.cancelAnimationFrame(state.routeTransition.frame); + } else { + clearTimeout(state.routeTransition.frame); + } + } + if (state?.routeTransition?.timeout !== null) { + clearTimeout(state.routeTransition.timeout); + } if (analysisTimer) clearTimeout(analysisTimer); if (state?.mediaHandler && state?.mediaQuery) { try { state.mediaQuery.removeEventListener("change", state.mediaHandler); } catch {} @@ -623,6 +635,37 @@ if (scheduler.timeout) return; scheduler.timeout = setTimeout(flushScheduledEnsure, delay); }; + const routeTransition = { frame: null, timeout: null }; + const requestRouteFrame = (callback) => typeof window.requestAnimationFrame === "function" + ? window.requestAnimationFrame(callback) + : setTimeout(callback, 0); + const cancelRouteFrame = (frame) => { + if (frame === null) return; + if (typeof window.cancelAnimationFrame === "function") window.cancelAnimationFrame(frame); + else clearTimeout(frame); + }; + const beginRouteTransition = () => { + const root = document.documentElement; + if (!root) return; + cancelRouteFrame(routeTransition.frame); + routeTransition.frame = null; + if (routeTransition.timeout !== null) clearTimeout(routeTransition.timeout); + routeTransition.timeout = null; + setAttribute(root, "data-dream-route-phase", "prepare"); + metrics.routeTransitions += 1; + routeTransition.frame = requestRouteFrame(() => { + routeTransition.frame = null; + if (window[DISABLED_KEY] || window[STATE_KEY]?.installToken !== installToken) return; + setAttribute(root, "data-dream-route-phase", "settling"); + ensure({ scope: true }); + routeTransition.timeout = setTimeout(() => { + routeTransition.timeout = null; + if (window[STATE_KEY]?.installToken === installToken) { + root.removeAttribute("data-dream-route-phase"); + } + }, ROUTE_TRANSITION_MS); + }); + }; if (typeof MutationObserver === "function") { rootObserver = new MutationObserver(() => scheduleEnsure({ root: true })); } @@ -638,7 +681,7 @@ ? window.navigation : null; const navigationHandler = navigationApi ? () => { metrics.navigationEvents += 1; - scheduleEnsure({ scope: true }, 180); + beginRouteTransition(); } : null; window[STATE_KEY] = { @@ -647,6 +690,7 @@ rootObserver, timer: null, scheduler, + routeTransition, mediaQuery, mediaHandler, navigation: navigationApi, @@ -666,6 +710,7 @@ themeId: THEME.id || "custom", revision: PAYLOAD_REVISION, detectShellAppearance, + beginRouteTransition, }; const firstEnsureStartedAt = now(); ensure({ root: true }); diff --git a/tools/renderer-runtime.test.mjs b/tools/renderer-runtime.test.mjs index d464b7bb..f02eb745 100644 --- a/tools/renderer-runtime.test.mjs +++ b/tools/renderer-runtime.test.mjs @@ -35,6 +35,7 @@ function makeFixture({ nativeAppearance = "dark", settings = false, adopted = tr const observers = []; const timers = new Map(); const intervals = new Map(); + const frames = new Map(); const listeners = new Map(); const revoked = []; let nextId = 0; @@ -91,6 +92,12 @@ function makeFixture({ nativeAppearance = "dark", settings = false, adopted = tr } const window = { navigation, + requestAnimationFrame(callback) { + const id = ++nextId; + frames.set(id, callback); + return id; + }, + cancelAnimationFrame(id) { frames.delete(id); }, matchMedia() { return { matches: nativeAppearance === "dark", @@ -135,8 +142,14 @@ function makeFixture({ nativeAppearance = "dark", settings = false, adopted = tr if (timer.delay <= maximumDelay) { timers.delete(id); timer.callback(); } } }; + const flushAnimationFrames = () => { + for (const [id, callback] of [...frames]) { + frames.delete(id); + callback(16); + } + }; return { - attrs, context, document, flushTimers, intervals, listeners, nodes, observers, + attrs, context, document, flushAnimationFrames, flushTimers, frames, intervals, listeners, nodes, observers, payloadFor, revoked, root, rootClasses, rootStyle, timers, window, }; } @@ -193,6 +206,13 @@ export async function runRendererRuntimeTest(assetRoot) { // and the measured fossil selector must be absent from the canonical CSS. assert.doesNotMatch(css, /(?:^|[.#\s])(?:codex-dream-skin|dream-skin-home|dream-home|dream-task)(?:[\s.#:{>]|$)|home-suggestion-list-item/); assert.match(css, /html\[data-dream-skin="active"\]/); + assert.match(css, /@property --ds-route-progress/); + assert.match(css, /\[data-dream-route-phase="prepare"\]/); + assert.match(css, /--ds-route-transition:\s*380ms cubic-bezier/); + assert.ok((css.match(/opacity:\s*var\(--ds-route-progress\)/g) || []).length >= 2, + "Sidebar and main route overlays must consume the same progress value."); + assert.doesNotMatch(template, /scheduleEnsure\(\{\s*scope:\s*true\s*\},\s*180\)/, + "Navigation must not retain the retired 180ms route debounce."); // Home gating must stay single-level: CSS forbids :has() inside :has(), // and Chromium drops any rule that nests it (the v1.3.1 regression). The // canonical CSS therefore gates on the :has()-free home-route-css alias. @@ -232,9 +252,17 @@ export async function runRendererRuntimeTest(assetRoot) { const navigationHandler = home.listeners.get("navigation:navigate"); assert.equal(typeof navigationHandler, "function"); navigationHandler(); - home.flushTimers(180); + assert.equal(home.attrs.get("data-dream-route-phase"), "prepare", + "Navigation must reset route progress in the same event turn."); + assert.equal(state.metrics.routePasses, 1, + "Scope measurement waits for the next animation frame, not an arbitrary debounce."); + home.flushAnimationFrames(); + assert.equal(home.attrs.get("data-dream-route-phase"), "settling"); assert.equal(state.metrics.navigationEvents, 1); + assert.equal(state.metrics.routeTransitions, 1); assert.equal(state.metrics.routePasses, 2); + home.flushTimers(380); + assert.equal(home.attrs.has("data-dream-route-phase"), false); const settings = makeFixture({ nativeAppearance: "light", settings: true }); vm.runInNewContext(settings.payloadFor(), settings.context); diff --git a/windows/CHANGELOG.md b/windows/CHANGELOG.md index 5ec35427..992d77f9 100644 --- a/windows/CHANGELOG.md +++ b/windows/CHANGELOG.md @@ -1,5 +1,13 @@ # Windows Changelog +## Unreleased + +### 改进 + +- 托盘菜单改为更接近 Windows 11 / Codex 的轻量原生面板:主菜单和主题子菜单使用真正的圆角裁切、双层品牌/状态标题(运行绿、暂停棕、异常红)、紧凑 Segoe UI 字号、内容自适应宽度、统一 16px 文本栅格、柔和中性悬停、浅蓝灰分隔线和独立退出区,避免高 DPI 下字体、行距与右侧留白过度放大;源码运行缺少安装器 ICO 时会在内存中绘制同款品牌标记,不再退回无辨识度的系统应用图标。新增「停止 Dream Skin」与 DreamSkin Studio 入口,并由真实 WinForms 自测覆盖图标、渲染器和空菜单首项。 +- 启动脚本只在皮肤验证成功后补启一次托盘,并通过隐藏的 STA PowerShell 子进程托管通知区图标;启动脚本会立即正常结束,托盘互斥锁继续阻止重复后台实例。 +- 路由白色/深色可读性层不再等待 180ms 后才更新。统一 runtime 在 Navigation API 事件同一轮写入 `data-dream-route-phase`,下一动画帧按选择器契约复测 scope,并以 380ms 曲线驱动单一继承进度;左栏与主区使用同一数值叠加任务页 veil,避免两列透明度不同步或梯度瞬间跳变。实现仍不监听 DOM subtree、不写业务 class、不读布局,并遵守 reduced-motion。 + ## 1.3.3 — 2026-07-23 ### 修复 diff --git a/windows/README.en.md b/windows/README.en.md index 58df845b..1f9232bc 100644 --- a/windows/README.en.md +++ b/windows/README.en.md @@ -59,6 +59,7 @@ Exit the Dream Skin tray and close Codex, update the checkout (`git pull`, or do ## Launch and verify The `Codex Dream Skin` shortcut is the recommended launcher. It asks for confirmation before restarting an open Codex window. +After the skin verifies successfully, the launcher hands the tray controller to a hidden background process and exits; a mutex prevents duplicate tray instances. Command-line launch: diff --git a/windows/README.md b/windows/README.md index 8a63f69c..e5d8ffdb 100644 --- a/windows/README.md +++ b/windows/README.md @@ -52,6 +52,7 @@ powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File .\scripts\install- ## 启动与验证 推荐从 `Codex Dream Skin` 快捷方式启动。它发现 Codex 已经运行时会先询问是否重启。 +皮肤验证成功后,启动脚本会按需把托盘控制器交给隐藏的后台进程并立即结束;互斥锁会避免重复托盘。 命令行启动: diff --git a/windows/assets/dream-skin.css b/windows/assets/dream-skin.css index d020d73a..a6843dbf 100644 --- a/windows/assets/dream-skin.css +++ b/windows/assets/dream-skin.css @@ -1,3 +1,9 @@ +@property --ds-route-progress { + syntax: ""; + inherits: true; + initial-value: 1; +} + /* Canonical cross-platform skin. Run tools/sync-runtime-assets.mjs after editing. */ :root[data-dream-skin="active"] { color-scheme: dark !important; @@ -56,6 +62,14 @@ --ds-task-immersive-edge: rgb(var(--ds-bg-rgb) / .82); --ds-task-immersive-mid: rgb(var(--ds-bg-rgb) / .74); --ds-task-immersive-far: rgb(var(--ds-bg-rgb) / .60); + --ds-task-sidebar-overlay: rgb(var(--ds-panel-rgb) / .44); + --ds-task-sidebar-edge-overlay: rgb(var(--ds-bg-rgb) / .70); + --ds-task-overlay-edge: rgb(var(--ds-bg-rgb) / .70); + --ds-task-overlay-mid: rgb(var(--ds-bg-rgb) / .65); + --ds-task-overlay-far: rgb(var(--ds-bg-rgb) / .52); + --ds-route-progress: 1; + --ds-route-transition: 380ms cubic-bezier(.25, .32, .25, 1); + transition: --ds-route-progress var(--ds-route-transition); } html[data-dream-skin="active"][data-dream-shell="light"] { @@ -101,6 +115,23 @@ html[data-dream-skin="active"][data-dream-shell="light"] { --ds-task-immersive-edge: rgb(var(--ds-panel-rgb) / .86); --ds-task-immersive-mid: rgb(var(--ds-panel-rgb) / .78); --ds-task-immersive-far: rgb(var(--ds-panel-rgb) / .66); + --ds-task-sidebar-overlay: rgb(var(--ds-panel-rgb) / .46); + --ds-task-sidebar-edge-overlay: rgb(var(--ds-panel-rgb) / .75); + --ds-task-overlay-edge: rgb(var(--ds-panel-rgb) / .75); + --ds-task-overlay-mid: rgb(var(--ds-panel-rgb) / .69); + --ds-task-overlay-far: rgb(var(--ds-panel-rgb) / .60); +} + +/* Navigation begins at the click/navigation event, not after route DOM settles. + The renderer advances to "settling" on the next animation frame so Chromium + can interpolate one inherited value without layout reads or subtree watches. */ +html[data-dream-skin="active"][data-dream-route-phase="prepare"] { + --ds-route-progress: 0; + transition: none !important; +} + +html[data-dream-skin="active"][data-dream-route-phase="settling"] { + --ds-route-progress: 1; } html[data-dream-skin="active"]:is([data-dream-art-safe="left"], [data-dream-art-safe-area="left"]) { @@ -316,12 +347,35 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) aside.app-shell-left-panel { background: linear-gradient(90deg, - var(--ds-task-immersive-sidebar), - var(--ds-task-immersive-edge) 100%) !important; + var(--ds-immersive-sidebar), + var(--ds-immersive-edge) 100%) !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; backdrop-filter: none !important; + isolation: isolate; +} + +/* The sidebar and main surface share this inherited progress value. Keeping the + stronger task wash in separate overlays avoids a discrete gradient swap. */ +html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) + aside.app-shell-left-panel::before { + content: ""; + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + background: linear-gradient(90deg, + var(--ds-task-sidebar-overlay), + var(--ds-task-sidebar-edge-overlay)); + opacity: var(--ds-route-progress); + will-change: opacity; +} + +html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) + aside.app-shell-left-panel > :first-child { + position: relative; + z-index: 1; } /* Native sidebar resize chrome inherits the sidebar background and extends @@ -334,9 +388,9 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) main.main-surface:not(:has([role="main"])) { background: linear-gradient(90deg, - var(--ds-task-immersive-edge), - var(--ds-task-immersive-mid) 64%, - var(--ds-task-immersive-far)) !important; + var(--ds-immersive-edge), + var(--ds-immersive-mid) 64%, + var(--ds-immersive-far)) !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; @@ -344,7 +398,17 @@ html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream- html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"] main.main-surface:not(:has([role="main"]))::before { - content: none; + content: ""; + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + background: linear-gradient(90deg, + var(--ds-task-overlay-edge), + var(--ds-task-overlay-mid) 64%, + var(--ds-task-overlay-far)); + opacity: var(--ds-route-progress); + will-change: opacity; } html[data-dream-skin="active"]:is([data-dream-task-mode="ambient"], [data-dream-art-task-mode="ambient"], [data-dream-task-mode="banner"], [data-dream-art-task-mode="banner"])[data-dream-art-wide="true"]:has(main.main-surface):not(:has(main.main-surface [role="main"])) @@ -1084,6 +1148,10 @@ html[data-dream-skin="active"] [data-message-author-role] { border-radius: 16px; } @media (prefers-reduced-motion: reduce) { + :root[data-dream-skin="active"] { + --ds-route-transition: 0ms linear; + } + html[data-dream-skin="active"] *, html[data-dream-skin="active"] *::before, html[data-dream-skin="active"] *::after { diff --git a/windows/assets/renderer-inject.js b/windows/assets/renderer-inject.js index bf2bb1cb..99a76df2 100644 --- a/windows/assets/renderer-inject.js +++ b/windows/assets/renderer-inject.js @@ -10,8 +10,9 @@ "data-dream-skin", SHELL_ATTR, "data-dream-art-wide", "data-dream-art-safe", "data-dream-task-mode", "data-dream-art-safe-area", "data-dream-art-task-mode", "data-dream-art-aspect", - "data-dream-art-ready", + "data-dream-art-ready", "data-dream-route-phase", ]; + const ROUTE_TRANSITION_MS = 380; const VERSION = __DREAM_SKIN_VERSION_JSON__; const STYLE_REVISION = __DREAM_SKIN_STYLE_REVISION_JSON__; const PAYLOAD_REVISION = __DREAM_SKIN_PAYLOAD_REVISION_JSON__; @@ -58,6 +59,7 @@ styleWrites: 0, styleRepairs: 0, navigationEvents: 0, + routeTransitions: 0, safetyPasses: 0, analysisRuns: 0, analysisCacheHits: artAnalysis ? 1 : 0, @@ -586,6 +588,16 @@ } if (state?.timer) clearInterval(state.timer); if (state?.scheduler?.timeout) clearTimeout(state.scheduler.timeout); + if (state?.routeTransition?.frame !== null) { + if (typeof window.cancelAnimationFrame === "function") { + window.cancelAnimationFrame(state.routeTransition.frame); + } else { + clearTimeout(state.routeTransition.frame); + } + } + if (state?.routeTransition?.timeout !== null) { + clearTimeout(state.routeTransition.timeout); + } if (analysisTimer) clearTimeout(analysisTimer); if (state?.mediaHandler && state?.mediaQuery) { try { state.mediaQuery.removeEventListener("change", state.mediaHandler); } catch {} @@ -623,6 +635,37 @@ if (scheduler.timeout) return; scheduler.timeout = setTimeout(flushScheduledEnsure, delay); }; + const routeTransition = { frame: null, timeout: null }; + const requestRouteFrame = (callback) => typeof window.requestAnimationFrame === "function" + ? window.requestAnimationFrame(callback) + : setTimeout(callback, 0); + const cancelRouteFrame = (frame) => { + if (frame === null) return; + if (typeof window.cancelAnimationFrame === "function") window.cancelAnimationFrame(frame); + else clearTimeout(frame); + }; + const beginRouteTransition = () => { + const root = document.documentElement; + if (!root) return; + cancelRouteFrame(routeTransition.frame); + routeTransition.frame = null; + if (routeTransition.timeout !== null) clearTimeout(routeTransition.timeout); + routeTransition.timeout = null; + setAttribute(root, "data-dream-route-phase", "prepare"); + metrics.routeTransitions += 1; + routeTransition.frame = requestRouteFrame(() => { + routeTransition.frame = null; + if (window[DISABLED_KEY] || window[STATE_KEY]?.installToken !== installToken) return; + setAttribute(root, "data-dream-route-phase", "settling"); + ensure({ scope: true }); + routeTransition.timeout = setTimeout(() => { + routeTransition.timeout = null; + if (window[STATE_KEY]?.installToken === installToken) { + root.removeAttribute("data-dream-route-phase"); + } + }, ROUTE_TRANSITION_MS); + }); + }; if (typeof MutationObserver === "function") { rootObserver = new MutationObserver(() => scheduleEnsure({ root: true })); } @@ -638,7 +681,7 @@ ? window.navigation : null; const navigationHandler = navigationApi ? () => { metrics.navigationEvents += 1; - scheduleEnsure({ scope: true }, 180); + beginRouteTransition(); } : null; window[STATE_KEY] = { @@ -647,6 +690,7 @@ rootObserver, timer: null, scheduler, + routeTransition, mediaQuery, mediaHandler, navigation: navigationApi, @@ -666,6 +710,7 @@ themeId: THEME.id || "custom", revision: PAYLOAD_REVISION, detectShellAppearance, + beginRouteTransition, }; const firstEnsureStartedAt = now(); ensure({ root: true }); diff --git a/windows/scripts/start-dream-skin.ps1 b/windows/scripts/start-dream-skin.ps1 index 8925d552..61e59898 100644 --- a/windows/scripts/start-dream-skin.ps1 +++ b/windows/scripts/start-dream-skin.ps1 @@ -13,6 +13,18 @@ $Injector = Join-Path $PSScriptRoot 'injector.mjs' . (Join-Path $PSScriptRoot 'common-windows.ps1') . (Join-Path $PSScriptRoot 'theme-windows.ps1') +function Start-DreamSkinTrayInBackground { + param([Parameter(Mandatory = $true)][int]$TrayPort) + if (Test-DreamSkinTrayActive) { return } + + $powershell = (Get-Command powershell.exe -ErrorAction Stop).Source + $trayScript = Join-Path $PSScriptRoot 'tray-dream-skin.ps1' + $trayToken = ConvertTo-DreamSkinProcessArgument -Value $trayScript + $trayArguments = '-NoProfile -STA -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File ' + + $trayToken + " -Port $TrayPort" + Start-Process -FilePath $powershell -ArgumentList $trayArguments -WindowStyle Hidden | Out-Null +} + $operationLock = Enter-DreamSkinOperationLock try { Assert-DreamSkinPort -Port $Port @@ -306,6 +318,7 @@ try { } Write-Host "Codex Dream Skin is active on verified loopback port $Port." + Start-DreamSkinTrayInBackground -TrayPort $Port } finally { if ($null -ne $operationLock) { Exit-DreamSkinOperationLock -Mutex $operationLock } } diff --git a/windows/scripts/tray-dream-skin.ps1 b/windows/scripts/tray-dream-skin.ps1 index 5d2e62eb..8c42a082 100644 --- a/windows/scripts/tray-dream-skin.ps1 +++ b/windows/scripts/tray-dream-skin.ps1 @@ -1,5 +1,8 @@ [CmdletBinding()] -param([int]$Port = 9335) +param( + [int]$Port = 9335, + [switch]$SelfTest +) $ErrorActionPreference = 'Stop' Add-Type -AssemblyName System.Windows.Forms @@ -8,6 +11,402 @@ Add-Type -AssemblyName Microsoft.VisualBasic . (Join-Path $PSScriptRoot 'common-windows.ps1') . (Join-Path $PSScriptRoot 'theme-windows.ps1') +if (-not ('DreamSkin.TrayRenderer' -as [type])) { + Add-Type -ReferencedAssemblies @( + [System.Windows.Forms.NotifyIcon].Assembly.Location, + [System.Drawing.Bitmap].Assembly.Location + ) -TypeDefinition @' +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace DreamSkin { + public static class NativeMethods { + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DestroyIcon(IntPtr handle); + } + + public sealed class TrayColorTable : ProfessionalColorTable { + private static readonly Color Surface = Color.FromArgb(255, 255, 255, 255); + private static readonly Color Selected = Color.FromArgb(255, 243, 244, 246); + private static readonly Color Accent = Color.FromArgb(255, 37, 99, 235); + private static readonly Color Border = Color.FromArgb(255, 218, 222, 229); + private static readonly Color Divider = Color.FromArgb(255, 218, 228, 242); + + public override Color ToolStripDropDownBackground { get { return Surface; } } + public override Color ImageMarginGradientBegin { get { return Surface; } } + public override Color ImageMarginGradientMiddle { get { return Surface; } } + public override Color ImageMarginGradientEnd { get { return Surface; } } + public override Color MenuItemSelected { get { return Selected; } } + public override Color MenuItemBorder { get { return Accent; } } + public override Color MenuBorder { get { return Border; } } + public override Color SeparatorDark { get { return Divider; } } + public override Color SeparatorLight { get { return Color.Transparent; } } + public override Color CheckBackground { get { return Selected; } } + public override Color CheckSelectedBackground { get { return Selected; } } + public override Color CheckPressedBackground { get { return Selected; } } + } + + public sealed class TrayMenu : ContextMenuStrip { + private static GraphicsPath RoundedRectangle(Rectangle bounds, int radius) { + GraphicsPath path = new GraphicsPath(); + int diameter = radius * 2; + Rectangle arc = new Rectangle(bounds.Location, new Size(diameter, diameter)); + path.AddArc(arc, 180, 90); + arc.X = bounds.Right - diameter; + path.AddArc(arc, 270, 90); + arc.Y = bounds.Bottom - diameter; + path.AddArc(arc, 0, 90); + arc.X = bounds.Left; + path.AddArc(arc, 90, 90); + path.CloseFigure(); + return path; + } + + private void ApplyRoundedRegion() { + if (Width < 2 || Height < 2) return; + int radius = Math.Max(10, (int)Math.Round(14.0 * DeviceDpi / 96.0)); + using (GraphicsPath path = RoundedRectangle(new Rectangle(0, 0, Width, Height), radius)) { + Region previous = Region; + Region = new Region(path); + if (previous != null) previous.Dispose(); + } + } + + public TrayMenu() { + SetStyle( + ControlStyles.AllPaintingInWmPaint | + ControlStyles.OptimizedDoubleBuffer | + ControlStyles.ResizeRedraw, + true + ); + } + + protected override void OnHandleCreated(EventArgs e) { + base.OnHandleCreated(e); + ApplyRoundedRegion(); + } + + protected override void OnSizeChanged(EventArgs e) { + base.OnSizeChanged(e); + ApplyRoundedRegion(); + } + + protected override void Dispose(bool disposing) { + if (disposing && Region != null) { + Region.Dispose(); + Region = null; + } + base.Dispose(disposing); + } + } + + public sealed class TrayRenderer : ToolStripProfessionalRenderer { + private static GraphicsPath RoundedRectangle(Rectangle bounds, int radius) { + GraphicsPath path = new GraphicsPath(); + int diameter = radius * 2; + Rectangle arc = new Rectangle(bounds.Location, new Size(diameter, diameter)); + path.AddArc(arc, 180, 90); + arc.X = bounds.Right - diameter; + path.AddArc(arc, 270, 90); + arc.Y = bounds.Bottom - diameter; + path.AddArc(arc, 0, 90); + arc.X = bounds.Left; + path.AddArc(arc, 90, 90); + path.CloseFigure(); + return path; + } + + public TrayRenderer() : base(new TrayColorTable()) { + RoundedEdges = true; + } + + protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) { + e.Graphics.Clear(Color.White); + } + + protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) { + // Keep the menu visually flat. Checks are rendered independently below. + } + + protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { + if (!e.Item.Selected || !e.Item.Enabled) return; + Rectangle bounds = new Rectangle(4, 1, Math.Max(1, e.Item.Width - 8), Math.Max(1, e.Item.Height - 2)); + SmoothingMode previous = e.Graphics.SmoothingMode; + e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; + using (GraphicsPath path = RoundedRectangle(bounds, 8)) + using (SolidBrush brush = new SolidBrush(Color.FromArgb(255, 243, 244, 246))) { + e.Graphics.FillPath(brush, path); + } + e.Graphics.SmoothingMode = previous; + } + + protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) { + ToolStripMenuItem menuItem = e.Item as ToolStripMenuItem; + int rightInset = menuItem != null && menuItem.HasDropDownItems ? 36 : 12; + Rectangle bounds = new Rectangle( + 16, + 0, + Math.Max(1, e.Item.Width - 16 - rightInset), + e.Item.Height + ); + Color color = e.Item.Enabled + ? e.Item.ForeColor + : Color.FromArgb(255, 146, 151, 159); + TextRenderer.DrawText( + e.Graphics, + e.Text, + e.TextFont, + bounds, + color, + TextFormatFlags.Left | + TextFormatFlags.VerticalCenter | + TextFormatFlags.SingleLine | + TextFormatFlags.NoPrefix + ); + } + + protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) { + int y = e.Item.Height / 2; + using (Pen pen = new Pen(Color.FromArgb(255, 218, 228, 242), 1.0f)) { + e.Graphics.DrawLine(pen, 0, y, Math.Max(0, e.Item.Width), y); + } + } + + protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { + int radius = Math.Max(10, (int)Math.Round(14.0 * e.ToolStrip.DeviceDpi / 96.0)); + Rectangle bounds = new Rectangle( + 0, + 0, + Math.Max(1, e.ToolStrip.Width - 1), + Math.Max(1, e.ToolStrip.Height - 1) + ); + SmoothingMode previous = e.Graphics.SmoothingMode; + e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; + using (GraphicsPath path = RoundedRectangle(bounds, radius)) + using (Pen pen = new Pen(Color.FromArgb(255, 218, 222, 229), 1.0f)) { + e.Graphics.DrawPath(pen, path); + } + e.Graphics.SmoothingMode = previous; + } + + protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e) { + int centerX = e.ArrowRectangle.Left + (e.ArrowRectangle.Width / 2); + int centerY = e.ArrowRectangle.Top + (e.ArrowRectangle.Height / 2); + Color color = e.Item.Enabled + ? Color.FromArgb(255, 91, 97, 105) + : Color.FromArgb(255, 183, 188, 196); + SmoothingMode previous = e.Graphics.SmoothingMode; + e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; + using (Pen pen = new Pen(color, 1.6f)) { + pen.StartCap = LineCap.Round; + pen.EndCap = LineCap.Round; + e.Graphics.DrawLines(pen, new Point[] { + new Point(centerX - 2, centerY - 4), + new Point(centerX + 2, centerY), + new Point(centerX - 2, centerY + 4) + }); + } + e.Graphics.SmoothingMode = previous; + } + + protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) { + Rectangle box = new Rectangle(e.ImageRectangle.Left + 3, e.ImageRectangle.Top + 3, 16, 16); + SmoothingMode previous = e.Graphics.SmoothingMode; + e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; + using (SolidBrush brush = new SolidBrush(Color.FromArgb(255, 37, 99, 235))) + using (GraphicsPath path = RoundedRectangle(box, 5)) + using (Pen pen = new Pen(Color.White, 1.8f)) { + pen.StartCap = LineCap.Round; + pen.EndCap = LineCap.Round; + e.Graphics.FillPath(brush, path); + e.Graphics.DrawLines(pen, new Point[] { + new Point(box.Left + 4, box.Top + 8), + new Point(box.Left + 7, box.Top + 11), + new Point(box.Left + 12, box.Top + 5) + }); + } + e.Graphics.SmoothingMode = previous; + } + } +} +'@ +} + +function New-DreamSkinTrayIcon { + $bitmap = [System.Drawing.Bitmap]::new( + 32, + 32, + [System.Drawing.Imaging.PixelFormat]::Format32bppArgb + ) + $graphics = [System.Drawing.Graphics]::FromImage($bitmap) + $mark = [System.Drawing.Drawing2D.GraphicsPath]::new() + $paper = $null + $ink = $null + $outline = $null + $dot = $null + try { + $graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias + $graphics.Clear([System.Drawing.Color]::Transparent) + $mark.AddArc(2, 2, 9, 9, 180, 90) + $mark.AddArc(21, 2, 9, 9, 270, 90) + $mark.AddArc(21, 21, 9, 9, 0, 90) + $mark.AddArc(2, 21, 9, 9, 90, 90) + $mark.CloseFigure() + + $paper = [System.Drawing.SolidBrush]::new([System.Drawing.Color]::FromArgb(255, 253, 253, 252)) + $graphics.FillPath($paper, $mark) + $graphics.SetClip($mark) + $ink = [System.Drawing.SolidBrush]::new([System.Drawing.Color]::FromArgb(255, 23, 24, 28)) + $graphics.FillPolygon($ink, [System.Drawing.Point[]]@( + [System.Drawing.Point]::new(30, 2), + [System.Drawing.Point]::new(30, 30), + [System.Drawing.Point]::new(2, 30) + )) + $graphics.ResetClip() + $outline = [System.Drawing.Pen]::new([System.Drawing.Color]::FromArgb(118, 23, 24, 28), 1.1) + $graphics.DrawPath($outline, $mark) + $dot = [System.Drawing.SolidBrush]::new([System.Drawing.Color]::FromArgb(255, 45, 225, 194)) + $graphics.FillEllipse($dot, 20, 6, 6, 6) + + $handle = $bitmap.GetHicon() + try { + $borrowed = [System.Drawing.Icon]::FromHandle($handle) + try { return [System.Drawing.Icon]$borrowed.Clone() } finally { $borrowed.Dispose() } + } finally { + if ($handle -ne [IntPtr]::Zero) { + [void][DreamSkin.NativeMethods]::DestroyIcon($handle) + } + } + } finally { + if ($null -ne $dot) { $dot.Dispose() } + if ($null -ne $outline) { $outline.Dispose() } + if ($null -ne $ink) { $ink.Dispose() } + if ($null -ne $paper) { $paper.Dispose() } + $mark.Dispose() + $graphics.Dispose() + $bitmap.Dispose() + } +} + +function Initialize-DreamSkinTrayMenu { + param([Parameter(Mandatory = $true)][System.Windows.Forms.ContextMenuStrip]$Menu) + $Menu.Renderer = [DreamSkin.TrayRenderer]::new() + $Menu.BackColor = [System.Drawing.Color]::White + $Menu.ForeColor = [System.Drawing.Color]::FromArgb(255, 31, 35, 40) + $Menu.Font = [System.Drawing.Font]::new('Segoe UI', 9.0) + $Menu.Padding = [System.Windows.Forms.Padding]::new(5, 5, 5, 5) + $Menu.AutoSize = $true + $Menu.DropShadowEnabled = $true + $Menu.ShowImageMargin = $false + $Menu.ShowCheckMargin = $false +} + +function Show-DreamSkinTrayError { + param([string]$Message) + [void][System.Windows.Forms.MessageBox]::Show( + $Message, + 'Codex Dream Skin', + [System.Windows.Forms.MessageBoxButtons]::OK, + [System.Windows.Forms.MessageBoxIcon]::Error + ) +} + +function Add-DreamSkinTrayItem { + param( + [Parameter(Mandatory = $true)] + [AllowEmptyCollection()] + [System.Windows.Forms.ToolStripItemCollection]$Items, + [Parameter(Mandatory = $true)][string]$Text, + [AllowNull()][scriptblock]$Action, + [bool]$Enabled = $true, + [bool]$Checked = $false + ) + $displayText = if ($Checked) { "✓ $Text" } else { $Text } + $item = [System.Windows.Forms.ToolStripMenuItem]::new($displayText) + $item.Enabled = $Enabled + $item.Checked = $false + $item.ForeColor = if ($Enabled) { + [System.Drawing.Color]::FromArgb(255, 31, 35, 40) + } else { + [System.Drawing.Color]::FromArgb(255, 146, 151, 159) + } + $item.Padding = [System.Windows.Forms.Padding]::new(8, 4, 8, 4) + $item.Margin = [System.Windows.Forms.Padding]::new(1, 0, 1, 0) + if ($null -ne $Action) { + $item.add_Click({ + try { & $Action } catch { Show-DreamSkinTrayError -Message $_.Exception.Message } + }.GetNewClosure()) + } + [void]$Items.Add($item) + return $item +} + +function Add-DreamSkinTraySection { + param( + [Parameter(Mandatory = $true)] + [AllowEmptyCollection()] + [System.Windows.Forms.ToolStripItemCollection]$Items, + [Parameter(Mandatory = $true)][string]$Text + ) + $label = [System.Windows.Forms.ToolStripLabel]::new($Text) + $label.ForeColor = [System.Drawing.Color]::FromArgb(255, 98, 105, 114) + $label.Padding = [System.Windows.Forms.Padding]::new(11, 6, 11, 2) + $label.Font = [System.Drawing.Font]::new('Segoe UI', 8.25, [System.Drawing.FontStyle]::Regular) + [void]$Items.Add($label) + return $label +} + +function Clear-DreamSkinTrayItems { + param( + [Parameter(Mandatory = $true)] + [AllowEmptyCollection()] + [System.Windows.Forms.ToolStripItemCollection]$Items + ) + $previousItems = @($Items) + $Items.Clear() + foreach ($item in $previousItems) { $item.Dispose() } +} + +if ($SelfTest) { + $testMenu = [DreamSkin.TrayMenu]::new() + $testIcon = $null + try { + Initialize-DreamSkinTrayMenu -Menu $testMenu + $null = Add-DreamSkinTraySection -Items $testMenu.Items -Text 'Dream Skin' + $null = Add-DreamSkinTrayItem -Items $testMenu.Items -Text 'Self test' -Action $null + $testSubmenu = [System.Windows.Forms.ToolStripMenuItem]::new('Themes') + $testDropDown = [DreamSkin.TrayMenu]::new() + Initialize-DreamSkinTrayMenu -Menu $testDropDown + $testSubmenu.DropDown = $testDropDown + $null = Add-DreamSkinTrayItem -Items $testSubmenu.DropDownItems -Text 'Example' -Action $null + [void]$testMenu.Items.Add($testSubmenu) + $testMenu.PerformLayout() + $null = $testMenu.Handle + if ( + $testMenu.Items.Count -ne 3 -or + $testMenu.GetType().FullName -cne 'DreamSkin.TrayMenu' -or + $testMenu.Renderer.GetType().FullName -cne 'DreamSkin.TrayRenderer' -or + $testSubmenu.DropDown.GetType().FullName -cne 'DreamSkin.TrayMenu' -or + $null -eq $testMenu.Region + ) { + throw 'The styled tray menu did not initialize correctly.' + } + $testIcon = New-DreamSkinTrayIcon + if ($null -eq $testIcon -or $testIcon.Width -ne 32 -or $testIcon.Height -ne 32) { + throw 'The Dream Skin tray fallback icon was not created at 32 x 32.' + } + Write-Host 'PASS: branded tray icon and styled empty context menu.' + } finally { + if ($null -ne $testIcon) { $testIcon.Dispose() } + $testMenu.Dispose() + } + exit 0 +} + Assert-DreamSkinPort -Port $Port $SkillRoot = Split-Path -Parent $PSScriptRoot $StateRoot = Join-Path $env:LOCALAPPDATA 'CodexDreamSkin' @@ -33,23 +432,15 @@ try { $trayIcon = [System.Drawing.Icon]::new($iconPath) $notify.Icon = $trayIcon } else { - $notify.Icon = [System.Drawing.SystemIcons]::Application + $trayIcon = New-DreamSkinTrayIcon + $notify.Icon = $trayIcon } $notify.Text = 'Codex Dream Skin' $notify.Visible = $true - $menu = [System.Windows.Forms.ContextMenuStrip]::new() + $menu = [DreamSkin.TrayMenu]::new() + Initialize-DreamSkinTrayMenu -Menu $menu $notify.ContextMenuStrip = $menu - function Show-DreamSkinTrayError { - param([string]$Message) - [void][System.Windows.Forms.MessageBox]::Show( - $Message, - 'Codex Dream Skin', - [System.Windows.Forms.MessageBoxButtons]::OK, - [System.Windows.Forms.MessageBoxIcon]::Error - ) - } - function Start-DreamSkinPowerShell { param([Parameter(Mandatory = $true)][string]$Script, [string[]]$Arguments = @()) $scriptToken = ConvertTo-DreamSkinProcessArgument -Value $Script @@ -58,28 +449,6 @@ try { Start-Process -FilePath $powershell -ArgumentList $argumentLine -WindowStyle Hidden | Out-Null } - function Add-DreamSkinTrayItem { - param( - [Parameter(Mandatory = $true)] - [AllowEmptyCollection()] - [System.Windows.Forms.ToolStripItemCollection]$Items, - [Parameter(Mandatory = $true)][string]$Text, - [AllowNull()][scriptblock]$Action, - [bool]$Enabled = $true, - [bool]$Checked = $false - ) - $item = [System.Windows.Forms.ToolStripMenuItem]::new($Text) - $item.Enabled = $Enabled - $item.Checked = $Checked - if ($null -ne $Action) { - $item.add_Click({ - try { & $Action } catch { Show-DreamSkinTrayError -Message $_.Exception.Message } - }.GetNewClosure()) - } - [void]$Items.Add($item) - return $item - } - function Set-DreamSkinAutoStart { param([Parameter(Mandatory = $true)][bool]$Enabled) if (-not $Enabled) { @@ -96,17 +465,33 @@ try { } function Rebuild-DreamSkinTrayMenu { - $menu.Items.Clear() + Clear-DreamSkinTrayItems -Items $menu.Items $paused = Test-DreamSkinPaused -StateRoot $StateRoot $state = $null try { $state = Read-DreamSkinState -Path $paths.State } catch {} $active = $null try { $active = Read-DreamSkinTheme -ThemeDirectory $paths.Active -SkipImageMetadata } catch {} - $status = if ($paused) { '状态:已暂停' } elseif ($state) { '状态:运行中' } else { '状态:未运行' } + $status = if ($paused) { '已暂停' } elseif ($state) { '运行中' } else { '未运行' } if ($null -ne $active -and $null -ne $active.Theme -and $active.Theme.name) { $status += " · $($active.Theme.name)" } - $null = Add-DreamSkinTrayItem -Items $menu.Items -Text $status -Action $null -Enabled $false + $brandLabel = [System.Windows.Forms.ToolStripLabel]::new('Codex Dream Skin') + $brandLabel.ForeColor = [System.Drawing.Color]::FromArgb(255, 31, 35, 40) + $brandLabel.Padding = [System.Windows.Forms.Padding]::new(11, 8, 11, 1) + $brandLabel.Font = [System.Drawing.Font]::new('Segoe UI', 9.25, [System.Drawing.FontStyle]::Regular) + [void]$menu.Items.Add($brandLabel) + + $statusLabel = [System.Windows.Forms.ToolStripLabel]::new($status) + $statusLabel.ForeColor = if ($paused) { + [System.Drawing.Color]::FromArgb(255, 145, 98, 32) + } elseif ($state) { + [System.Drawing.Color]::FromArgb(255, 22, 130, 92) + } else { + [System.Drawing.Color]::FromArgb(255, 190, 48, 48) + } + $statusLabel.Padding = [System.Windows.Forms.Padding]::new(11, 1, 11, 7) + $statusLabel.Font = [System.Drawing.Font]::new('Segoe UI', 8.25, [System.Drawing.FontStyle]::Regular) + [void]$menu.Items.Add($statusLabel) [void]$menu.Items.Add([System.Windows.Forms.ToolStripSeparator]::new()) $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '应用或重新应用' -Action { @@ -186,6 +571,12 @@ try { } $savedMenu = [System.Windows.Forms.ToolStripMenuItem]::new('已保存主题') + $savedMenu.ForeColor = [System.Drawing.Color]::FromArgb(255, 31, 35, 40) + $savedMenu.Padding = [System.Windows.Forms.Padding]::new(8, 4, 8, 4) + $savedMenu.Margin = [System.Windows.Forms.Padding]::new(1, 0, 1, 0) + $savedDropDown = [DreamSkin.TrayMenu]::new() + Initialize-DreamSkinTrayMenu -Menu $savedDropDown + $savedMenu.DropDown = $savedDropDown $savedThemes = @(Get-DreamSkinSavedThemes -StateRoot $StateRoot -SkipImageMetadata) if ($savedThemes.Count -eq 0) { $empty = [System.Windows.Forms.ToolStripMenuItem]::new('暂无已保存主题') @@ -205,16 +596,16 @@ try { } [void]$menu.Items.Add($savedMenu) + [void]$menu.Items.Add([System.Windows.Forms.ToolStripSeparator]::new()) $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '打开图片文件夹' -Action { $imageDirectoryToken = ConvertTo-DreamSkinProcessArgument -Value $paths.Images Start-Process -FilePath explorer.exe -ArgumentList $imageDirectoryToken | Out-Null } - [void]$menu.Items.Add([System.Windows.Forms.ToolStripSeparator]::new()) $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '检查更新…' -Action { Start-DreamSkinPowerShell -Script $checkUpdateScript -Arguments @('-Interactive') } - $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '打开 DreamSkin.cc' -Action { - Start-Process -FilePath 'https://dreamskin.cc' | Out-Null + $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '打开 DreamSkin Studio' -Action { + Start-Process -FilePath 'https://www.dreamskin.cc/studio' | Out-Null } $autoStartEnabled = Test-Path -LiteralPath $startupShortcut -PathType Leaf $autoStartAction = { @@ -223,13 +614,17 @@ try { $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '登录时启动' ` -Action $autoStartAction -Checked $autoStartEnabled [void]$menu.Items.Add([System.Windows.Forms.ToolStripSeparator]::new()) + $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '停止 Dream Skin' -Action { + Start-DreamSkinPowerShell -Script $restoreScript -Arguments @( + '-Port', "$Port", '-PromptRestart' + ) + } $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '完全恢复 Codex' -Action { Start-DreamSkinPowerShell -Script $restoreScript -Arguments @( '-Port', "$Port", '-RestoreBaseTheme', '-PromptRestart' ) - $notify.Visible = $false - [System.Windows.Forms.Application]::Exit() } + [void]$menu.Items.Add([System.Windows.Forms.ToolStripSeparator]::new()) $null = Add-DreamSkinTrayItem -Items $menu.Items -Text '退出托盘' -Action { $notify.Visible = $false [System.Windows.Forms.Application]::Exit() @@ -247,7 +642,10 @@ try { }) [System.Windows.Forms.Application]::Run() } finally { - if ($null -ne $notify) { $notify.Dispose() } + if ($null -ne $notify) { + $notify.Visible = $false + $notify.Dispose() + } if ($null -ne $trayIcon) { $trayIcon.Dispose() } if ($acquired) { try { $mutex.ReleaseMutex() } catch {} } $mutex.Dispose() diff --git a/windows/tests/run-tests.ps1 b/windows/tests/run-tests.ps1 index 1667165d..cea4dd79 100644 --- a/windows/tests/run-tests.ps1 +++ b/windows/tests/run-tests.ps1 @@ -945,6 +945,9 @@ try { '--ds-immersive-composer', 'background-position: var(--ds-art-position)', 'html[data-dream-skin="active"]', + '@property --ds-route-progress', + '[data-dream-route-phase="prepare"]', + 'opacity: var(--ds-route-progress)', 'main.main-surface:has([role="main"])', 'main.main-surface:not(:has([role="main"]))' )) { @@ -968,7 +971,17 @@ try { throw 'macOS and Windows selector contract assets are not byte-identical.' } $traySource = Read-DreamSkinUtf8File -Path (Join-Path $Root 'scripts\tray-dream-skin.ps1') - foreach ($requiredTrayAction in @('System.Windows.Forms.NotifyIcon', '暂停皮肤', '继续显示皮肤', '更换背景图', '已保存主题', '完全恢复 Codex')) { + foreach ($requiredTrayAction in @( + 'System.Windows.Forms.NotifyIcon', + 'DreamSkin.TrayRenderer', + 'New-DreamSkinTrayIcon', + '暂停皮肤', + '继续显示皮肤', + '更换背景图', + '已保存主题', + '停止 Dream Skin', + '完全恢复 Codex' + )) { if (-not $traySource.Contains($requiredTrayAction)) { throw "Tray action is missing: $requiredTrayAction" } } if (-not $traySource.Contains('Invoke-DreamSkinLiveRemove') -or @@ -1015,7 +1028,7 @@ try { -not $traySource.Contains('Get-DreamSkinSavedThemes -StateRoot $StateRoot -SkipImageMetadata')) { throw 'Tray menu metadata enumeration still performs full image parsing on every open.' } - foreach ($requiredReleaseAction in @('check-update.ps1', '检查更新', '打开 DreamSkin.cc', '登录时启动')) { + foreach ($requiredReleaseAction in @('check-update.ps1', '检查更新', '打开 DreamSkin Studio', '登录时启动')) { if (-not $traySource.Contains($requiredReleaseAction)) { throw "Tray release action is missing: $requiredReleaseAction" } @@ -1036,6 +1049,7 @@ try { if ($null -eq $addTrayItemAst) { throw 'Tray item helper could not be loaded for an empty-menu behavior check.' } Invoke-Expression $addTrayItemAst.Extent.Text Add-Type -AssemblyName System.Windows.Forms + Add-Type -AssemblyName System.Drawing $emptyMenu = [System.Windows.Forms.ContextMenuStrip]::new() try { $probeItem = Add-DreamSkinTrayItem -Items $emptyMenu.Items -Text 'first-item-probe' -Action $null -Enabled $false @@ -1045,6 +1059,21 @@ try { } finally { $emptyMenu.Dispose() } + $traySelfTest = Invoke-DreamSkinNative -FilePath ( + (Get-Command powershell.exe -ErrorAction Stop).Source + ) -ArgumentList @( + '-NoProfile', + '-STA', + '-ExecutionPolicy', + 'RemoteSigned', + '-File', + (Join-Path $Root 'scripts\tray-dream-skin.ps1'), + '-SelfTest' + ) + if ($traySelfTest.ExitCode -ne 0 -or + ($traySelfTest.Output -join "`n") -notmatch 'PASS: branded tray icon and styled empty context menu') { + throw "Tray icon/menu self-test failed: $($traySelfTest.Output -join '')" + } $restoreSource = Read-DreamSkinUtf8File -Path (Join-Path $Root 'scripts\restore-dream-skin.ps1') if (-not $restoreSource.Contains('Stop-DreamSkinTrayProcess')) { throw 'Complete restore does not stop a separately launched tray process.' @@ -1058,6 +1087,28 @@ try { -not $startSource.Contains('Start-DreamSkinCodex -Codex $codex')) { throw 'Start still executes the WindowsApps path instead of activating the registered package.' } + $activeMessageIndex = $startSource.IndexOf( + 'Write-Host "Codex Dream Skin is active on verified loopback port $Port."', + [System.StringComparison]::Ordinal + ) + $trayBackgroundIndex = $startSource.IndexOf( + 'Start-DreamSkinTrayInBackground -TrayPort $Port', + [System.StringComparison]::Ordinal + ) + foreach ($requiredTrayLaunchToken in @( + 'function Start-DreamSkinTrayInBackground', + 'Test-DreamSkinTrayActive', + "Join-Path `$PSScriptRoot 'tray-dream-skin.ps1'", + '-NoProfile -STA -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File', + 'Start-Process -FilePath $powershell -ArgumentList $trayArguments -WindowStyle Hidden' + )) { + if (-not $startSource.Contains($requiredTrayLaunchToken)) { + throw "Start no longer detaches the tray safely after launch: $requiredTrayLaunchToken" + } + } + if ($activeMessageIndex -lt 0 -or $trayBackgroundIndex -le $activeMessageIndex) { + throw 'Start launches the tray before the skin has completed verification.' + } $stateReadIndex = $startSource.IndexOf('$previousState = Read-DreamSkinState', [System.StringComparison]::Ordinal) $restartPromptIndex = $startSource.IndexOf('$restartAuthorized = Confirm-DreamSkinRestart', [System.StringComparison]::Ordinal) $recordedStopIndex = $startSource.IndexOf('$recordedInjectorStopped = Stop-DreamSkinRecordedInjector', [System.StringComparison]::Ordinal) @@ -1105,7 +1156,8 @@ try { $rendererSource = Read-DreamSkinUtf8File -Path (Join-Path $Root 'assets\renderer-inject.js') foreach ($requiredRendererBehavior in @( 'adoptedStyleSheets', 'CSSStyleSheet', 'artMetadata', 'detectShellAppearance', - 'data-dream-skin', 'window.navigation', 'selectorsSchema', 'codex-dream-skin-selectors/1' + 'data-dream-skin', 'window.navigation', 'selectorsSchema', 'codex-dream-skin-selectors/1', + 'beginRouteTransition', 'data-dream-route-phase', 'requestAnimationFrame' )) { if (-not $rendererSource.Contains($requiredRendererBehavior)) { throw "Renderer adaptive behavior is missing: $requiredRendererBehavior" From 9a1494929ef2d96d29682fc13d4b288ffa75ac4e Mon Sep 17 00:00:00 2001 From: EnderXie23 <3142007828@qq.com> Date: Thu, 23 Jul 2026 01:29:01 -0700 Subject: [PATCH 2/2] docs(windows): add tray menu preview --- windows/references/tray-menu-preview.png | Bin 0 -> 93798 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 windows/references/tray-menu-preview.png diff --git a/windows/references/tray-menu-preview.png b/windows/references/tray-menu-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..826034942c5cd26176788008747ebf0447c85781 GIT binary patch literal 93798 zcmc$_Rd5|Wur6whnVD&MnVFfHneCVxVVu(3rX6CceDuL!}uQ*k_rHxQM!^;n{|VE8(H> z<@@Euw@dA_;zvW7;BGa5gqzNW&4uC)@RI5X#>$ALQhPE9g`AC6-k9IUcy2?hr8_< z>d7CZ&nQ)r>(@aF+fTAbBsM-9iIFB7q*^3gl$Z$Man3@_k{>ps?tHq0;VOd* zzM5wAm(YJJmj<8%q!U5y4Pl6vsEBS;CrM+B87U(jSc2e|Ip<#-^ zoKq!-?RSk554NIL1hC?%GRDg_>WWuKlfnkH(S>71OoYf*30JF7jO}OW%7G@f7D$|c z0WWn8BPtA0CK@zWnPVW23S~UKiLDCc_iwVHOcoVo!~mB-4Q-DZ!2rz;#4qM;=~Pet zc!3rE&P)&~xuces%5+%NnDBGKpuT;88A^&en$>BQ>hLU@3aFt%qh;x-a0w*MszH(^ z*#?rRP}>4AlBOBD>X`6wjYltNpnNi9Y$w0fqO3Y?{d5p1>?I0_z~A3hr~xMRxb}4c z?r0*Yp&kGjWg4s$Q{}-kA`#S0D%LDSP%Rajq&?@ikJ&TwV9 zA&TdY_8J4lr9qz=jP9EdL4vvp8iPrd9o=IEH7(Cj&D7x!+9TPmHQcX<4Dhk@Zsj=- z9Zs>Qnn_tn;^pq{JljfC$g#5?JsAfjkhse=oe7Z(sotxt-|QgT4cAu+$3AoTHcmUk&YJJ@h$VZo<(vv zk2_B>SCNF+0W(W7N}ufT{q!e1o$cox`@ZHbz}dbzOXQpJ-aO#@T0*^`m14~>4dOml0!gK-43?TzE?I(@%`m*yPjQnVkK)_xyehC9!w`7zg zHpKynC3#{W!SCd6i$xkTqq}Oa1I}G=L{&hJ?AH6`(7;>5ry=moCmpuq&sUc8I(p;9 zA?(~=Y_Ut-V?qLMnS!U@(e^Lo1qMYG)I9O@*d`{UQu<_KwQA_DUa%ur0QE25#=M(o z@fx&oKieQ3NJE)uAycgozr@O5yTU7v28t7k+JnT{F#j((Eno`Wtgb5a5j(C%3Ik?P z6qunUSeS$uJ3iUb0~$0YFPp9!y2bjFU&g7*@uZc)Smt73m+n?>C!WWl|HoD@=k`pk z@p(ysnH_6s6&W$|F1I^j#IHb0CoD?#S?+2|^BNAxQGw`XoL?AoCNdfn3F2@GFiFWZ zR<7vyqHR*ZIt^A@xQ?#S0W=dJ@k`&2+ zBF$J?x)>a=EB*El;m%N7Rg30 z+XS^6!(%u-11UbuV~n7_o%`nBXNv6

{Q$DjWu3*C z8nXizmI%KmzdgMu`QOkPdY9xAojbE4B-aCj zCfBB}EBr_0X7~pZj67rP9P-OH=%fs_;}wv2;UZs({HXX^dir*i-qP(HF21hi@cn82 zq!!4AS1-qer&lRVx$Q*0TJ>n1uXA$Tc@i=F_%-9TJw=pD7|U#5OYUMuHL~TM6!7%x z_ctFG7)zM`*tPUz)X421ih!7Gmm12ak#TTB|(>Z<^*v8=PR za<|*yv8P%oNjb9RdnJA&k6!Q3d2dHUXbbz`U$RgBeCFBRRUD8t1~JU_J$(KdKUQnL zJ0|S9ZmjS;KF0C%dIaxSETf)0#*B8N3s7gxigo0U9>Eb#k3@wJiB;9Ws*52S`G`mC=iI+@)mN zXjxgB$)81!Ejw`|#}r}wF<(k_vuOhocPsG!ED};ym1Y+wtI9gh%V=>sd7%8}08+TU z+uX3$lx`bWK5!r}wzxPBiW=+in0v{XY40E^9jR2ao0;1rNsZtgU6gemL!5NcBA!r( zM*$yt-1Fm=(aR;$=qFf>=cvoKt~w(yWy18!ewo~`F6@`S4}xWJlmS-Ik0A00ecXla z-wjvGFz3%WZ)9bu>FEnQ{)C%!Wo=^Ud3Do7YZXitpQysCnU7K;y;IOO%)4dA!ojv% z3Hb$qClG4bqftUbW3FkK(E_cGxlpyNM;TiSEdui~EO{PIRCF;p$$9A{psn|gx9AX%z z3KXl=EK#OWL6e%M_B-@p48zR%7185EqIa5ym?Gk)0j+@mfUpx_?^+5q8FD`3!Jpq3 zAPleQiQD)S?ED;$dXI;`mbIvWSa}mD3SgG~tUq69_OY(t97940$Y%<;M|{>_kx>w5*h?+ z{E2JldMz|MV)@B<>3~R zd|2Di?ZmTb8WZ z5;X%N>*J+5;p&f(Uuthx8KU{A*QzanRZO4|I4ThTcAlqFGN(D%hvXT;=xq;}PUT}2 zuxo8-w~R{Lku^g643XgH%trTZw(*^T5s?SCXZ0s!Gqi*%`2I0CW-ajH8{gnq2N1vW z%MqdLE}VqdT2&MjlmWMQb|s%*B(Dy~SoP&!x`N*LG#<^f#)%X#-&h}$CZtsz&)?m? zJ1&p6Lww(7-I|#V^@LtQdf@1>>(1>nNEHXE;N(fLb5`o~S3uZ)%3G$=CtqB7@Ib44uI;lr!=~3sl=h`$(?KoVpv^nwZDUYAr90}1b42Ulfh-~3oTjTYR;EDT= zw;R>e(wxR%fSUADb2=JE`l2t)V1G#oFAB?kg(@13#+}Mav)YPSikVN8=&ytfZz-jS zDUzCywVII8IT%P)Hs`$%@$q;+z4Q9HQ)2UxIO+yY#|3WrX zUM#YgwZo*bj1C^c_`Gl}l$;>V7ig^dTg1*TM9-$mrepezhF}Rfxu4*)fqQ1DW#;Nf z!KGi;W8+1*5x)x8jG1o4(do2zLFI@B(e@@T+^K3-yR@0>&>&3AQ-x^wgI676+w2Ss z>Km_Xy(>3UH}lYc9F_RK{W^V8-DW}lI5B!&`@ApkeUFIX-aPkx{fy9t?RaqRuuCN2 zZFO8*9pZ1}H+8SF-V4m@+L5&na1@}#(~OnTEWLprM>K}d%=8O(L>e?<(PzZ*?+th$ z1L^IPQ@x4B>g3Bdb7T7{LaCRu^8DC?`|QPwx-|5xrn9orf%?g_E2_-jh56=YGU;OJ zP|2_ncJR51=j7A56w@-sC{uxKym`dCW!H4ZJ5EggbvZ@lY`JSMbpH2SLiTh_k!M+cBe&l&Mz92+}l$vSH;xU%%#xec;p5x@f0biVNAwPhLue=%ax(~8%hH<6tpYqg=7;9T!ZS6FVWnwOP0 z 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 literal 0 HcmV?d00001