Files
orca/mobile/scripts/hosted-webview-control-point.mjs
T
Jinwoo-H 15d19c308b feat(mobile): move mobile sessions and settings into the hosted page
Session snapshot/feed/activate/close/createBrowser/createTerminal,
quick commands and agent options now run as Desktop mobileWeb.* adapters
behind the generic host-request forwarder instead of shell translators.
Voice, notification, terminal, browser, chat, About and diagnostics
settings render as hosted page routes with native-*/web-* operation
backends. Adds the hosted WebView e2e journeys used to validate them.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-07 04:16:39 -04:00

59 lines
2.0 KiB
JavaScript

import { WebSocket } from 'ws'
import {
evaluateHostedDocumentWithRetry,
readHostedWebViewState
} from './hosted-webview-cdp-session.mjs'
export async function readHostedWebViewControlPoint(
document,
label,
WebSocketCtor = WebSocket,
options = {}
) {
const expression = `(() => {
const element = ${options.matchText === true}
? Array.from(document.querySelectorAll('[role=button]')).find((candidate) => candidate.textContent.trim() === ${JSON.stringify(label)})
: Array.from(document.querySelectorAll('[aria-label]')).find((candidate) => candidate.getAttribute('aria-label') === ${JSON.stringify(label)});
if (!(element instanceof HTMLElement)) return '';
element.scrollIntoView({ block: 'nearest', inline: 'nearest' });
const rect = element.getBoundingClientRect();
const screenWidth = Number(screen.width);
const screenHeight = Number(screen.height);
const viewportTop = Math.max(0, screenHeight - Number(innerHeight));
return JSON.stringify({
x: (rect.left + rect.width / 2) / screenWidth,
y: (viewportTop + rect.top + rect.height / 2) / screenHeight
});
})()`
const value = await evaluateHostedDocumentWithRetry(document, expression, WebSocketCtor)
let point
try {
point = JSON.parse(value)
} catch {
const state = await readHostedWebViewState(document, WebSocketCtor).catch(() => null)
throw new Error(
`Hosted WebView control was not measurable: ${label}. State: ${JSON.stringify({
path: state ? new URL(state.href).pathname : null,
labels: state?.labels?.slice(0, 40),
text: state?.bodyText?.slice(0, 1000)
})}`
)
}
if (!isNormalizedPoint(point)) {
throw new Error(`Hosted WebView returned an invalid control point: ${label}`)
}
return point
}
function isNormalizedPoint(point) {
return (
point &&
Number.isFinite(point.x) &&
Number.isFinite(point.y) &&
point.x >= 0 &&
point.x <= 1 &&
point.y >= 0 &&
point.y <= 1
)
}