From 6c26ac0b28e42dc9c82fba1030573bdbbbf497f7 Mon Sep 17 00:00:00 2001 From: mycyg Date: Thu, 2 Jul 2026 22:18:20 +0800 Subject: [PATCH 01/10] =?UTF-8?q?fix(desktop):=20remove=20fake=20spotlight?= =?UTF-8?q?=20resize=20handles=20=E5=BE=85=E7=9C=9F=E6=9C=BA=E9=AA=8C?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/desktop-webview/src/browser.ts | 17 +----------- apps/desktop-webview/src/main.test.ts | 18 ++++++------- .../src/spotlight/controller.ts | 26 +------------------ .../desktop-webview/src/spotlight/css.test.ts | 10 +++++-- apps/desktop-webview/src/spotlight/css.ts | 6 +---- .../rust-system-i18n-report.json | 10 +++---- .../smoke-summary.md | 2 +- 7 files changed, 25 insertions(+), 64 deletions(-) diff --git a/apps/desktop-webview/src/browser.ts b/apps/desktop-webview/src/browser.ts index 4f0281850..394fc2e26 100644 --- a/apps/desktop-webview/src/browser.ts +++ b/apps/desktop-webview/src/browser.ts @@ -89,7 +89,6 @@ import { glassWindowCss } from "./glass-window.js"; import { mountSpotlight, type SpotlightManualDragFn, - type SpotlightResizeDirection, type SpotlightResizeFn } from "./spotlight/controller.js"; import { spotlightCss } from "./spotlight/css.js"; @@ -1120,7 +1119,7 @@ const resizeMainWindow: SpotlightResizeFn = (width, height) => { } }; -// 搜索条像系统 Spotlight 一样可拖动,边缘热区可缩放;浏览器开发态无 __TAURI__ → no-op。 +// 搜索条像系统 Spotlight 一样可拖动;浏览器开发态无 __TAURI__ → no-op。 const dragMainWindow = (): void => { const tauri = (globalThis as { __TAURI__?: { @@ -1147,19 +1146,6 @@ const moveMainWindowBy: SpotlightManualDragFn = (deltaX, deltaY): void => { } }; -const resizeMainWindowFromEdge = (direction: SpotlightResizeDirection): void => { - const tauri = (globalThis as { - __TAURI__?: { - core?: { invoke?: (cmd: string, args?: Record) => Promise }; - invoke?: (cmd: string, args?: Record) => Promise; - }; - }).__TAURI__; - const invoke = tauri?.core?.invoke ?? tauri?.invoke; - if (typeof invoke === "function") { - void invoke("start_main_window_resize_drag", { direction }).catch(() => undefined); - } -}; - // M2:launcher 顶层 Esc → 隐藏主窗(关闭盒子),兑现 hello 卡「Esc 关闭」承诺。浏览器开发态无 __TAURI__ → no-op。 const dismissMainWindow = (): void => { const tauri = (globalThis as { @@ -1252,7 +1238,6 @@ async function bootSpotlight() { resize: resizeMainWindow, drag: dragMainWindow, dragMove: moveMainWindowBy, - resizeDrag: resizeMainWindowFromEdge, dismiss: dismissMainWindow, onActionSettled: () => { void refreshApprovalsBadge(); diff --git a/apps/desktop-webview/src/main.test.ts b/apps/desktop-webview/src/main.test.ts index 214bcbc29..8e43dd4e1 100644 --- a/apps/desktop-webview/src/main.test.ts +++ b/apps/desktop-webview/src/main.test.ts @@ -771,10 +771,12 @@ test("Spotlight exposes native move and resize gestures instead of a fixed top s const source = readFileSync(new URL("./spotlight/controller.ts", import.meta.url), "utf8"); const browserSource = readFileSync(new URL("./browser.ts", import.meta.url), "utf8"); + // 3-1: the old assertions required invisible resize handles, but those handles were not backed by + // durable resize state and render-driven auto-resize could overwrite the user's dragged size. assert.match(source, /export type SpotlightManualDragFn = \(deltaX: number, deltaY: number\) => void/u); assert.match(source, /drag\?: \(\) => void/u); assert.match(source, /dragMove\?: SpotlightManualDragFn/u); - assert.match(source, /resizeDrag\?: \(direction: SpotlightResizeDirection\) => void/u); + assert.doesNotMatch(source, /resizeDrag\?:/u); assert.match(source, /renderWorkHubLiquidGlassLayer\("spotlight"\)/u); assert.match(source, /class="wh-spot ds-anim-spring-in"/u); // 盒子自己在 css.ts 里持有液态玻璃(渐变白底 + backdrop blur),不再借用扁平的 ds-glass-strong 工具类。 @@ -783,14 +785,14 @@ test("Spotlight exposes native move and resize gestures instead of a fixed top s assert.match(source, /class="wh-spot-drag-sheet" data-spot-drag-sheet/u); assert.match(source, /class="wh-spot-field" type="search" data-spot-input role="combobox"/u); assert.doesNotMatch(source, /data-tauri-drag-region/u); - assert.match(source, /data-spot-resize="south-east"/u); + assert.doesNotMatch(source, /data-spot-resize/u); assert.match(source, /focusSearch\(\{ expand: false \}\)/u); assert.match(source, /suppressNextFocusExpansion = !options\.expand/u); assert.match(source, /if \(suppressNextFocusExpansion \|\| nowMs\(\) < suppressSearchFocusUntil\) \{\s*suppressNextFocusExpansion = false;\s*\}/u); - assert.match(source, /const dragExcludedSelector = "button,a,select,\[contenteditable=true\],\[data-spot-resize\]"/u); + assert.match(source, /const dragExcludedSelector = "button,a,select,\[contenteditable=true\]"/u); assert.match(source, /Boolean\(target\.closest\(dragExcludedSelector\)\)/u); assert.doesNotMatch(source, /dragExcludedSelector = "input,textarea,button/u); - assert.match(source, /let userResizeAutoUnlockAt = 0/u); + assert.doesNotMatch(source, /userResizeAutoUnlockAt/u); assert.match(source, /let suppressSearchFocusUntil = 0/u); assert.match(source, /let suppressSearchClickUntil = 0/u); assert.match(source, /const resetLauncher = \(\) => \{/u); @@ -803,7 +805,6 @@ test("Spotlight exposes native move and resize gestures instead of a fixed top s assert.match(source, /reset: \(\) => \{\s*resetLauncher\(\);\s*\}/u); assert.match(source, /nowMs\(\) < suppressSearchFocusUntil/u); assert.match(source, /nowMs\(\) < suppressSearchClickUntil/u); - assert.match(source, /userResizeAutoUnlockAt = nowMs\(\) \+ 1600/u); assert.match(source, /suppressSearchFocusUntil = nowMs\(\) \+ 700/u); assert.match(source, /suppressSearchClickUntil = nowMs\(\) \+ 900/u); assert.match(source, /suppressSearchClickUntil = nowMs\(\) \+ 700/u); @@ -829,11 +830,8 @@ test("Spotlight exposes native move and resize gestures instead of a fixed top s assert.notEqual(pointerMoveStart, -1); const pointerDownSource = source.slice(pointerDownStart, pointerMoveStart); assert.doesNotMatch(pointerDownSource, /input\.drag\(\)/u); - assert.match(source, /if \(now < userResizeAutoUnlockAt\) \{\s*userResizeAutoUnlockAt = now \+ 700;\s*return;\s*\}/u); assert.match(source, /input\.drag\?\.\(\)/u); - assert.match(source, /input\.resizeDrag\?\.\(direction\)/u); - assert.match(source, /const requestResizeFromWindowResize = \(\) => \{\s*scheduleWorkHubLiquidGlassFilterRebuild\(doc\);\s*const now = nowMs\(\);/u); - assert.match(source, /input\.resizeDrag\?\.\(direction\);\s*scheduleWorkHubLiquidGlassFilterRebuild\(doc\);/u); + assert.match(source, /const requestResizeFromWindowResize = \(\) => \{\s*scheduleWorkHubLiquidGlassFilterRebuild\(doc\);\s*requestResize\(\);\s*\};/u); const mouseMoveStart = source.indexOf('"mousemove"'); const mouseUpStart = source.indexOf('"mouseup"', mouseMoveStart); assert.notEqual(mouseMoveStart, -1); @@ -854,7 +852,7 @@ test("Spotlight exposes native move and resize gestures instead of a fixed top s assert.match(browserSource, /const moveMainWindowBy: SpotlightManualDragFn = \(deltaX, deltaY\): void =>/u); assert.match(browserSource, /invoke\("move_main_window_by", \{ deltaX, deltaY \}\)/u); assert.match(browserSource, /invoke\("start_main_window_drag"\)/u); - assert.match(browserSource, /invoke\("start_main_window_resize_drag", \{ direction \}\)/u); + assert.doesNotMatch(browserSource, /start_main_window_resize_drag/u); }); test("desktop offline settings edit the API base locally instead of navigating to a dead settings route", () => { diff --git a/apps/desktop-webview/src/spotlight/controller.ts b/apps/desktop-webview/src/spotlight/controller.ts index b9b37ad88..9d3f1cd3c 100644 --- a/apps/desktop-webview/src/spotlight/controller.ts +++ b/apps/desktop-webview/src/spotlight/controller.ts @@ -20,7 +20,6 @@ import type { SpotlightApiClient, SpotlightTarget, SpotlightViewContext } from " export type SpotlightResizeFn = (width: number, height: number) => void; export type SpotlightManualDragFn = (deltaX: number, deltaY: number) => void; -export type SpotlightResizeDirection = "east" | "south" | "south-east"; export type MountSpotlightInput = { host: HTMLElement; @@ -33,7 +32,6 @@ export type MountSpotlightInput = { // 顶栏拖动/边缘缩放(browser.ts 注入 → 原生 frameless 窗口手势)。浏览器开发态可为空(no-op)。 drag?: () => void; dragMove?: SpotlightManualDragFn; - resizeDrag?: (direction: SpotlightResizeDirection) => void; // 关闭/隐藏盒子(browser.ts 注入 → invoke hide_main_window)。M2:让 launcher 顶层 Esc 真正关闭盒子, // 兑现 hello 卡「Esc 关闭」的承诺。浏览器开发态可为空(no-op)。 dismiss?: () => void; @@ -135,9 +133,6 @@ export function mountSpotlight(input: MountSpotlightInput): SpotlightHandle {
- - - `; const box = host.querySelector("[data-spot-box]")!; @@ -155,7 +150,6 @@ export function mountSpotlight(input: MountSpotlightInput): SpotlightHandle { let resizeRaf = 0; let lastSentW = 0; let lastSentH = 0; - let userResizeAutoUnlockAt = 0; const nowMs = () => window.performance.now(); const focusSearch = (options: { expand: boolean }) => { if (options.expand) { @@ -206,11 +200,6 @@ export function mountSpotlight(input: MountSpotlightInput): SpotlightHandle { }; const requestResizeFromWindowResize = () => { scheduleWorkHubLiquidGlassFilterRebuild(doc); - const now = nowMs(); - if (now < userResizeAutoUnlockAt) { - userResizeAutoUnlockAt = now + 700; - return; - } requestResize(); }; @@ -436,7 +425,7 @@ export function mountSpotlight(input: MountSpotlightInput): SpotlightHandle { dispatch({ type: "back" }); }); - const dragExcludedSelector = "button,a,select,[contenteditable=true],[data-spot-resize]"; + const dragExcludedSelector = "button,a,select,[contenteditable=true]"; const isDragExcludedTarget = (target: EventTarget | null) => target instanceof Element && Boolean(target.closest(dragExcludedSelector)); let manualDrag: | { @@ -644,19 +633,6 @@ export function mountSpotlight(input: MountSpotlightInput): SpotlightHandle { topEl.addEventListener("pointerup", clearDragStart); topEl.addEventListener("pointercancel", clearDragStart); - host.querySelectorAll("[data-spot-resize]").forEach((handle) => { - handle.addEventListener("pointerdown", (event) => { - event.preventDefault(); - event.stopPropagation(); - const direction = handle.dataset.spotResize as SpotlightResizeDirection | undefined; - if (direction) { - userResizeAutoUnlockAt = nowMs() + 1600; - input.resizeDrag?.(direction); - scheduleWorkHubLiquidGlassFilterRebuild(doc); - } - }); - }); - body.addEventListener("click", (event) => { const target = event.target; if (!(target instanceof HTMLElement)) { diff --git a/apps/desktop-webview/src/spotlight/css.test.ts b/apps/desktop-webview/src/spotlight/css.test.ts index d63334236..027c96c1c 100644 --- a/apps/desktop-webview/src/spotlight/css.test.ts +++ b/apps/desktop-webview/src/spotlight/css.test.ts @@ -67,13 +67,14 @@ test("Spotlight shell keeps a translucent liquid-glass surface", () => { assert.match(css, /\.wh-spot>\.wh-liquid-glass-content\{display:flex;flex-direction:column/u); assert.match(css, /\.wh-spot-top\{[^}]*-webkit-app-region:no-drag;cursor:grab/u); assert.match(css, /\.wh-spot-top:active\{cursor:grabbing\}/u); - assert.match(css, /\.wh-spot-back,\.wh-spot-resize,\.wh-spot button,\.wh-spot a,\.wh-spot select,\.wh-spot textarea,\.wh-spot \[contenteditable=true\]\{-webkit-app-region:no-drag\}/u); + // 3-1: the old assertion included `.wh-spot-resize`, but that pinned a fake manual-resize affordance + // whose dragged size could be overwritten by render-driven auto-resize. + assert.match(css, /\.wh-spot-back,\.wh-spot button,\.wh-spot a,\.wh-spot select,\.wh-spot textarea,\.wh-spot \[contenteditable=true\]\{-webkit-app-region:no-drag\}/u); assert.doesNotMatch(css, /\.wh-spot-top>\*\{-webkit-app-region:no-drag\}/u); assert.doesNotMatch(css, /\.wh-spot-field\{[^}]*-webkit-app-region/u); assert.match(css, /\.wh-spot-drag-sheet\{position:absolute;inset:0;display:none;z-index:3;border:0;background:transparent;cursor:grab/u); assert.match(css, /\.wh-spot\[data-mode="launcher"\]\[data-collapsed="true"\] \.wh-spot-drag-sheet\{display:block\}/u); assert.match(css, /\.wh-spot-drag-sheet:active\{cursor:grabbing\}/u); - assert.match(css, /\.wh-spot-resize\{position:absolute;z-index:4;pointer-events:auto;background:transparent;border:0;padding:0;-webkit-app-region:no-drag\}/u); assert.match(css, /input\.wh-spot-field:focus\{outline:0!important;box-shadow:none!important\}/u); assert.doesNotMatch(css, /\.wh-spot-back\{[^}]*background:var\(--ds-glass\)/u); assert.doesNotMatch( @@ -87,6 +88,11 @@ test("Spotlight shell keeps a translucent liquid-glass surface", () => { assert.doesNotMatch(css, /\.wh-spot \.wh-conflict-head,[^{]+\{[^}]*backdrop-filter/u); }); +test("Spotlight shell does not expose manual resize hit zones without durable resize state", () => { + assert.doesNotMatch(css, /\.wh-spot-resize/u); + assert.doesNotMatch(css, /cursor:(?:ew|ns|nwse)-resize/u); +}); + test("Spotlight launcher cards stay glassy instead of white tiles", () => { assert.match(css, /\.wh-spot\[data-mode="launcher"\] \.wh-spot-cap\{[^}]*background:transparent/u); assert.match(css, /\.wh-spot\[data-mode="launcher"\] \.wh-spot-cap:hover\{[^}]*background:transparent/u); diff --git a/apps/desktop-webview/src/spotlight/css.ts b/apps/desktop-webview/src/spotlight/css.ts index 7293d755b..44342d4c9 100644 --- a/apps/desktop-webview/src/spotlight/css.ts +++ b/apps/desktop-webview/src/spotlight/css.ts @@ -27,14 +27,10 @@ export const spotlightCss = [ ".wh-spot[data-mode=\"launcher\"][data-collapsed=\"true\"] .wh-spot-body{display:none}", ".wh-spot[data-mode=\"launcher\"][data-collapsed=\"true\"] .wh-spot-top{border-bottom:0}", ".wh-spot[data-mode=\"launcher\"][data-collapsed=\"true\"]{height:auto;min-height:0}", - ".wh-spot-resize{position:absolute;z-index:4;pointer-events:auto;background:transparent;border:0;padding:0;-webkit-app-region:no-drag}", - ".wh-spot-resize--e{top:18px;right:0;bottom:18px;width:10px;cursor:ew-resize}", - ".wh-spot-resize--s{left:18px;right:18px;bottom:0;height:10px;cursor:ns-resize}", - ".wh-spot-resize--se{right:0;bottom:0;width:18px;height:18px;cursor:nwse-resize}", // 顶栏:搜索/标题 + 面包屑返回。搜索条本身也是原生 drag region;只有真实按钮/表单控件退出拖动。 ".wh-spot-top{position:relative;display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid var(--ds-glass-hairline);-webkit-app-region:no-drag;cursor:grab}", ".wh-spot-top:active{cursor:grabbing}", - ".wh-spot-back,.wh-spot-resize,.wh-spot button,.wh-spot a,.wh-spot select,.wh-spot textarea,.wh-spot [contenteditable=true]{-webkit-app-region:no-drag}", + ".wh-spot-back,.wh-spot button,.wh-spot a,.wh-spot select,.wh-spot textarea,.wh-spot [contenteditable=true]{-webkit-app-region:no-drag}", ".wh-spot-drag-sheet{position:absolute;inset:0;display:none;z-index:3;border:0;background:transparent;cursor:grab;padding:0;-webkit-app-region:no-drag}", ".wh-spot[data-mode=\"launcher\"][data-collapsed=\"true\"] .wh-spot-drag-sheet{display:block}", ".wh-spot-drag-sheet:active{cursor:grabbing}", diff --git a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json index ba76d6ea2..fabe3497f 100644 --- a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json +++ b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json @@ -1,14 +1,14 @@ { - "generated_at": "2026-06-28T14:09:33.792Z", + "generated_at": "2026-07-02T14:17:03.879Z", "module": "R4.6 Rust system-string i18n", - "output_dir": "/Users/apple/Desktop/开发项目/WorkHub/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n", + "output_dir": "/private/tmp/workhub-r9-codex/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n", "cargo_mode": "executed", "commands": [ { - "command": "cargo test --manifest-path /Users/apple/Desktop/开发项目/WorkHub/client-tauri/src-tauri/Cargo.toml", + "command": "cargo test --manifest-path /private/tmp/workhub-r9-codex/client-tauri/src-tauri/Cargo.toml", "exitCode": 0, - "stdoutTail": "se::tests::plans_contract_stream_paths_without_copying_domain_logic ... ok\ntest sse::tests::status_payloads_use_the_dedicated_sse_status_channel ... ok\ntest sse::tests::startup_targets_subscribe_to_the_per_user_stream_not_the_admin_only_global ... ok\ntest sse::tests::worker_plan_keeps_retry_policy_and_subscription_headers ... ok\ntest sse_worker::tests::byte_pump_holds_partial_frames_until_the_blank_line_arrives ... ok\ntest sse_worker::tests::byte_pump_preserves_multibyte_utf8_split_across_chunks ... ok\ntest sse_worker::tests::default_reconnect_delay_is_small_enough_for_desktop_feedback ... ok\ntest sse_worker::tests::frame_boundary_end_recognizes_every_blank_line_encoding ... ok\ntest sse_worker::tests::reconnect_backoff_is_base_when_healthy_and_caps_at_60s ... ok\ntest tray::tests::keeps_tray_ids_stable_and_unique ... ok\ntest tray::tests::maps_tray_window_actions_to_existing_window_control_contract ... ok\ntest tray::tests::opens_inbox_through_a_safe_main_route ... ok\ntest tray::tests::localizes_user_visible_tray_labels_without_changing_ids ... ok\ntest tray::tests::opens_settings_through_a_safe_main_route ... ok\ntest tray::tests::quit_action_does_not_claim_business_window_control ... ok\ntest tray::tests::restore_pet_interaction_shows_cuu_without_stealing_focus ... ok\ntest window_controls::tests::command_names_match_the_tauri_runtime_entry ... ok\ntest window_controls::tests::hidden_windows_do_not_carry_stale_routes ... ok\ntest window_controls::tests::main_window_controls_show_and_focus_known_routes ... ok\ntest window_controls::tests::pet_window_controls_do_not_steal_focus ... ok\ntest window_controls::tests::rejects_unsafe_deep_link_routes ... ok\ntest window_controls::tests::serializes_for_tauri_command_payloads ... ok\ntest windows::tests::default_window_plan_has_main_and_pet_labels ... ok\ntest windows::tests::main_window_is_a_resizable_spotlight_shell ... ok\ntest windows::tests::pet_window_contract_matches_cuu_desktop_concept ... ok\ntest windows::tests::window_plans_serialize_with_tauri_style_field_names ... ok\n\ntest result: ok. 78 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 12 tests\ntest tests::cuu_qa_preferences_env_accepts_qa_capture_scenarios ... ok\ntest tests::cuu_qa_preferences_env_accepts_window_settings ... ok\ntest tests::cuu_qa_preferences_env_enables_dom_report_when_path_is_present ... ok\ntest tests::cuu_qa_preferences_env_ignores_invalid_settings ... ok\ntest tests::main_window_resize_direction_accepts_spotlight_edges_only ... ok\ntest tests::cuu_qa_preferences_env_accepts_hide_on_hover_truthy_values ... ok\ntest tests::spotlight_size_clamp_allows_idle_search_bar_height ... ok\ntest tests::sse_disable_env_accepts_explicit_truthy_values ... ok\ntest tests::pet_initialization_script_can_inject_qa_preferences ... ok\ntest tests::cuu_qa_dom_report_writer_writes_pretty_json_to_the_env_owned_path ... ok\ntest tests::sse_disable_env_ignores_missing_and_falsey_values ... ok\ntest tests::tray_quit_dry_run_env_accepts_truthy_values_only ... ok\n\ntest result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 9 tests\ntest default_capability_is_local_and_window_scoped ... ok\ntest tauri_bundle_targets_are_platform_native_not_windows_only ... ok\ntest tauri_windows_match_the_shell_window_contract ... ok\ntest macos_info_plist_overrides_legacy_carbon_requirement ... ok\ntest tauri_build_points_at_the_desktop_webview_surface ... ok\ntest macos_main_window_receives_pointer_events_with_a_native_one_alpha_hit_surface ... ok\ntest transparent_windows_declare_a_fully_transparent_webview_background ... ok\ntest macos_main_window_exposes_manual_drag_fallback_for_transparent_search_center ... ok\ntest macos_main_window_restores_native_vibrancy_for_real_frosted_glass ... ok\n\ntest result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n", - "stderrTail": " Finished `test` profile [unoptimized + debuginfo] target(s) in 0.25s\n Running unittests src/lib.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-280f635369cc5546)\n Running unittests src/main.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-068f30fa3eb9fc06)\n Running tests/tauri_scaffold.rs (client-tauri/src-tauri/target/debug/deps/tauri_scaffold-aedc7444f6e91615)\n Doc-tests workhub_client_tauri\n" + "stdoutTail": "n_logic ... ok\ntest sse::tests::rejects_unsafe_stream_path_segments ... ok\ntest sse::tests::startup_targets_subscribe_to_the_per_user_stream_not_the_admin_only_global ... ok\ntest sse::tests::status_payloads_use_the_dedicated_sse_status_channel ... ok\ntest sse::tests::worker_plan_keeps_retry_policy_and_subscription_headers ... ok\ntest sse_worker::tests::byte_pump_holds_partial_frames_until_the_blank_line_arrives ... ok\ntest sse_worker::tests::default_reconnect_delay_is_small_enough_for_desktop_feedback ... ok\ntest sse_worker::tests::byte_pump_preserves_multibyte_utf8_split_across_chunks ... ok\ntest sse_worker::tests::frame_boundary_end_recognizes_every_blank_line_encoding ... ok\ntest sse_worker::tests::reconnect_backoff_is_base_when_healthy_and_caps_at_60s ... ok\ntest tray::tests::keeps_tray_ids_stable_and_unique ... ok\ntest tray::tests::localizes_user_visible_tray_labels_without_changing_ids ... ok\ntest tray::tests::maps_tray_window_actions_to_existing_window_control_contract ... ok\ntest tray::tests::opens_inbox_through_a_safe_main_route ... ok\ntest tray::tests::opens_settings_through_a_safe_main_route ... ok\ntest tray::tests::quit_action_does_not_claim_business_window_control ... ok\ntest tray::tests::restore_pet_interaction_shows_cuu_without_stealing_focus ... ok\ntest window_controls::tests::command_names_match_the_tauri_runtime_entry ... ok\ntest window_controls::tests::hidden_windows_do_not_carry_stale_routes ... ok\ntest window_controls::tests::main_window_controls_show_and_focus_known_routes ... ok\ntest window_controls::tests::pet_window_controls_do_not_steal_focus ... ok\ntest window_controls::tests::rejects_unsafe_deep_link_routes ... ok\ntest window_controls::tests::serializes_for_tauri_command_payloads ... ok\ntest windows::tests::default_window_plan_has_main_and_pet_labels ... ok\ntest windows::tests::main_window_is_a_resizable_spotlight_shell ... ok\ntest windows::tests::pet_window_contract_matches_cuu_desktop_concept ... ok\ntest windows::tests::window_plans_serialize_with_tauri_style_field_names ... ok\n\ntest result: ok. 78 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 12 tests\ntest tests::main_window_resize_direction_accepts_spotlight_edges_only ... ok\ntest tests::cuu_qa_preferences_env_ignores_invalid_settings ... ok\ntest tests::cuu_qa_preferences_env_enables_dom_report_when_path_is_present ... ok\ntest tests::spotlight_size_clamp_allows_idle_search_bar_height ... ok\ntest tests::cuu_qa_preferences_env_accepts_hide_on_hover_truthy_values ... ok\ntest tests::sse_disable_env_ignores_missing_and_falsey_values ... ok\ntest tests::cuu_qa_preferences_env_accepts_window_settings ... ok\ntest tests::sse_disable_env_accepts_explicit_truthy_values ... ok\ntest tests::cuu_qa_preferences_env_accepts_qa_capture_scenarios ... ok\ntest tests::pet_initialization_script_can_inject_qa_preferences ... ok\ntest tests::tray_quit_dry_run_env_accepts_truthy_values_only ... ok\ntest tests::cuu_qa_dom_report_writer_writes_pretty_json_to_the_env_owned_path ... ok\n\ntest result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 9 tests\ntest default_capability_is_local_and_window_scoped ... ok\ntest tauri_bundle_targets_are_platform_native_not_windows_only ... ok\ntest tauri_windows_match_the_shell_window_contract ... ok\ntest transparent_windows_declare_a_fully_transparent_webview_background ... ok\ntest tauri_build_points_at_the_desktop_webview_surface ... ok\ntest macos_info_plist_overrides_legacy_carbon_requirement ... ok\ntest macos_main_window_receives_pointer_events_with_a_native_one_alpha_hit_surface ... ok\ntest macos_main_window_restores_native_vibrancy_for_real_frosted_glass ... ok\ntest macos_main_window_exposes_manual_drag_fallback_for_transparent_search_center ... ok\n\ntest result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n", + "stderrTail": "g tauri-winres v0.3.6\n Compiling fdeflate v0.3.7\n Compiling crossbeam-utils v0.8.21\n Compiling typenum v1.20.1\n Compiling dpi v0.1.2\n Compiling raw-window-handle v0.6.2\n Compiling cookie v0.18.1\n Compiling core-foundation-sys v0.8.7\n Compiling flate2 v1.1.9\n Compiling getrandom v0.3.4\n Compiling core-foundation v0.10.1\n Compiling foreign-types-macros v0.2.3\n Compiling objc2-app-kit v0.3.2\n Compiling tauri-utils v2.9.2\n Compiling block-buffer v0.10.4\n Compiling crypto-common v0.1.7\n Compiling ring v0.17.14\n Compiling foreign-types-shared v0.3.1\n Compiling bitflags v1.3.2\n Compiling png v0.17.16\n Compiling foreign-types v0.5.0\n Compiling objc2-web-kit v0.3.2\n Compiling crossbeam-channel v0.5.15\n Compiling digest v0.10.7\n Compiling core-graphics-types v0.2.0\n Compiling cpufeatures v0.2.17\n Compiling unicode-segmentation v1.13.3\n Compiling wry v0.55.1\n Compiling zeroize v1.8.2\n Compiling tauri-runtime v2.11.2\n Compiling rustls-pki-types v1.14.1\n Compiling keyboard-types v0.7.0\n Compiling sha2 v0.10.9\n Compiling ico v0.5.0\n Compiling png v0.18.1\n Compiling tracing-core v0.1.36\n Compiling dispatch2 v0.3.1\n Compiling tauri-build v2.6.2\n Compiling tauri-plugin v2.6.2\n Compiling futures-macro v0.3.32\n Compiling tracing-attributes v0.1.31\n Compiling getrandom v0.2.17\n Compiling http-body v1.0.1\n Compiling tauri-runtime-wry v2.11.2\n Compiling untrusted v0.9.0\n Compiling futures-task v0.3.32\n Compiling slab v0.4.12\n Compiling objc-sys v0.3.5\n Compiling zerocopy v0.8.50\n Compiling httparse v1.10.1\n Compiling core-graphics v0.25.0\n Compiling tracing v0.1.44\n Compiling tao v0.35.3\n Compiling futures-util v0.3.32\n Compiling muda v0.19.2\n Compiling tauri-codegen v2.6.2\n Compiling objc2-core-graphics v0.3.2\n Compiling serialize-to-javascript-impl v0.1.2\n Compiling tower-service v0.3.3\n Compiling rustls v0.23.40\n Compiling try-lock v0.2.5\n Compiling want v0.3.1\n Compiling serialize-to-javascript v0.1.2\n Compiling tray-icon v0.23.1\n Compiling tauri v2.11.2\n Compiling tauri-macros v2.6.2\n Compiling rustls-webpki v0.103.13\n Compiling window-vibrancy v0.6.0\n Compiling futures-channel v0.3.32\n Compiling serde_repr v0.1.20\n Compiling mac-notification-sys v0.6.13\n Compiling subtle v2.6.1\n Compiling atomic-waker v1.1.2\n Compiling embed_plist v1.2.2\n Compiling mime v0.3.17\n Compiling hyper v1.10.1\n Compiling objc2 v0.5.2\n Compiling tauri-plugin-notification v2.3.3\n Compiling tauri-plugin-deep-link v2.4.9\n Compiling ppv-lite86 v0.2.21\n Compiling rand_core v0.9.5\n Compiling sync_wrapper v1.0.2\n Compiling tower-layer v0.3.3\n Compiling parking v2.2.1\n Compiling ipnet v2.12.0\n Compiling futures-io v0.3.32\n Compiling tower v0.5.3\n Compiling rand_chacha v0.9.0\n Compiling futures-lite v2.6.1\n Compiling hyper-util v0.1.20\n Compiling objc2-foundation v0.2.2\n Compiling webpki-roots v1.0.7\n Compiling ryu v1.0.23\n Compiling futures-sink v0.3.32\n Compiling tower-http v0.6.11\n Compiling tokio-util v0.7.18\n Compiling serde_urlencoded v0.7.1\n Compiling rand v0.9.4\n Compiling workhub-client-tauri v0.1.0 (/private/tmp/workhub-r9-codex/client-tauri/src-tauri)\n Compiling http-body-util v0.1.3\n Compiling objc2-app-kit v0.2.2\n Compiling window-vibrancy v0.5.3\n Compiling tokio-rustls v0.26.4\n Compiling hyper-rustls v0.27.9\n Compiling reqwest v0.12.28\n Compiling notify-rust v4.17.0\n Compiling tauri-plugin-single-instance v2.4.2\n Finished `test` profile [unoptimized + debuginfo] target(s) in 1m 05s\n Running unittests src/lib.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-280f635369cc5546)\n Running unittests src/main.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-068f30fa3eb9fc06)\n Running tests/tauri_scaffold.rs (client-tauri/src-tauri/target/debug/deps/tauri_scaffold-aedc7444f6e91615)\n Doc-tests workhub_client_tauri\n" } ], "gates": { diff --git a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md index 95fd33511..646a24b2a 100644 --- a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md +++ b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md @@ -1,6 +1,6 @@ # R4.6 Rust System I18n Smoke -- generated_at: 2026-06-28T14:09:33.792Z +- generated_at: 2026-07-02T14:17:03.879Z - cargo_mode: executed - cargo_tests_passed: true - all_gates_passed: true From 57609255ece2530f4f8490b0111111fea2715eaf Mon Sep 17 00:00:00 2001 From: mycyg Date: Thu, 2 Jul 2026 22:27:35 +0800 Subject: [PATCH 02/10] =?UTF-8?q?fix(desktop):=20exclude=20text=20inputs?= =?UTF-8?q?=20from=20spotlight=20drag=20=E5=BE=85=E7=9C=9F=E6=9C=BA?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/desktop-webview/src/main.test.ts | 7 ++-- .../src/spotlight/controller-drag.test.ts | 34 +++++++++++++++++++ .../src/spotlight/controller.ts | 11 +++--- .../rust-system-i18n-report.json | 6 ++-- .../smoke-summary.md | 2 +- 5 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 apps/desktop-webview/src/spotlight/controller-drag.test.ts diff --git a/apps/desktop-webview/src/main.test.ts b/apps/desktop-webview/src/main.test.ts index 8e43dd4e1..443ef816f 100644 --- a/apps/desktop-webview/src/main.test.ts +++ b/apps/desktop-webview/src/main.test.ts @@ -789,9 +789,10 @@ test("Spotlight exposes native move and resize gestures instead of a fixed top s assert.match(source, /focusSearch\(\{ expand: false \}\)/u); assert.match(source, /suppressNextFocusExpansion = !options\.expand/u); assert.match(source, /if \(suppressNextFocusExpansion \|\| nowMs\(\) < suppressSearchFocusUntil\) \{\s*suppressNextFocusExpansion = false;\s*\}/u); - assert.match(source, /const dragExcludedSelector = "button,a,select,\[contenteditable=true\]"/u); - assert.match(source, /Boolean\(target\.closest\(dragExcludedSelector\)\)/u); - assert.doesNotMatch(source, /dragExcludedSelector = "input,textarea,button/u); + // 3-2: the old selector assertion omitted input/textarea, but that let text selection in the + // search box or composers start a window drag instead of selecting editable text. + assert.match(source, /const DRAG_EXCLUDED_SELECTOR = "input,textarea,button,a,select,\[contenteditable=true\]"/u); + assert.match(source, /Boolean\(target\.closest\(DRAG_EXCLUDED_SELECTOR\)\)/u); assert.doesNotMatch(source, /userResizeAutoUnlockAt/u); assert.match(source, /let suppressSearchFocusUntil = 0/u); assert.match(source, /let suppressSearchClickUntil = 0/u); diff --git a/apps/desktop-webview/src/spotlight/controller-drag.test.ts b/apps/desktop-webview/src/spotlight/controller-drag.test.ts new file mode 100644 index 000000000..47d911db7 --- /dev/null +++ b/apps/desktop-webview/src/spotlight/controller-drag.test.ts @@ -0,0 +1,34 @@ +import assert from "node:assert/strict"; +import { afterEach, test } from "node:test"; + +import { isSpotlightDragExcludedTarget } from "./controller.js"; + +const originalElement = globalThis.Element; + +class FakeElement { + constructor(private readonly tagName: string) {} + + closest(selector: string): FakeElement | null { + const selectors = selector.split(",").map((item) => item.trim()); + return selectors.includes(this.tagName) ? this : null; + } +} + +afterEach(() => { + Object.defineProperty(globalThis, "Element", { + configurable: true, + value: originalElement + }); +}); + +test("Spotlight drag target classifier excludes text editing controls from window dragging", () => { + Object.defineProperty(globalThis, "Element", { + configurable: true, + value: FakeElement + }); + + assert.equal(isSpotlightDragExcludedTarget(new FakeElement("input") as unknown as EventTarget), true); + assert.equal(isSpotlightDragExcludedTarget(new FakeElement("textarea") as unknown as EventTarget), true); + assert.equal(isSpotlightDragExcludedTarget(new FakeElement("button") as unknown as EventTarget), true); + assert.equal(isSpotlightDragExcludedTarget(new FakeElement("div") as unknown as EventTarget), false); +}); diff --git a/apps/desktop-webview/src/spotlight/controller.ts b/apps/desktop-webview/src/spotlight/controller.ts index 9d3f1cd3c..7ce6585ef 100644 --- a/apps/desktop-webview/src/spotlight/controller.ts +++ b/apps/desktop-webview/src/spotlight/controller.ts @@ -54,6 +54,11 @@ const SEARCH_ICON = ''; const BACK_ICON = ''; +const DRAG_EXCLUDED_SELECTOR = "input,textarea,button,a,select,[contenteditable=true]"; + +export function isSpotlightDragExcludedTarget(target: EventTarget | null): boolean { + return target instanceof Element && Boolean(target.closest(DRAG_EXCLUDED_SELECTOR)); +} function renderLauncherGrid( matches: CommandMatch[], @@ -425,8 +430,6 @@ export function mountSpotlight(input: MountSpotlightInput): SpotlightHandle { dispatch({ type: "back" }); }); - const dragExcludedSelector = "button,a,select,[contenteditable=true]"; - const isDragExcludedTarget = (target: EventTarget | null) => target instanceof Element && Boolean(target.closest(dragExcludedSelector)); let manualDrag: | { startClientX: number; @@ -439,7 +442,7 @@ export function mountSpotlight(input: MountSpotlightInput): SpotlightHandle { topEl.addEventListener( "mousedown", (event) => { - if (event.button !== 0 || isDragExcludedTarget(event.target)) { + if (event.button !== 0 || isSpotlightDragExcludedTarget(event.target)) { return; } manualDrag = { @@ -595,7 +598,7 @@ export function mountSpotlight(input: MountSpotlightInput): SpotlightHandle { if (event.button !== 0) { return; } - if (isDragExcludedTarget(event.target)) { + if (isSpotlightDragExcludedTarget(event.target)) { return; } if (input.dragMove) { diff --git a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json index fabe3497f..7f0ca2278 100644 --- a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json +++ b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-07-02T14:17:03.879Z", + "generated_at": "2026-07-02T14:26:01.872Z", "module": "R4.6 Rust system-string i18n", "output_dir": "/private/tmp/workhub-r9-codex/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n", "cargo_mode": "executed", @@ -7,8 +7,8 @@ { "command": "cargo test --manifest-path /private/tmp/workhub-r9-codex/client-tauri/src-tauri/Cargo.toml", "exitCode": 0, - "stdoutTail": "n_logic ... ok\ntest sse::tests::rejects_unsafe_stream_path_segments ... ok\ntest sse::tests::startup_targets_subscribe_to_the_per_user_stream_not_the_admin_only_global ... ok\ntest sse::tests::status_payloads_use_the_dedicated_sse_status_channel ... ok\ntest sse::tests::worker_plan_keeps_retry_policy_and_subscription_headers ... ok\ntest sse_worker::tests::byte_pump_holds_partial_frames_until_the_blank_line_arrives ... ok\ntest sse_worker::tests::default_reconnect_delay_is_small_enough_for_desktop_feedback ... ok\ntest sse_worker::tests::byte_pump_preserves_multibyte_utf8_split_across_chunks ... ok\ntest sse_worker::tests::frame_boundary_end_recognizes_every_blank_line_encoding ... ok\ntest sse_worker::tests::reconnect_backoff_is_base_when_healthy_and_caps_at_60s ... ok\ntest tray::tests::keeps_tray_ids_stable_and_unique ... ok\ntest tray::tests::localizes_user_visible_tray_labels_without_changing_ids ... ok\ntest tray::tests::maps_tray_window_actions_to_existing_window_control_contract ... ok\ntest tray::tests::opens_inbox_through_a_safe_main_route ... ok\ntest tray::tests::opens_settings_through_a_safe_main_route ... ok\ntest tray::tests::quit_action_does_not_claim_business_window_control ... ok\ntest tray::tests::restore_pet_interaction_shows_cuu_without_stealing_focus ... ok\ntest window_controls::tests::command_names_match_the_tauri_runtime_entry ... ok\ntest window_controls::tests::hidden_windows_do_not_carry_stale_routes ... ok\ntest window_controls::tests::main_window_controls_show_and_focus_known_routes ... ok\ntest window_controls::tests::pet_window_controls_do_not_steal_focus ... ok\ntest window_controls::tests::rejects_unsafe_deep_link_routes ... ok\ntest window_controls::tests::serializes_for_tauri_command_payloads ... ok\ntest windows::tests::default_window_plan_has_main_and_pet_labels ... ok\ntest windows::tests::main_window_is_a_resizable_spotlight_shell ... ok\ntest windows::tests::pet_window_contract_matches_cuu_desktop_concept ... ok\ntest windows::tests::window_plans_serialize_with_tauri_style_field_names ... ok\n\ntest result: ok. 78 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 12 tests\ntest tests::main_window_resize_direction_accepts_spotlight_edges_only ... ok\ntest tests::cuu_qa_preferences_env_ignores_invalid_settings ... ok\ntest tests::cuu_qa_preferences_env_enables_dom_report_when_path_is_present ... ok\ntest tests::spotlight_size_clamp_allows_idle_search_bar_height ... ok\ntest tests::cuu_qa_preferences_env_accepts_hide_on_hover_truthy_values ... ok\ntest tests::sse_disable_env_ignores_missing_and_falsey_values ... ok\ntest tests::cuu_qa_preferences_env_accepts_window_settings ... ok\ntest tests::sse_disable_env_accepts_explicit_truthy_values ... ok\ntest tests::cuu_qa_preferences_env_accepts_qa_capture_scenarios ... ok\ntest tests::pet_initialization_script_can_inject_qa_preferences ... ok\ntest tests::tray_quit_dry_run_env_accepts_truthy_values_only ... ok\ntest tests::cuu_qa_dom_report_writer_writes_pretty_json_to_the_env_owned_path ... ok\n\ntest result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 9 tests\ntest default_capability_is_local_and_window_scoped ... ok\ntest tauri_bundle_targets_are_platform_native_not_windows_only ... ok\ntest tauri_windows_match_the_shell_window_contract ... ok\ntest transparent_windows_declare_a_fully_transparent_webview_background ... ok\ntest tauri_build_points_at_the_desktop_webview_surface ... ok\ntest macos_info_plist_overrides_legacy_carbon_requirement ... ok\ntest macos_main_window_receives_pointer_events_with_a_native_one_alpha_hit_surface ... ok\ntest macos_main_window_restores_native_vibrancy_for_real_frosted_glass ... ok\ntest macos_main_window_exposes_manual_drag_fallback_for_transparent_search_center ... ok\n\ntest result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n", - "stderrTail": "g tauri-winres v0.3.6\n Compiling fdeflate v0.3.7\n Compiling crossbeam-utils v0.8.21\n Compiling typenum v1.20.1\n Compiling dpi v0.1.2\n Compiling raw-window-handle v0.6.2\n Compiling cookie v0.18.1\n Compiling core-foundation-sys v0.8.7\n Compiling flate2 v1.1.9\n Compiling getrandom v0.3.4\n Compiling core-foundation v0.10.1\n Compiling foreign-types-macros v0.2.3\n Compiling objc2-app-kit v0.3.2\n Compiling tauri-utils v2.9.2\n Compiling block-buffer v0.10.4\n Compiling crypto-common v0.1.7\n Compiling ring v0.17.14\n Compiling foreign-types-shared v0.3.1\n Compiling bitflags v1.3.2\n Compiling png v0.17.16\n Compiling foreign-types v0.5.0\n Compiling objc2-web-kit v0.3.2\n Compiling crossbeam-channel v0.5.15\n Compiling digest v0.10.7\n Compiling core-graphics-types v0.2.0\n Compiling cpufeatures v0.2.17\n Compiling unicode-segmentation v1.13.3\n Compiling wry v0.55.1\n Compiling zeroize v1.8.2\n Compiling tauri-runtime v2.11.2\n Compiling rustls-pki-types v1.14.1\n Compiling keyboard-types v0.7.0\n Compiling sha2 v0.10.9\n Compiling ico v0.5.0\n Compiling png v0.18.1\n Compiling tracing-core v0.1.36\n Compiling dispatch2 v0.3.1\n Compiling tauri-build v2.6.2\n Compiling tauri-plugin v2.6.2\n Compiling futures-macro v0.3.32\n Compiling tracing-attributes v0.1.31\n Compiling getrandom v0.2.17\n Compiling http-body v1.0.1\n Compiling tauri-runtime-wry v2.11.2\n Compiling untrusted v0.9.0\n Compiling futures-task v0.3.32\n Compiling slab v0.4.12\n Compiling objc-sys v0.3.5\n Compiling zerocopy v0.8.50\n Compiling httparse v1.10.1\n Compiling core-graphics v0.25.0\n Compiling tracing v0.1.44\n Compiling tao v0.35.3\n Compiling futures-util v0.3.32\n Compiling muda v0.19.2\n Compiling tauri-codegen v2.6.2\n Compiling objc2-core-graphics v0.3.2\n Compiling serialize-to-javascript-impl v0.1.2\n Compiling tower-service v0.3.3\n Compiling rustls v0.23.40\n Compiling try-lock v0.2.5\n Compiling want v0.3.1\n Compiling serialize-to-javascript v0.1.2\n Compiling tray-icon v0.23.1\n Compiling tauri v2.11.2\n Compiling tauri-macros v2.6.2\n Compiling rustls-webpki v0.103.13\n Compiling window-vibrancy v0.6.0\n Compiling futures-channel v0.3.32\n Compiling serde_repr v0.1.20\n Compiling mac-notification-sys v0.6.13\n Compiling subtle v2.6.1\n Compiling atomic-waker v1.1.2\n Compiling embed_plist v1.2.2\n Compiling mime v0.3.17\n Compiling hyper v1.10.1\n Compiling objc2 v0.5.2\n Compiling tauri-plugin-notification v2.3.3\n Compiling tauri-plugin-deep-link v2.4.9\n Compiling ppv-lite86 v0.2.21\n Compiling rand_core v0.9.5\n Compiling sync_wrapper v1.0.2\n Compiling tower-layer v0.3.3\n Compiling parking v2.2.1\n Compiling ipnet v2.12.0\n Compiling futures-io v0.3.32\n Compiling tower v0.5.3\n Compiling rand_chacha v0.9.0\n Compiling futures-lite v2.6.1\n Compiling hyper-util v0.1.20\n Compiling objc2-foundation v0.2.2\n Compiling webpki-roots v1.0.7\n Compiling ryu v1.0.23\n Compiling futures-sink v0.3.32\n Compiling tower-http v0.6.11\n Compiling tokio-util v0.7.18\n Compiling serde_urlencoded v0.7.1\n Compiling rand v0.9.4\n Compiling workhub-client-tauri v0.1.0 (/private/tmp/workhub-r9-codex/client-tauri/src-tauri)\n Compiling http-body-util v0.1.3\n Compiling objc2-app-kit v0.2.2\n Compiling window-vibrancy v0.5.3\n Compiling tokio-rustls v0.26.4\n Compiling hyper-rustls v0.27.9\n Compiling reqwest v0.12.28\n Compiling notify-rust v4.17.0\n Compiling tauri-plugin-single-instance v2.4.2\n Finished `test` profile [unoptimized + debuginfo] target(s) in 1m 05s\n Running unittests src/lib.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-280f635369cc5546)\n Running unittests src/main.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-068f30fa3eb9fc06)\n Running tests/tauri_scaffold.rs (client-tauri/src-tauri/target/debug/deps/tauri_scaffold-aedc7444f6e91615)\n Doc-tests workhub_client_tauri\n" + "stdoutTail": "se::tests::plans_contract_stream_paths_without_copying_domain_logic ... ok\ntest sse::tests::startup_targets_subscribe_to_the_per_user_stream_not_the_admin_only_global ... ok\ntest sse::tests::status_payloads_use_the_dedicated_sse_status_channel ... ok\ntest sse::tests::worker_plan_keeps_retry_policy_and_subscription_headers ... ok\ntest sse_worker::tests::byte_pump_holds_partial_frames_until_the_blank_line_arrives ... ok\ntest sse_worker::tests::byte_pump_preserves_multibyte_utf8_split_across_chunks ... ok\ntest sse_worker::tests::default_reconnect_delay_is_small_enough_for_desktop_feedback ... ok\ntest sse_worker::tests::frame_boundary_end_recognizes_every_blank_line_encoding ... ok\ntest sse_worker::tests::reconnect_backoff_is_base_when_healthy_and_caps_at_60s ... ok\ntest tray::tests::keeps_tray_ids_stable_and_unique ... ok\ntest tray::tests::maps_tray_window_actions_to_existing_window_control_contract ... ok\ntest tray::tests::localizes_user_visible_tray_labels_without_changing_ids ... ok\ntest tray::tests::opens_settings_through_a_safe_main_route ... ok\ntest tray::tests::opens_inbox_through_a_safe_main_route ... ok\ntest tray::tests::quit_action_does_not_claim_business_window_control ... ok\ntest tray::tests::restore_pet_interaction_shows_cuu_without_stealing_focus ... ok\ntest window_controls::tests::command_names_match_the_tauri_runtime_entry ... ok\ntest window_controls::tests::hidden_windows_do_not_carry_stale_routes ... ok\ntest window_controls::tests::main_window_controls_show_and_focus_known_routes ... ok\ntest window_controls::tests::pet_window_controls_do_not_steal_focus ... ok\ntest window_controls::tests::rejects_unsafe_deep_link_routes ... ok\ntest window_controls::tests::serializes_for_tauri_command_payloads ... ok\ntest windows::tests::default_window_plan_has_main_and_pet_labels ... ok\ntest windows::tests::main_window_is_a_resizable_spotlight_shell ... ok\ntest windows::tests::pet_window_contract_matches_cuu_desktop_concept ... ok\ntest windows::tests::window_plans_serialize_with_tauri_style_field_names ... ok\n\ntest result: ok. 78 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 12 tests\ntest tests::main_window_resize_direction_accepts_spotlight_edges_only ... ok\ntest tests::cuu_qa_preferences_env_accepts_hide_on_hover_truthy_values ... ok\ntest tests::cuu_qa_preferences_env_accepts_window_settings ... ok\ntest tests::cuu_qa_preferences_env_enables_dom_report_when_path_is_present ... ok\ntest tests::cuu_qa_preferences_env_accepts_qa_capture_scenarios ... ok\ntest tests::cuu_qa_preferences_env_ignores_invalid_settings ... ok\ntest tests::spotlight_size_clamp_allows_idle_search_bar_height ... ok\ntest tests::sse_disable_env_accepts_explicit_truthy_values ... ok\ntest tests::pet_initialization_script_can_inject_qa_preferences ... ok\ntest tests::sse_disable_env_ignores_missing_and_falsey_values ... ok\ntest tests::tray_quit_dry_run_env_accepts_truthy_values_only ... ok\ntest tests::cuu_qa_dom_report_writer_writes_pretty_json_to_the_env_owned_path ... ok\n\ntest result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 9 tests\ntest default_capability_is_local_and_window_scoped ... ok\ntest tauri_build_points_at_the_desktop_webview_surface ... ok\ntest macos_info_plist_overrides_legacy_carbon_requirement ... ok\ntest tauri_bundle_targets_are_platform_native_not_windows_only ... ok\ntest tauri_windows_match_the_shell_window_contract ... ok\ntest transparent_windows_declare_a_fully_transparent_webview_background ... ok\ntest macos_main_window_receives_pointer_events_with_a_native_one_alpha_hit_surface ... ok\ntest macos_main_window_exposes_manual_drag_fallback_for_transparent_search_center ... ok\ntest macos_main_window_restores_native_vibrancy_for_real_frosted_glass ... ok\n\ntest result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n", + "stderrTail": " Compiling workhub-client-tauri v0.1.0 (/private/tmp/workhub-r9-codex/client-tauri/src-tauri)\n Finished `test` profile [unoptimized + debuginfo] target(s) in 1.05s\n Running unittests src/lib.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-280f635369cc5546)\n Running unittests src/main.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-068f30fa3eb9fc06)\n Running tests/tauri_scaffold.rs (client-tauri/src-tauri/target/debug/deps/tauri_scaffold-aedc7444f6e91615)\n Doc-tests workhub_client_tauri\n" } ], "gates": { diff --git a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md index 646a24b2a..1be614a37 100644 --- a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md +++ b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md @@ -1,6 +1,6 @@ # R4.6 Rust System I18n Smoke -- generated_at: 2026-07-02T14:17:03.879Z +- generated_at: 2026-07-02T14:26:01.872Z - cargo_mode: executed - cargo_tests_passed: true - all_gates_passed: true From 1bc1b57a941c3cb3cd1f2345dec0d70b22a1d6b0 Mon Sep 17 00:00:00 2001 From: mycyg Date: Thu, 2 Jul 2026 22:41:51 +0800 Subject: [PATCH 03/10] =?UTF-8?q?fix(desktop):=20wire=20spotlight=20routes?= =?UTF-8?q?=20into=20cuu=20context=20=E5=BE=85=E7=9C=9F=E6=9C=BA=E9=AA=8C?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/desktop-webview/src/browser.ts | 15 +++----- apps/desktop-webview/src/main.test.ts | 14 ++------ .../src/spotlight-shell-navigation.test.ts | 34 ++++++++++++++++++ .../src/spotlight-shell-navigation.ts | 35 +++++++++++++++++++ .../rust-system-i18n-report.json | 6 ++-- .../smoke-summary.md | 2 +- 6 files changed, 81 insertions(+), 25 deletions(-) create mode 100644 apps/desktop-webview/src/spotlight-shell-navigation.test.ts create mode 100644 apps/desktop-webview/src/spotlight-shell-navigation.ts diff --git a/apps/desktop-webview/src/browser.ts b/apps/desktop-webview/src/browser.ts index 394fc2e26..9fdc5c7db 100644 --- a/apps/desktop-webview/src/browser.ts +++ b/apps/desktop-webview/src/browser.ts @@ -77,6 +77,7 @@ import { resolveDesktopPetWindowBridge } from "./pet-window-bridge.js"; import { parseDesktopShellNavigatePayload } from "./shell-events.js"; +import { handleDesktopSpotlightShellNavigate } from "./spotlight-shell-navigation.js"; import { appleGlassDesignSystemCss } from "./design-system.js"; import { commandPaletteCss, @@ -92,7 +93,6 @@ import { type SpotlightResizeFn } from "./spotlight/controller.js"; import { spotlightCss } from "./spotlight/css.js"; -import { capabilityForShellRoute, entityIdFromShellRoute } from "./spotlight/state.js"; import { reviewProposalWithoutMerge } from "./spotlight/views/proposals.js"; import { isStaleDesktopClientTokenError } from "./auth-recovery.js"; @@ -1249,15 +1249,10 @@ async function bootSpotlight() { // 监听它 → 把盒子直接开到对应能力(回 "/" 则回 launcher)。这是 Cuu/外部入口与盒子联动的地基。 const shellListen = resolveDesktopShellListen(); void shellListen?.("navigate", (event) => { - const parsed = parseDesktopShellNavigatePayload(event.payload); - const cap = parsed ? capabilityForShellRoute(parsed.route) : undefined; - if (cap && parsed) { - // rank13:携带路由里的实体 id,让 workitem/proposals/replay 直接打开该项而非落到列表。 - const id = entityIdFromShellRoute(parsed.route); - spotlight.openCapability(cap, id ? { id, route: parsed.route } : { route: parsed.route }); - } else { - spotlight.reset(); - } + handleDesktopSpotlightShellNavigate(event.payload, { + spotlight, + saveProjectContextFromRoute: saveDesktopCuuProjectContextFromRoute + }); }); // rank12:把「待你拍板」实时条数喂给 launcher 审批角标——盒子的核心承诺是一眼看到有几条待决策。 // 启动拉一次 + 每 30s + 窗口重新聚焦时刷新;best-effort,失败不更新角标、不影响盒子。 diff --git a/apps/desktop-webview/src/main.test.ts b/apps/desktop-webview/src/main.test.ts index 443ef816f..76f973f60 100644 --- a/apps/desktop-webview/src/main.test.ts +++ b/apps/desktop-webview/src/main.test.ts @@ -733,17 +733,9 @@ test("R4.21 desktop browser uses the shared web runtime helpers", () => { assert.doesNotMatch(source, /function updateLineEditorPanelPayload/u); }); -test("desktop browser saves project context so Cuu can ask about project drive files", () => { - const source = readFileSync(new URL("./browser.ts", import.meta.url), "utf8"); - const activateStart = source.indexOf("const activateRoute = (route: string) => {"); - const activateEnd = source.indexOf("const activateFromHash", activateStart); - assert.notEqual(activateStart, -1); - assert.notEqual(activateEnd, -1); - const activateSource = source.slice(activateStart, activateEnd); - - assert.match(source, /saveDesktopCuuProjectContextFromRoute/u); - assert.match(activateSource, /saveDesktopCuuProjectContextFromRoute\(route\)/u); -}); +// The old project-context assertion was wrong: it grepped deprecated gold-path +// activateRoute text while the production desktop shell is bootSpotlight(). +// Production behavior is covered by spotlight-shell-navigation.test.ts. test("desktop browser proposal review action confirms only and leaves merge as a second step", () => { const source = readFileSync(new URL("./browser.ts", import.meta.url), "utf8"); diff --git a/apps/desktop-webview/src/spotlight-shell-navigation.test.ts b/apps/desktop-webview/src/spotlight-shell-navigation.test.ts new file mode 100644 index 000000000..a40f1617f --- /dev/null +++ b/apps/desktop-webview/src/spotlight-shell-navigation.test.ts @@ -0,0 +1,34 @@ +import { strict as assert } from "node:assert"; +import { test } from "node:test"; + +import { handleDesktopSpotlightShellNavigate } from "./spotlight-shell-navigation.js"; + +test("production Spotlight shell navigate saves project context before opening a capability", () => { + const projectId = "10000000-0000-4000-8000-000000000002"; + const route = `/drive?project_id=${projectId}`; + const savedRoutes: string[] = []; + const opened: Array<{ id: string; target?: { id?: string; route?: string } }> = []; + let resetCount = 0; + + const result = handleDesktopSpotlightShellNavigate( + { route }, + { + saveProjectContextFromRoute: (nextRoute) => { + savedRoutes.push(nextRoute); + }, + spotlight: { + openCapability(id, target) { + opened.push(target ? { id, target } : { id }); + }, + reset() { + resetCount += 1; + } + } + } + ); + + assert.deepEqual(savedRoutes, [route]); + assert.deepEqual(opened, [{ id: "drive", target: { id: projectId, route } }]); + assert.equal(resetCount, 0); + assert.equal(result.kind, "open"); +}); diff --git a/apps/desktop-webview/src/spotlight-shell-navigation.ts b/apps/desktop-webview/src/spotlight-shell-navigation.ts new file mode 100644 index 000000000..fad45fc63 --- /dev/null +++ b/apps/desktop-webview/src/spotlight-shell-navigation.ts @@ -0,0 +1,35 @@ +import type { CommandId } from "./command-palette.js"; +import { parseDesktopShellNavigatePayload } from "./shell-events.js"; +import type { SpotlightHandle } from "./spotlight/controller.js"; +import { capabilityForShellRoute, entityIdFromShellRoute } from "./spotlight/state.js"; +import type { SpotlightTarget } from "./spotlight/view-context.js"; + +export type DesktopSpotlightProjectContextSaver = (route: string) => unknown; + +export type DesktopSpotlightShellNavigationResult = + | { kind: "open"; route: string; capability: CommandId; target: SpotlightTarget } + | { kind: "reset"; route?: string }; + +export function handleDesktopSpotlightShellNavigate( + payload: unknown, + input: { + spotlight: Pick; + saveProjectContextFromRoute?: DesktopSpotlightProjectContextSaver | undefined; + } +): DesktopSpotlightShellNavigationResult { + const parsed = parseDesktopShellNavigatePayload(payload); + if (parsed) { + input.saveProjectContextFromRoute?.(parsed.route); + } + + const capability = parsed ? capabilityForShellRoute(parsed.route) : undefined; + if (capability && parsed) { + const id = entityIdFromShellRoute(parsed.route); + const target = id ? { id, route: parsed.route } : { route: parsed.route }; + input.spotlight.openCapability(capability, target); + return { kind: "open", route: parsed.route, capability, target }; + } + + input.spotlight.reset(); + return parsed ? { kind: "reset", route: parsed.route } : { kind: "reset" }; +} diff --git a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json index 7f0ca2278..199a579bb 100644 --- a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json +++ b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/rust-system-i18n-report.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-07-02T14:26:01.872Z", + "generated_at": "2026-07-02T14:40:35.811Z", "module": "R4.6 Rust system-string i18n", "output_dir": "/private/tmp/workhub-r9-codex/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n", "cargo_mode": "executed", @@ -7,8 +7,8 @@ { "command": "cargo test --manifest-path /private/tmp/workhub-r9-codex/client-tauri/src-tauri/Cargo.toml", "exitCode": 0, - "stdoutTail": "se::tests::plans_contract_stream_paths_without_copying_domain_logic ... ok\ntest sse::tests::startup_targets_subscribe_to_the_per_user_stream_not_the_admin_only_global ... ok\ntest sse::tests::status_payloads_use_the_dedicated_sse_status_channel ... ok\ntest sse::tests::worker_plan_keeps_retry_policy_and_subscription_headers ... ok\ntest sse_worker::tests::byte_pump_holds_partial_frames_until_the_blank_line_arrives ... ok\ntest sse_worker::tests::byte_pump_preserves_multibyte_utf8_split_across_chunks ... ok\ntest sse_worker::tests::default_reconnect_delay_is_small_enough_for_desktop_feedback ... ok\ntest sse_worker::tests::frame_boundary_end_recognizes_every_blank_line_encoding ... ok\ntest sse_worker::tests::reconnect_backoff_is_base_when_healthy_and_caps_at_60s ... ok\ntest tray::tests::keeps_tray_ids_stable_and_unique ... ok\ntest tray::tests::maps_tray_window_actions_to_existing_window_control_contract ... ok\ntest tray::tests::localizes_user_visible_tray_labels_without_changing_ids ... ok\ntest tray::tests::opens_settings_through_a_safe_main_route ... ok\ntest tray::tests::opens_inbox_through_a_safe_main_route ... ok\ntest tray::tests::quit_action_does_not_claim_business_window_control ... ok\ntest tray::tests::restore_pet_interaction_shows_cuu_without_stealing_focus ... ok\ntest window_controls::tests::command_names_match_the_tauri_runtime_entry ... ok\ntest window_controls::tests::hidden_windows_do_not_carry_stale_routes ... ok\ntest window_controls::tests::main_window_controls_show_and_focus_known_routes ... ok\ntest window_controls::tests::pet_window_controls_do_not_steal_focus ... ok\ntest window_controls::tests::rejects_unsafe_deep_link_routes ... ok\ntest window_controls::tests::serializes_for_tauri_command_payloads ... ok\ntest windows::tests::default_window_plan_has_main_and_pet_labels ... ok\ntest windows::tests::main_window_is_a_resizable_spotlight_shell ... ok\ntest windows::tests::pet_window_contract_matches_cuu_desktop_concept ... ok\ntest windows::tests::window_plans_serialize_with_tauri_style_field_names ... ok\n\ntest result: ok. 78 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 12 tests\ntest tests::main_window_resize_direction_accepts_spotlight_edges_only ... ok\ntest tests::cuu_qa_preferences_env_accepts_hide_on_hover_truthy_values ... ok\ntest tests::cuu_qa_preferences_env_accepts_window_settings ... ok\ntest tests::cuu_qa_preferences_env_enables_dom_report_when_path_is_present ... ok\ntest tests::cuu_qa_preferences_env_accepts_qa_capture_scenarios ... ok\ntest tests::cuu_qa_preferences_env_ignores_invalid_settings ... ok\ntest tests::spotlight_size_clamp_allows_idle_search_bar_height ... ok\ntest tests::sse_disable_env_accepts_explicit_truthy_values ... ok\ntest tests::pet_initialization_script_can_inject_qa_preferences ... ok\ntest tests::sse_disable_env_ignores_missing_and_falsey_values ... ok\ntest tests::tray_quit_dry_run_env_accepts_truthy_values_only ... ok\ntest tests::cuu_qa_dom_report_writer_writes_pretty_json_to_the_env_owned_path ... ok\n\ntest result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 9 tests\ntest default_capability_is_local_and_window_scoped ... ok\ntest tauri_build_points_at_the_desktop_webview_surface ... ok\ntest macos_info_plist_overrides_legacy_carbon_requirement ... ok\ntest tauri_bundle_targets_are_platform_native_not_windows_only ... ok\ntest tauri_windows_match_the_shell_window_contract ... ok\ntest transparent_windows_declare_a_fully_transparent_webview_background ... ok\ntest macos_main_window_receives_pointer_events_with_a_native_one_alpha_hit_surface ... ok\ntest macos_main_window_exposes_manual_drag_fallback_for_transparent_search_center ... ok\ntest macos_main_window_restores_native_vibrancy_for_real_frosted_glass ... ok\n\ntest result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n", - "stderrTail": " Compiling workhub-client-tauri v0.1.0 (/private/tmp/workhub-r9-codex/client-tauri/src-tauri)\n Finished `test` profile [unoptimized + debuginfo] target(s) in 1.05s\n Running unittests src/lib.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-280f635369cc5546)\n Running unittests src/main.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-068f30fa3eb9fc06)\n Running tests/tauri_scaffold.rs (client-tauri/src-tauri/target/debug/deps/tauri_scaffold-aedc7444f6e91615)\n Doc-tests workhub_client_tauri\n" + "stdoutTail": "se::tests::plans_contract_stream_paths_without_copying_domain_logic ... ok\ntest sse::tests::startup_targets_subscribe_to_the_per_user_stream_not_the_admin_only_global ... ok\ntest sse::tests::status_payloads_use_the_dedicated_sse_status_channel ... ok\ntest sse::tests::worker_plan_keeps_retry_policy_and_subscription_headers ... ok\ntest sse_worker::tests::byte_pump_holds_partial_frames_until_the_blank_line_arrives ... ok\ntest sse_worker::tests::byte_pump_preserves_multibyte_utf8_split_across_chunks ... ok\ntest sse_worker::tests::default_reconnect_delay_is_small_enough_for_desktop_feedback ... ok\ntest sse_worker::tests::frame_boundary_end_recognizes_every_blank_line_encoding ... ok\ntest sse_worker::tests::reconnect_backoff_is_base_when_healthy_and_caps_at_60s ... ok\ntest tray::tests::keeps_tray_ids_stable_and_unique ... ok\ntest tray::tests::localizes_user_visible_tray_labels_without_changing_ids ... ok\ntest tray::tests::opens_inbox_through_a_safe_main_route ... ok\ntest tray::tests::maps_tray_window_actions_to_existing_window_control_contract ... ok\ntest tray::tests::opens_settings_through_a_safe_main_route ... ok\ntest tray::tests::quit_action_does_not_claim_business_window_control ... ok\ntest tray::tests::restore_pet_interaction_shows_cuu_without_stealing_focus ... ok\ntest window_controls::tests::command_names_match_the_tauri_runtime_entry ... ok\ntest window_controls::tests::hidden_windows_do_not_carry_stale_routes ... ok\ntest window_controls::tests::main_window_controls_show_and_focus_known_routes ... ok\ntest window_controls::tests::pet_window_controls_do_not_steal_focus ... ok\ntest window_controls::tests::rejects_unsafe_deep_link_routes ... ok\ntest window_controls::tests::serializes_for_tauri_command_payloads ... ok\ntest windows::tests::default_window_plan_has_main_and_pet_labels ... ok\ntest windows::tests::main_window_is_a_resizable_spotlight_shell ... ok\ntest windows::tests::pet_window_contract_matches_cuu_desktop_concept ... ok\ntest windows::tests::window_plans_serialize_with_tauri_style_field_names ... ok\n\ntest result: ok. 78 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 12 tests\ntest tests::cuu_qa_preferences_env_accepts_hide_on_hover_truthy_values ... ok\ntest tests::cuu_qa_preferences_env_enables_dom_report_when_path_is_present ... ok\ntest tests::main_window_resize_direction_accepts_spotlight_edges_only ... ok\ntest tests::cuu_qa_preferences_env_accepts_window_settings ... ok\ntest tests::spotlight_size_clamp_allows_idle_search_bar_height ... ok\ntest tests::cuu_qa_preferences_env_ignores_invalid_settings ... ok\ntest tests::sse_disable_env_accepts_explicit_truthy_values ... ok\ntest tests::sse_disable_env_ignores_missing_and_falsey_values ... ok\ntest tests::cuu_qa_preferences_env_accepts_qa_capture_scenarios ... ok\ntest tests::pet_initialization_script_can_inject_qa_preferences ... ok\ntest tests::tray_quit_dry_run_env_accepts_truthy_values_only ... ok\ntest tests::cuu_qa_dom_report_writer_writes_pretty_json_to_the_env_owned_path ... ok\n\ntest result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 9 tests\ntest default_capability_is_local_and_window_scoped ... ok\ntest tauri_build_points_at_the_desktop_webview_surface ... ok\ntest transparent_windows_declare_a_fully_transparent_webview_background ... ok\ntest tauri_windows_match_the_shell_window_contract ... ok\ntest macos_info_plist_overrides_legacy_carbon_requirement ... ok\ntest tauri_bundle_targets_are_platform_native_not_windows_only ... ok\ntest macos_main_window_receives_pointer_events_with_a_native_one_alpha_hit_surface ... ok\ntest macos_main_window_restores_native_vibrancy_for_real_frosted_glass ... ok\ntest macos_main_window_exposes_manual_drag_fallback_for_transparent_search_center ... ok\n\ntest result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n\n", + "stderrTail": " Finished `test` profile [unoptimized + debuginfo] target(s) in 0.23s\n Running unittests src/lib.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-280f635369cc5546)\n Running unittests src/main.rs (client-tauri/src-tauri/target/debug/deps/workhub_client_tauri-068f30fa3eb9fc06)\n Running tests/tauri_scaffold.rs (client-tauri/src-tauri/target/debug/deps/tauri_scaffold-aedc7444f6e91615)\n Doc-tests workhub_client_tauri\n" } ], "gates": { diff --git a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md index 1be614a37..5cfa683d0 100644 --- a/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md +++ b/docs/workhub/05-clients/assets/audit/2026-06-11-r4-rust-system-i18n/smoke-summary.md @@ -1,6 +1,6 @@ # R4.6 Rust System I18n Smoke -- generated_at: 2026-07-02T14:26:01.872Z +- generated_at: 2026-07-02T14:40:35.811Z - cargo_mode: executed - cargo_tests_passed: true - all_gates_passed: true From 5fd7b3e6e4ce7df611ba08b2471ca19c734ba4cd Mon Sep 17 00:00:00 2001 From: mycyg Date: Thu, 2 Jul 2026 22:52:07 +0800 Subject: [PATCH 04/10] =?UTF-8?q?fix(desktop):=20disable=20hidden=20svg=20?= =?UTF-8?q?glass=20filters=20=E5=BE=85=E7=9C=9F=E6=9C=BA=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/liquid-glass-filter.test.ts | 23 +- .../src/liquid-glass-filter.ts | 311 +----------------- apps/desktop-webview/src/pet-surface.test.ts | 7 +- .../desktop-webview/src/spotlight/css.test.ts | 4 +- .../rust-system-i18n-report.json | 6 +- .../smoke-summary.md | 2 +- 6 files changed, 33 insertions(+), 320 deletions(-) diff --git a/apps/desktop-webview/src/liquid-glass-filter.test.ts b/apps/desktop-webview/src/liquid-glass-filter.test.ts index 7f043c633..ed12e2275 100644 --- a/apps/desktop-webview/src/liquid-glass-filter.test.ts +++ b/apps/desktop-webview/src/liquid-glass-filter.test.ts @@ -3,6 +3,7 @@ import test from "node:test"; import { liquidGlassFilterCss, + liquidGlassFilterHtml, rebuildWorkHubLiquidGlassFilters, renderWorkHubLiquidGlassLayer } from "./liquid-glass-filter.js"; @@ -19,14 +20,17 @@ test("liquid glass layer only refracts at the edge, without a colored backing su assert.doesNotMatch(liquidGlassFilterCss, /\.wh-liquid-glass-warp--spotlight \.wh-liquid-glass-refract\{[^}]*backdrop-filter/u); assert.doesNotMatch(liquidGlassFilterCss, /\.wh-liquid-glass-warp--pet \.wh-liquid-glass-refract\{[^}]*-webkit-backdrop-filter/u); assert.doesNotMatch(liquidGlassFilterCss, /\.wh-liquid-glass-warp--spotlight \.wh-liquid-glass-refract\{[^}]*-webkit-backdrop-filter/u); - assert.match(liquidGlassFilterCss, /\.wh-liquid-glass-warp--pet \.wh-liquid-glass-edge\{backdrop-filter:url\(#workhub-liquid-glass-pet-filter\) blur\(var\(--wh-liquid-frost\)\)/u); - assert.match(liquidGlassFilterCss, /\.wh-liquid-glass-warp--spotlight \.wh-liquid-glass-edge\{backdrop-filter:url\(#workhub-liquid-glass-spotlight-filter\) blur\(var\(--wh-liquid-frost\)\)/u); + // 3-4: the old assertions pinned SVG url(#workhub-liquid-glass-*) edge filters, but all + // active desktop consumers hide those layers; keeping the URLs kept a dead generated-map path alive. + assert.doesNotMatch(liquidGlassFilterCss, /url\(#workhub-liquid-glass/u); + assert.doesNotMatch(liquidGlassFilterHtml, / { +test("liquid glass filter rebuild is a no-op while SVG refraction is disabled", () => { let innerHtmlWrites = 0; + let canvasCreates = 0; const defs = { dataset: {} as Record, _innerHTML: "", @@ -58,15 +62,16 @@ test("liquid glass filters are not rewritten when surface geometry is unchanged" const doc = { getElementById: (id: string) => (id === "workhub-liquid-glass-defs" ? defs : null), querySelector: () => element, - createElement: () => canvas + createElement: () => { + canvasCreates += 1; + return canvas; + } } as unknown as Document; rebuildWorkHubLiquidGlassFilters(doc); rebuildWorkHubLiquidGlassFilters(doc); - assert.equal(innerHtmlWrites, 1); - assert.match(defs.innerHTML, /result="edge_mask"/u); - assert.match(defs.innerHTML, /