Files
wehub-resource-sync 9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:48 +08:00

61 lines
2.9 KiB
JavaScript

// Shared helpers for trae-solo adapter — panel navigation, pointer chain, etc.
import { CommandExecutionError } from '@jackwener/opencli/errors';
// The 3 sidebar panel entries: 'New task' / 'Skills' / 'Automation'.
// Each renders as a clickable DIV with class .task-list-new-task-item.
export async function switchToPanel(page, panelName) {
const nameJson = JSON.stringify(panelName);
const result = await page.evaluate(`(async () => {
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
const target = ${nameJson};
// Check if already active.
const active = Array.from(document.querySelectorAll('.task-list-new-task-item'))
.find((el) => el.offsetParent && /\\b(task-list-skills-item|task-list-new-task-item-in)\\b/.test(el.className) && el.className.includes('active') && el.textContent.trim() === target);
if (active) return { ok: true, already: true };
const entry = Array.from(document.querySelectorAll('.task-list-new-task-item'))
.find((el) => el.offsetParent && el.textContent.trim() === target);
if (!entry) {
return { ok: false, reason: 'Panel entry not found.', detail: 'wanted=' + target };
}
const r = entry.getBoundingClientRect();
const init = {
bubbles: true, cancelable: true, button: 0, buttons: 1,
clientX: Math.round(r.left + Math.min(30, r.width / 2)),
clientY: Math.round(r.top + Math.min(10, r.height / 2)),
};
entry.dispatchEvent(new PointerEvent('pointerdown', { ...init, pointerType: 'mouse' }));
entry.dispatchEvent(new MouseEvent('mousedown', init));
entry.dispatchEvent(new PointerEvent('pointerup', { ...init, pointerType: 'mouse' }));
entry.dispatchEvent(new MouseEvent('mouseup', init));
entry.dispatchEvent(new MouseEvent('click', init));
await wait(900);
return { ok: true };
})()`);
if (!result?.ok) {
throw new CommandExecutionError(result?.reason || `Could not switch to ${panelName} panel.`, result?.detail || '');
}
return result;
}
// Click a target element using the full pointer-event chain. Useful for
// React + radix components that ignore plain .click().
export async function pointerClickByEval(page, selectorJsExpr) {
return await page.evaluate(`(async () => {
const target = ${selectorJsExpr};
if (!target) return { ok: false, reason: 'target not found' };
const r = target.getBoundingClientRect();
const init = {
bubbles: true, cancelable: true, button: 0, buttons: 1,
clientX: Math.round(r.left + r.width / 2),
clientY: Math.round(r.top + r.height / 2),
};
target.dispatchEvent(new PointerEvent('pointerdown', { ...init, pointerType: 'mouse' }));
target.dispatchEvent(new MouseEvent('mousedown', init));
target.dispatchEvent(new PointerEvent('pointerup', { ...init, pointerType: 'mouse' }));
target.dispatchEvent(new MouseEvent('mouseup', init));
target.dispatchEvent(new MouseEvent('click', init));
return { ok: true };
})()`);
}