capture static method
Run the full pipeline: raw capture → normalize → stable IDs → snapshot.
Implementation
static UiSnapshot? capture({
required String screen,
required Rect viewport,
}) {
final raw = TreeCapture.capture(viewport);
if (raw == null) return null;
final norm = TreeNormalizer.normalize(raw, screen: screen);
final ids = StableIdAssigner.assign(norm, screen: screen);
final nodes = <UiNode>[];
final paths = <String, String>{};
final visibleIndex = <int>[];
final viewportArea = viewport.width * viewport.height;
for (var i = 0; i < norm.nodes.length; i++) {
final n = norm.nodes[i];
final stableId = ids.stableIds[i];
final inter = n.bounds.intersect(viewport);
final coverage = viewportArea <= 0 || inter.isEmpty
? 0.0
: (inter.width * inter.height) / viewportArea;
nodes.add(UiNode(
stableId: stableId,
role: n.role,
text: n.text,
normalizedText: n.normalizedText,
normalizedTokens: n.normalizedTokens,
bounds: n.bounds,
scrollable: n.scrollable,
visible: n.visible,
visibleFraction: n.visibleFraction,
layer: n.layer,
overlayId: n.overlayId,
hasAction: n.hasAction,
identifier: n.identifier,
actions: n.actions,
subtreeText: n.subtreeText,
rawId: n.rawId,
selected: n.selected,
value: n.value,
checked: n.checked,
editable: n.editable,
secure: n.secure,
coversViewport: coverage >= kSubtreeTextOmitCoverage,
disabled: n.disabled,
placeholder: n.placeholder,
range: n.range,
parentId: n.parentIndex >= 0 ? ids.stableIds[n.parentIndex] : '',
visual: n.visual,
));
paths[stableId] = ids.paths[i];
if (n.visible) visibleIndex.add(i);
}
return UiSnapshot(
screen: screen,
nodes: nodes,
paths: paths,
visibleIndex: visibleIndex,
capturedAt: DateTime.now().toUtc(),
viewportSize: Size(viewport.width, viewport.height),
overlays: [
for (final overlay in raw.overlays)
if (nodes.any((node) => node.overlayId == overlay.id))
UiOverlay(
id: overlay.id,
key: _overlayKey(overlay, nodes),
kind: overlay.kind,
layer: overlay.id,
bounds: raw.nodes[overlay.rootIndex].bounds,
),
],
);
}