返回 DeepSeek-Reasonix
pagePicker.ts
根目录 / desktop / electron / src / main / browser / pagePicker.ts
1 /// <reference lib="dom" />
2 import { pageRegistry } from "./pageSemantic.js";
3
4 export function pageCancelPicker(): void {
5 (window as unknown as { __reasonixCancelPicker?: () => void }).__reasonixCancelPicker?.();
6 }
7
8 export async function pagePickElement(input: { key: string }): Promise<unknown> {
9 const registry = pageRegistry(input.key);
10 const host = window as unknown as { __reasonixCancelPicker?: () => void };
11 host.__reasonixCancelPicker?.();
12 return new Promise(resolve => {
13 const overlay = document.createElement("div");
14 overlay.style.cssText = "position:fixed;pointer-events:none;z-index:2147483647;border:2px solid #4d8dff;background:rgba(77,141,255,.12);box-sizing:border-box;display:none";
15 document.documentElement.append(overlay);
16 let target: Element | null = null;
17 let finished = false;
18 const finish = (result: unknown) => {
19 if (finished) return;
20 finished = true;
21 clearTimeout(timer); overlay.remove();
22 window.removeEventListener("pointermove", move, true);
23 window.removeEventListener("click", click, true);
24 window.removeEventListener("keydown", key, true);
25 for (const name of ["pointerdown", "mousedown", "mouseup"]) window.removeEventListener(name, block, true);
26 if (host.__reasonixCancelPicker === cancel) delete host.__reasonixCancelPicker;
27 resolve(result);
28 };
29 const cancel = () => finish(null);
30 const block = (event: Event) => { if (event.isTrusted) { event.preventDefault(); event.stopImmediatePropagation(); } };
31 const move = (event: PointerEvent) => {
32 if (!event.isTrusted) return;
33 target = event.composedPath().find(node => node instanceof Element && node !== overlay) as Element | undefined ?? null;
34 if (!target) return;
35 const box = target.getBoundingClientRect();
36 Object.assign(overlay.style, { display: "block", left: `${box.x}px`, top: `${box.y}px`, width: `${box.width}px`, height: `${box.height}px` });
37 };
38 const click = (event: MouseEvent) => {
39 if (!event.isTrusted) return;
40 block(event);
41 const element = event.composedPath().find(node => node instanceof Element && node !== overlay) as Element | undefined ?? target;
42 if (!element) return;
43 const box = element.getBoundingClientRect(), style = getComputedStyle(element);
44 const sensitive = element instanceof HTMLInputElement && element.type === "password";
45 finish({ role: registry.kernel.utils.getAriaRole(element), name: registry.kernel.utils.getElementAccessibleNameText(element, false).slice(0, 160), text: sensitive ? "" : (element.textContent ?? "").replace(/\s+/g, " ").trim().slice(0, 300), tag: element.tagName.toLowerCase(), box: { x: box.x, y: box.y, width: box.width, height: box.height }, style: { display: style.display, color: style.color, backgroundColor: style.backgroundColor, fontSize: style.fontSize }, historical: true });
46 };
47 const key = (event: KeyboardEvent) => { if (event.isTrusted && event.key === "Escape") { block(event); cancel(); } };
48 const timer = setTimeout(cancel, 90_000);
49 host.__reasonixCancelPicker = cancel;
50 window.addEventListener("pointermove", move, true);
51 window.addEventListener("click", click, true);
52 window.addEventListener("keydown", key, true);
53 for (const name of ["pointerdown", "mousedown", "mouseup"]) window.addEventListener(name, block, true);
54 });
55 }
56
56 lines TYPESCRIPT