execbro 2.3.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/build/__tests__/helpers/fake-cdp-server.d.ts +0 -12
- package/build/__tests__/helpers/fake-cdp-server.d.ts.map +1 -1
- package/build/__tests__/helpers/fake-cdp-server.js +0 -22
- package/build/__tests__/helpers/fake-cdp-server.js.map +1 -1
- package/build/__tests__/helpers/tap-test-helpers.d.ts +0 -23
- package/build/__tests__/helpers/tap-test-helpers.d.ts.map +1 -1
- package/build/__tests__/helpers/tap-test-helpers.js +2 -29
- package/build/__tests__/helpers/tap-test-helpers.js.map +1 -1
- package/build/__tests__/integration/auto-reconnect.test.js +4 -14
- package/build/__tests__/integration/auto-reconnect.test.js.map +1 -1
- package/build/__tests__/integration/connection-health.test.js +1 -10
- package/build/__tests__/integration/connection-health.test.js.map +1 -1
- package/build/__tests__/integration/execute-in-app.test.js +1 -11
- package/build/__tests__/integration/execute-in-app.test.js.map +1 -1
- package/build/__tests__/integration/native-logs.test.js +0 -5
- package/build/__tests__/integration/native-logs.test.js.map +1 -1
- package/build/__tests__/integration/per-call-timeout.test.js +1 -5
- package/build/__tests__/integration/per-call-timeout.test.js.map +1 -1
- package/build/__tests__/integration/socket-close-midflight.test.js +2 -12
- package/build/__tests__/integration/socket-close-midflight.test.js.map +1 -1
- package/build/__tests__/integration/stale-target-probe.test.js +2 -17
- package/build/__tests__/integration/stale-target-probe.test.js.map +1 -1
- package/build/__tests__/integration/tap-strategies.test.js +2 -36
- package/build/__tests__/integration/tap-strategies.test.js.map +1 -1
- package/build/__tests__/integration/text-input.test.js +0 -39
- package/build/__tests__/integration/text-input.test.js.map +1 -1
- package/build/__tests__/integration/tools.test.js +1 -7
- package/build/__tests__/integration/tools.test.js.map +1 -1
- package/build/__tests__/setup.js +0 -2
- package/build/__tests__/setup.js.map +1 -1
- package/build/__tests__/unit/androidEmulatorAvds.test.js +0 -10
- package/build/__tests__/unit/androidEmulatorAvds.test.js.map +1 -1
- package/build/__tests__/unit/androidPinch.test.d.ts +2 -0
- package/build/__tests__/unit/androidPinch.test.d.ts.map +1 -0
- package/build/__tests__/unit/androidPinch.test.js +119 -0
- package/build/__tests__/unit/androidPinch.test.js.map +1 -0
- package/build/__tests__/unit/appContext.test.js +0 -2
- package/build/__tests__/unit/appContext.test.js.map +1 -1
- package/build/__tests__/unit/appRequest.test.js +0 -3
- package/build/__tests__/unit/appRequest.test.js.map +1 -1
- package/build/__tests__/unit/buildToken.test.js +0 -6
- package/build/__tests__/unit/buildToken.test.js.map +1 -1
- package/build/__tests__/unit/burst.test.js +0 -1
- package/build/__tests__/unit/burst.test.js.map +1 -1
- package/build/__tests__/unit/clearLogsNative.test.js +0 -8
- package/build/__tests__/unit/clearLogsNative.test.js.map +1 -1
- package/build/__tests__/unit/componentFormatNaming.test.js +0 -13
- package/build/__tests__/unit/componentFormatNaming.test.js.map +1 -1
- package/build/__tests__/unit/componentSource.test.js +0 -4
- package/build/__tests__/unit/componentSource.test.js.map +1 -1
- package/build/__tests__/unit/componentSourceResolve.test.js +0 -1
- package/build/__tests__/unit/componentSourceResolve.test.js.map +1 -1
- package/build/__tests__/unit/contextWiring.test.js +0 -3
- package/build/__tests__/unit/contextWiring.test.js.map +1 -1
- package/build/__tests__/unit/coordinateMiss.test.js +0 -16
- package/build/__tests__/unit/coordinateMiss.test.js.map +1 -1
- package/build/__tests__/unit/deviceDiscovery.test.js +0 -4
- package/build/__tests__/unit/deviceDiscovery.test.js.map +1 -1
- package/build/__tests__/unit/deviceResolution.test.js +0 -2
- package/build/__tests__/unit/deviceResolution.test.js.map +1 -1
- package/build/__tests__/unit/deviceResolver.test.js +0 -1
- package/build/__tests__/unit/deviceResolver.test.js.map +1 -1
- package/build/__tests__/unit/deviceResolverStaleRetry.test.js +0 -8
- package/build/__tests__/unit/deviceResolverStaleRetry.test.js.map +1 -1
- package/build/__tests__/unit/emulatorBridge.test.d.ts +2 -0
- package/build/__tests__/unit/emulatorBridge.test.d.ts.map +1 -0
- package/build/__tests__/unit/emulatorBridge.test.js +76 -0
- package/build/__tests__/unit/emulatorBridge.test.js.map +1 -0
- package/build/__tests__/unit/emulatorGrpc.test.d.ts +2 -0
- package/build/__tests__/unit/emulatorGrpc.test.d.ts.map +1 -0
- package/build/__tests__/unit/emulatorGrpc.test.js +33 -0
- package/build/__tests__/unit/emulatorGrpc.test.js.map +1 -0
- package/build/__tests__/unit/epochRender.test.js +0 -3
- package/build/__tests__/unit/epochRender.test.js.map +1 -1
- package/build/__tests__/unit/errorCategorization.test.js +0 -18
- package/build/__tests__/unit/errorCategorization.test.js.map +1 -1
- package/build/__tests__/unit/exec.test.js +0 -1
- package/build/__tests__/unit/exec.test.js.map +1 -1
- package/build/__tests__/unit/executor.test.js +0 -15
- package/build/__tests__/unit/executor.test.js.map +1 -1
- package/build/__tests__/unit/findElementTreeReuse.test.js +0 -12
- package/build/__tests__/unit/findElementTreeReuse.test.js.map +1 -1
- package/build/__tests__/unit/fingerprint.test.js +0 -4
- package/build/__tests__/unit/fingerprint.test.js.map +1 -1
- package/build/__tests__/unit/focusedInputTools.test.js +0 -4
- package/build/__tests__/unit/focusedInputTools.test.js.map +1 -1
- package/build/__tests__/unit/getLogsEmptyContract.test.js +0 -30
- package/build/__tests__/unit/getLogsEmptyContract.test.js.map +1 -1
- package/build/__tests__/unit/getLogsNativeSource.test.js +0 -22
- package/build/__tests__/unit/getLogsNativeSource.test.js.map +1 -1
- package/build/__tests__/unit/graphqlOperation.test.d.ts +2 -0
- package/build/__tests__/unit/graphqlOperation.test.d.ts.map +1 -0
- package/build/__tests__/unit/graphqlOperation.test.js +107 -0
- package/build/__tests__/unit/graphqlOperation.test.js.map +1 -0
- package/build/__tests__/unit/inputTarget.test.js +0 -16
- package/build/__tests__/unit/inputTarget.test.js.map +1 -1
- package/build/__tests__/unit/inputTextTool.test.js +0 -3
- package/build/__tests__/unit/inputTextTool.test.js.map +1 -1
- package/build/__tests__/unit/jsLogEvents.test.js +0 -3
- package/build/__tests__/unit/jsLogEvents.test.js.map +1 -1
- package/build/__tests__/unit/keyboardMetrics.test.js +0 -2
- package/build/__tests__/unit/keyboardMetrics.test.js.map +1 -1
- package/build/__tests__/unit/keyboardRaise.test.js +0 -2
- package/build/__tests__/unit/keyboardRaise.test.js.map +1 -1
- package/build/__tests__/unit/licenseGrace.test.js +1 -4
- package/build/__tests__/unit/licenseGrace.test.js.map +1 -1
- package/build/__tests__/unit/logEventFormat.test.js +0 -27
- package/build/__tests__/unit/logEventFormat.test.js.map +1 -1
- package/build/__tests__/unit/logEvents.test.js +1 -5
- package/build/__tests__/unit/logEvents.test.js.map +1 -1
- package/build/__tests__/unit/logGrouping.test.js +0 -2
- package/build/__tests__/unit/logGrouping.test.js.map +1 -1
- package/build/__tests__/unit/logOwnership.test.js +0 -11
- package/build/__tests__/unit/logOwnership.test.js.map +1 -1
- package/build/__tests__/unit/logRelevance.test.js +0 -6
- package/build/__tests__/unit/logRelevance.test.js.map +1 -1
- package/build/__tests__/unit/logSourceAndroid.test.js +0 -4
- package/build/__tests__/unit/logSourceAndroid.test.js.map +1 -1
- package/build/__tests__/unit/logSourceIos.test.js +0 -5
- package/build/__tests__/unit/logSourceIos.test.js.map +1 -1
- package/build/__tests__/unit/logs.test.js +0 -1
- package/build/__tests__/unit/logs.test.js.map +1 -1
- package/build/__tests__/unit/measureComponentTools.test.js +0 -1
- package/build/__tests__/unit/measureComponentTools.test.js.map +1 -1
- package/build/__tests__/unit/metro.test.js +0 -2
- package/build/__tests__/unit/metro.test.js.map +1 -1
- package/build/__tests__/unit/nativeInputValue.test.js +0 -4
- package/build/__tests__/unit/nativeInputValue.test.js.map +1 -1
- package/build/__tests__/unit/nativeLogs.test.js +1 -23
- package/build/__tests__/unit/nativeLogs.test.js.map +1 -1
- package/build/__tests__/unit/navigateVerify.test.js +0 -6
- package/build/__tests__/unit/navigateVerify.test.js.map +1 -1
- package/build/__tests__/unit/navigation.test.js +0 -5
- package/build/__tests__/unit/navigation.test.js.map +1 -1
- package/build/__tests__/unit/networkInterceptor.test.js +0 -2
- package/build/__tests__/unit/networkInterceptor.test.js.map +1 -1
- package/build/__tests__/unit/overlayGuard.test.d.ts +2 -0
- package/build/__tests__/unit/overlayGuard.test.d.ts.map +1 -0
- package/build/__tests__/unit/overlayGuard.test.js +123 -0
- package/build/__tests__/unit/overlayGuard.test.js.map +1 -0
- package/build/__tests__/unit/pendingExecutions.test.js +0 -6
- package/build/__tests__/unit/pendingExecutions.test.js.map +1 -1
- package/build/__tests__/unit/pinchGeometry.test.d.ts +2 -0
- package/build/__tests__/unit/pinchGeometry.test.d.ts.map +1 -0
- package/build/__tests__/unit/pinchGeometry.test.js +139 -0
- package/build/__tests__/unit/pinchGeometry.test.js.map +1 -0
- package/build/__tests__/unit/pinchTool.test.d.ts +2 -0
- package/build/__tests__/unit/pinchTool.test.d.ts.map +1 -0
- package/build/__tests__/unit/pinchTool.test.js +39 -0
- package/build/__tests__/unit/pinchTool.test.js.map +1 -0
- package/build/__tests__/unit/probe.test.js +0 -1
- package/build/__tests__/unit/probe.test.js.map +1 -1
- package/build/__tests__/unit/projectMemory.test.js +6 -7
- package/build/__tests__/unit/projectMemory.test.js.map +1 -1
- package/build/__tests__/unit/projectStore.test.js +2 -2
- package/build/__tests__/unit/projectStore.test.js.map +1 -1
- package/build/__tests__/unit/reloadAppAutoConnect.test.js +0 -9
- package/build/__tests__/unit/reloadAppAutoConnect.test.js.map +1 -1
- package/build/__tests__/unit/rnGlobalsBootstrap.test.js +3 -3
- package/build/__tests__/unit/rnGlobalsBootstrap.test.js.map +1 -1
- package/build/__tests__/unit/routeHistory.test.d.ts +2 -0
- package/build/__tests__/unit/routeHistory.test.d.ts.map +1 -0
- package/build/__tests__/unit/routeHistory.test.js +136 -0
- package/build/__tests__/unit/routeHistory.test.js.map +1 -0
- package/build/__tests__/unit/screenSpace.test.js +30 -13
- package/build/__tests__/unit/screenSpace.test.js.map +1 -1
- package/build/__tests__/unit/screenState.test.js +3 -6
- package/build/__tests__/unit/screenState.test.js.map +1 -1
- package/build/__tests__/unit/screenStateInputValue.test.js +0 -7
- package/build/__tests__/unit/screenStateInputValue.test.js.map +1 -1
- package/build/__tests__/unit/screenStateKeyboard.test.js +0 -1
- package/build/__tests__/unit/screenStateKeyboard.test.js.map +1 -1
- package/build/__tests__/unit/screenshot-diff.test.js +0 -6
- package/build/__tests__/unit/screenshot-diff.test.js.map +1 -1
- package/build/__tests__/unit/sdkMirrorPoller.test.js +0 -8
- package/build/__tests__/unit/sdkMirrorPoller.test.js.map +1 -1
- package/build/__tests__/unit/settleAndDiff.test.js +0 -11
- package/build/__tests__/unit/settleAndDiff.test.js.map +1 -1
- package/build/__tests__/unit/signedVerdict.test.js +0 -5
- package/build/__tests__/unit/signedVerdict.test.js.map +1 -1
- package/build/__tests__/unit/swipeDirection.test.js +6 -9
- package/build/__tests__/unit/swipeDirection.test.js.map +1 -1
- package/build/__tests__/unit/symbolicate.test.js +0 -1
- package/build/__tests__/unit/symbolicate.test.js.map +1 -1
- package/build/__tests__/unit/tap.test.js +2 -40
- package/build/__tests__/unit/tap.test.js.map +1 -1
- package/build/__tests__/unit/textEntry.test.js +0 -27
- package/build/__tests__/unit/textEntry.test.js.map +1 -1
- package/build/__tests__/unit/toolDescriptions.test.js +0 -40
- package/build/__tests__/unit/toolDescriptions.test.js.map +1 -1
- package/build/__tests__/unit/toolsJson.test.js +0 -10
- package/build/__tests__/unit/toolsJson.test.js.map +1 -1
- package/build/__tests__/unit/transportClassify.test.js +0 -20
- package/build/__tests__/unit/transportClassify.test.js.map +1 -1
- package/build/__tests__/unit/truncate.test.js +0 -5
- package/build/__tests__/unit/truncate.test.js.map +1 -1
- package/build/__tests__/unit/usageCache.test.js +0 -3
- package/build/__tests__/unit/usageCache.test.js.map +1 -1
- package/build/__tests__/unit/usageGate.test.js +1 -1
- package/build/__tests__/unit/usageGate.test.js.map +1 -1
- package/build/__tests__/unit/visibility.test.js +0 -8
- package/build/__tests__/unit/visibility.test.js.map +1 -1
- package/build/__tests__/unit/waitForMeasurements.test.js +2 -7
- package/build/__tests__/unit/waitForMeasurements.test.js.map +1 -1
- package/build/bin.js +0 -18
- package/build/bin.js.map +1 -1
- package/build/core/android.d.ts +0 -120
- package/build/core/android.d.ts.map +1 -1
- package/build/core/android.js +4 -259
- package/build/core/android.js.map +1 -1
- package/build/core/androidPinch.d.ts +21 -0
- package/build/core/androidPinch.d.ts.map +1 -0
- package/build/core/androidPinch.js +72 -0
- package/build/core/androidPinch.js.map +1 -0
- package/build/core/androidSystemBars.d.ts +7 -0
- package/build/core/androidSystemBars.d.ts.map +1 -0
- package/build/core/androidSystemBars.js +21 -0
- package/build/core/androidSystemBars.js.map +1 -0
- package/build/core/appContext.d.ts +0 -50
- package/build/core/appContext.d.ts.map +1 -1
- package/build/core/appContext.js +0 -50
- package/build/core/appContext.js.map +1 -1
- package/build/core/appDetection.d.ts +0 -16
- package/build/core/appDetection.d.ts.map +1 -1
- package/build/core/appDetection.js +0 -36
- package/build/core/appDetection.js.map +1 -1
- package/build/core/appRequest.d.ts +0 -12
- package/build/core/appRequest.d.ts.map +1 -1
- package/build/core/appRequest.js +0 -15
- package/build/core/appRequest.js.map +1 -1
- package/build/core/bufferConfig.d.ts +0 -2
- package/build/core/bufferConfig.d.ts.map +1 -1
- package/build/core/bufferConfig.js +0 -2
- package/build/core/bufferConfig.js.map +1 -1
- package/build/core/bundle.js +0 -40
- package/build/core/bundle.js.map +1 -1
- package/build/core/componentSearch.d.ts +0 -19
- package/build/core/componentSearch.d.ts.map +1 -1
- package/build/core/componentSearch.js +1 -22
- package/build/core/componentSearch.js.map +1 -1
- package/build/core/componentSource.d.ts +0 -21
- package/build/core/componentSource.d.ts.map +1 -1
- package/build/core/componentSource.js +0 -27
- package/build/core/componentSource.js.map +1 -1
- package/build/core/componentTree.js +0 -12
- package/build/core/componentTree.js.map +1 -1
- package/build/core/config.d.ts +0 -8
- package/build/core/config.d.ts.map +1 -1
- package/build/core/config.js +0 -10
- package/build/core/config.js.map +1 -1
- package/build/core/connection.d.ts +0 -76
- package/build/core/connection.d.ts.map +1 -1
- package/build/core/connection.js +15 -340
- package/build/core/connection.js.map +1 -1
- package/build/core/connectionState.d.ts +0 -78
- package/build/core/connectionState.d.ts.map +1 -1
- package/build/core/connectionState.js +4 -92
- package/build/core/connectionState.js.map +1 -1
- package/build/core/debugGlobals.js +0 -68
- package/build/core/debugGlobals.js.map +1 -1
- package/build/core/deviceDiscovery.d.ts +0 -5
- package/build/core/deviceDiscovery.d.ts.map +1 -1
- package/build/core/deviceDiscovery.js +0 -12
- package/build/core/deviceDiscovery.js.map +1 -1
- package/build/core/deviceResolver.d.ts +0 -10
- package/build/core/deviceResolver.d.ts.map +1 -1
- package/build/core/deviceResolver.js +0 -54
- package/build/core/deviceResolver.js.map +1 -1
- package/build/core/emulatorBridge.d.ts +17 -0
- package/build/core/emulatorBridge.d.ts.map +1 -0
- package/build/core/emulatorBridge.js +78 -0
- package/build/core/emulatorBridge.js.map +1 -0
- package/build/core/emulatorGrpc.d.ts +14 -0
- package/build/core/emulatorGrpc.d.ts.map +1 -0
- package/build/core/emulatorGrpc.js +93 -0
- package/build/core/emulatorGrpc.js.map +1 -0
- package/build/core/epochRender.d.ts +0 -12
- package/build/core/epochRender.d.ts.map +1 -1
- package/build/core/epochRender.js +0 -12
- package/build/core/epochRender.js.map +1 -1
- package/build/core/errorScreenParser.d.ts +0 -21
- package/build/core/errorScreenParser.d.ts.map +1 -1
- package/build/core/errorScreenParser.js +0 -50
- package/build/core/errorScreenParser.js.map +1 -1
- package/build/core/errors.d.ts +0 -15
- package/build/core/errors.d.ts.map +1 -1
- package/build/core/errors.js +0 -15
- package/build/core/errors.js.map +1 -1
- package/build/core/escapeNonAscii.d.ts +0 -9
- package/build/core/escapeNonAscii.d.ts.map +1 -1
- package/build/core/escapeNonAscii.js +1 -43
- package/build/core/escapeNonAscii.js.map +1 -1
- package/build/core/exec.d.ts +0 -12
- package/build/core/exec.d.ts.map +1 -1
- package/build/core/exec.js +2 -14
- package/build/core/exec.js.map +1 -1
- package/build/core/executor.js +0 -3
- package/build/core/executor.js.map +1 -1
- package/build/core/fastRefreshRecorder.js +0 -4
- package/build/core/fastRefreshRecorder.js.map +1 -1
- package/build/core/fastRefreshTools.js +0 -3
- package/build/core/fastRefreshTools.js.map +1 -1
- package/build/core/feedback.js +0 -4
- package/build/core/feedback.js.map +1 -1
- package/build/core/graphqlOperation.d.ts +13 -0
- package/build/core/graphqlOperation.d.ts.map +1 -0
- package/build/core/graphqlOperation.js +80 -0
- package/build/core/graphqlOperation.js.map +1 -0
- package/build/core/guides.d.ts +0 -10
- package/build/core/guides.d.ts.map +1 -1
- package/build/core/guides.js +18 -12
- package/build/core/guides.js.map +1 -1
- package/build/core/iconSemantics.d.ts +0 -15
- package/build/core/iconSemantics.d.ts.map +1 -1
- package/build/core/iconSemantics.js +0 -31
- package/build/core/iconSemantics.js.map +1 -1
- package/build/core/index.d.ts +2 -0
- package/build/core/index.d.ts.map +1 -1
- package/build/core/index.js +5 -47
- package/build/core/index.js.map +1 -1
- package/build/core/injected/visibility.d.ts +0 -30
- package/build/core/injected/visibility.d.ts.map +1 -1
- package/build/core/injected/visibility.js +0 -33
- package/build/core/injected/visibility.js.map +1 -1
- package/build/core/injectedFilters.d.ts +0 -28
- package/build/core/injectedFilters.d.ts.map +1 -1
- package/build/core/injectedFilters.js +0 -28
- package/build/core/injectedFilters.js.map +1 -1
- package/build/core/inputTarget.d.ts +1 -34
- package/build/core/inputTarget.d.ts.map +1 -1
- package/build/core/inputTarget.js +0 -26
- package/build/core/inputTarget.js.map +1 -1
- package/build/core/inputTargetTools.d.ts +0 -7
- package/build/core/inputTargetTools.d.ts.map +1 -1
- package/build/core/inputTargetTools.js +0 -7
- package/build/core/inputTargetTools.js.map +1 -1
- package/build/core/inspector.d.ts +0 -33
- package/build/core/inspector.d.ts.map +1 -1
- package/build/core/inspector.js +27 -40
- package/build/core/inspector.js.map +1 -1
- package/build/core/ios.d.ts +11 -122
- package/build/core/ios.d.ts.map +1 -1
- package/build/core/ios.js +32 -299
- package/build/core/ios.js.map +1 -1
- package/build/core/jsExecute.d.ts +0 -100
- package/build/core/jsExecute.d.ts.map +1 -1
- package/build/core/jsExecute.js +0 -261
- package/build/core/jsExecute.js.map +1 -1
- package/build/core/jsLogEvents.d.ts +0 -8
- package/build/core/jsLogEvents.d.ts.map +1 -1
- package/build/core/jsLogEvents.js +0 -8
- package/build/core/jsLogEvents.js.map +1 -1
- package/build/core/keyboardMetrics.js +0 -8
- package/build/core/keyboardMetrics.js.map +1 -1
- package/build/core/keyboardRaise.d.ts +0 -8
- package/build/core/keyboardRaise.d.ts.map +1 -1
- package/build/core/keyboardRaise.js +0 -23
- package/build/core/keyboardRaise.js.map +1 -1
- package/build/core/license.d.ts +0 -4
- package/build/core/license.d.ts.map +1 -1
- package/build/core/license.js +2 -55
- package/build/core/license.js.map +1 -1
- package/build/core/logDiagnosis.d.ts +0 -34
- package/build/core/logDiagnosis.d.ts.map +1 -1
- package/build/core/logDiagnosis.js +0 -15
- package/build/core/logDiagnosis.js.map +1 -1
- package/build/core/logEventFormat.d.ts +0 -1
- package/build/core/logEventFormat.d.ts.map +1 -1
- package/build/core/logEventFormat.js +0 -30
- package/build/core/logEventFormat.js.map +1 -1
- package/build/core/logEvents.d.ts +0 -54
- package/build/core/logEvents.d.ts.map +1 -1
- package/build/core/logEvents.js +0 -37
- package/build/core/logEvents.js.map +1 -1
- package/build/core/logGrouping.d.ts +0 -9
- package/build/core/logGrouping.d.ts.map +1 -1
- package/build/core/logGrouping.js +0 -17
- package/build/core/logGrouping.js.map +1 -1
- package/build/core/logOwnership.d.ts +0 -17
- package/build/core/logOwnership.d.ts.map +1 -1
- package/build/core/logOwnership.js +0 -34
- package/build/core/logOwnership.js.map +1 -1
- package/build/core/logRelevance.d.ts +0 -8
- package/build/core/logRelevance.d.ts.map +1 -1
- package/build/core/logRelevance.js +0 -15
- package/build/core/logRelevance.js.map +1 -1
- package/build/core/logSourceAndroid.d.ts +0 -8
- package/build/core/logSourceAndroid.d.ts.map +1 -1
- package/build/core/logSourceAndroid.js +0 -11
- package/build/core/logSourceAndroid.js.map +1 -1
- package/build/core/logSourceIos.d.ts +0 -8
- package/build/core/logSourceIos.d.ts.map +1 -1
- package/build/core/logSourceIos.js +1 -24
- package/build/core/logSourceIos.js.map +1 -1
- package/build/core/logbox.d.ts +0 -30
- package/build/core/logbox.d.ts.map +1 -1
- package/build/core/logbox.js +0 -43
- package/build/core/logbox.js.map +1 -1
- package/build/core/logs.d.ts +0 -6
- package/build/core/logs.d.ts.map +1 -1
- package/build/core/logs.js +0 -19
- package/build/core/logs.js.map +1 -1
- package/build/core/metro.d.ts +0 -14
- package/build/core/metro.d.ts.map +1 -1
- package/build/core/metro.js +1 -32
- package/build/core/metro.js.map +1 -1
- package/build/core/moduleRegistry.d.ts +0 -17
- package/build/core/moduleRegistry.d.ts.map +1 -1
- package/build/core/moduleRegistry.js +0 -17
- package/build/core/moduleRegistry.js.map +1 -1
- package/build/core/nativeInputValue.d.ts +0 -29
- package/build/core/nativeInputValue.d.ts.map +1 -1
- package/build/core/nativeInputValue.js +0 -18
- package/build/core/nativeInputValue.js.map +1 -1
- package/build/core/nativeLogs.d.ts +0 -47
- package/build/core/nativeLogs.d.ts.map +1 -1
- package/build/core/nativeLogs.js +0 -82
- package/build/core/nativeLogs.js.map +1 -1
- package/build/core/nativeOnlyHints.js +0 -4
- package/build/core/nativeOnlyHints.js.map +1 -1
- package/build/core/navigate.d.ts +0 -15
- package/build/core/navigate.d.ts.map +1 -1
- package/build/core/navigate.js +0 -22
- package/build/core/navigate.js.map +1 -1
- package/build/core/navigation.d.ts +0 -60
- package/build/core/navigation.d.ts.map +1 -1
- package/build/core/navigation.js +0 -60
- package/build/core/navigation.js.map +1 -1
- package/build/core/network.d.ts +0 -5
- package/build/core/network.d.ts.map +1 -1
- package/build/core/network.js +10 -31
- package/build/core/network.js.map +1 -1
- package/build/core/networkInterceptor.d.ts +0 -19
- package/build/core/networkInterceptor.d.ts.map +1 -1
- package/build/core/networkInterceptor.js +3 -27
- package/build/core/networkInterceptor.js.map +1 -1
- package/build/core/ocr.d.ts +0 -31
- package/build/core/ocr.d.ts.map +1 -1
- package/build/core/ocr.js +1 -71
- package/build/core/ocr.js.map +1 -1
- package/build/core/paths.js +0 -1
- package/build/core/paths.js.map +1 -1
- package/build/core/pinchGeometry.d.ts +28 -0
- package/build/core/pinchGeometry.d.ts.map +1 -0
- package/build/core/pinchGeometry.js +97 -0
- package/build/core/pinchGeometry.js.map +1 -0
- package/build/core/pinchThresholds.d.ts +14 -0
- package/build/core/pinchThresholds.d.ts.map +1 -0
- package/build/core/pinchThresholds.js +9 -0
- package/build/core/pinchThresholds.js.map +1 -0
- package/build/core/posthog.js +0 -7
- package/build/core/posthog.js.map +1 -1
- package/build/core/pressables.d.ts +0 -25
- package/build/core/pressables.d.ts.map +1 -1
- package/build/core/pressables.js +0 -37
- package/build/core/pressables.js.map +1 -1
- package/build/core/probe.d.ts +0 -9
- package/build/core/probe.d.ts.map +1 -1
- package/build/core/probe.js +0 -9
- package/build/core/probe.js.map +1 -1
- package/build/core/projectMemory.d.ts +0 -2
- package/build/core/projectMemory.d.ts.map +1 -1
- package/build/core/projectMemory.js +2 -7
- package/build/core/projectMemory.js.map +1 -1
- package/build/core/projectStore.d.ts +0 -18
- package/build/core/projectStore.d.ts.map +1 -1
- package/build/core/projectStore.js +0 -19
- package/build/core/projectStore.js.map +1 -1
- package/build/core/promiseHandles.d.ts +0 -13
- package/build/core/promiseHandles.d.ts.map +1 -1
- package/build/core/promiseHandles.js +0 -25
- package/build/core/promiseHandles.js.map +1 -1
- package/build/core/register.js +0 -44
- package/build/core/register.js.map +1 -1
- package/build/core/rnGlobalsBootstrap.d.ts +0 -13
- package/build/core/rnGlobalsBootstrap.d.ts.map +1 -1
- package/build/core/rnGlobalsBootstrap.js +0 -22
- package/build/core/rnGlobalsBootstrap.js.map +1 -1
- package/build/core/routeHistory.d.ts +24 -0
- package/build/core/routeHistory.d.ts.map +1 -0
- package/build/core/routeHistory.js +186 -0
- package/build/core/routeHistory.js.map +1 -0
- package/build/core/screenLayout.d.ts +0 -11
- package/build/core/screenLayout.d.ts.map +1 -1
- package/build/core/screenLayout.js +24 -61
- package/build/core/screenLayout.js.map +1 -1
- package/build/core/screenSpace.d.ts +32 -44
- package/build/core/screenSpace.d.ts.map +1 -1
- package/build/core/screenSpace.js +80 -46
- package/build/core/screenSpace.js.map +1 -1
- package/build/core/screenSpaceDevice.d.ts +0 -8
- package/build/core/screenSpaceDevice.d.ts.map +1 -1
- package/build/core/screenSpaceDevice.js +31 -14
- package/build/core/screenSpaceDevice.js.map +1 -1
- package/build/core/screenState.d.ts +2 -74
- package/build/core/screenState.d.ts.map +1 -1
- package/build/core/screenState.js +204 -145
- package/build/core/screenState.js.map +1 -1
- package/build/core/sdkBridge.js +0 -8
- package/build/core/sdkBridge.js.map +1 -1
- package/build/core/sdkMirrorPoller.d.ts +0 -18
- package/build/core/sdkMirrorPoller.d.ts.map +1 -1
- package/build/core/sdkMirrorPoller.js +0 -47
- package/build/core/sdkMirrorPoller.js.map +1 -1
- package/build/core/selectionBuffer.d.ts +0 -6
- package/build/core/selectionBuffer.d.ts.map +1 -1
- package/build/core/selectionBuffer.js +0 -5
- package/build/core/selectionBuffer.js.map +1 -1
- package/build/core/signedVerdict.js +0 -6
- package/build/core/signedVerdict.js.map +1 -1
- package/build/core/state.d.ts +0 -31
- package/build/core/state.d.ts.map +1 -1
- package/build/core/state.js +0 -57
- package/build/core/state.js.map +1 -1
- package/build/core/symbolicate.js +0 -11
- package/build/core/symbolicate.js.map +1 -1
- package/build/core/telemetry.d.ts +0 -47
- package/build/core/telemetry.d.ts.map +1 -1
- package/build/core/telemetry.js +1 -173
- package/build/core/telemetry.js.map +1 -1
- package/build/core/textEntry.d.ts +0 -34
- package/build/core/textEntry.d.ts.map +1 -1
- package/build/core/textEntry.js +0 -73
- package/build/core/textEntry.js.map +1 -1
- package/build/core/toolHelpers.d.ts +0 -12
- package/build/core/toolHelpers.d.ts.map +1 -1
- package/build/core/toolHelpers.js +2 -47
- package/build/core/toolHelpers.js.map +1 -1
- package/build/core/truncate.d.ts +0 -17
- package/build/core/truncate.d.ts.map +1 -1
- package/build/core/truncate.js +0 -32
- package/build/core/truncate.js.map +1 -1
- package/build/core/types.d.ts +0 -6
- package/build/core/types.d.ts.map +1 -1
- package/build/core/usageCache.js +0 -12
- package/build/core/usageCache.js.map +1 -1
- package/build/index.js +0 -18
- package/build/index.js.map +1 -1
- package/build/pro/coordinateMiss.d.ts +0 -30
- package/build/pro/coordinateMiss.d.ts.map +1 -1
- package/build/pro/coordinateMiss.js +0 -17
- package/build/pro/coordinateMiss.js.map +1 -1
- package/build/pro/overlayGuard.d.ts +27 -0
- package/build/pro/overlayGuard.d.ts.map +1 -0
- package/build/pro/overlayGuard.js +103 -0
- package/build/pro/overlayGuard.js.map +1 -0
- package/build/pro/screenshot-diff.js +4 -6
- package/build/pro/screenshot-diff.js.map +1 -1
- package/build/pro/tap.d.ts +0 -55
- package/build/pro/tap.d.ts.map +1 -1
- package/build/pro/tap.js +72 -316
- package/build/pro/tap.js.map +1 -1
- package/build/pro/usageGate.js +0 -9
- package/build/pro/usageGate.js.map +1 -1
- package/build/pro/usageNotifications.js +1 -13
- package/build/pro/usageNotifications.js.map +1 -1
- package/build/pro/verifyAction.d.ts +0 -13
- package/build/pro/verifyAction.d.ts.map +1 -1
- package/build/pro/verifyAction.js +0 -45
- package/build/pro/verifyAction.js.map +1 -1
- package/build/tools/_deviceArg.d.ts +0 -35
- package/build/tools/_deviceArg.d.ts.map +1 -1
- package/build/tools/_deviceArg.js +0 -35
- package/build/tools/_deviceArg.js.map +1 -1
- package/build/tools/accountTools.js +2 -2
- package/build/tools/accountTools.js.map +1 -1
- package/build/tools/bundleTools.js +0 -16
- package/build/tools/bundleTools.js.map +1 -1
- package/build/tools/componentTools.d.ts.map +1 -1
- package/build/tools/componentTools.js +47 -53
- package/build/tools/componentTools.js.map +1 -1
- package/build/tools/connectionTools.js +1 -59
- package/build/tools/connectionTools.js.map +1 -1
- package/build/tools/deviceTools.js +0 -11
- package/build/tools/deviceTools.js.map +1 -1
- package/build/tools/executionTools.js +1 -18
- package/build/tools/executionTools.js.map +1 -1
- package/build/tools/interactionTools.d.ts +0 -10
- package/build/tools/interactionTools.d.ts.map +1 -1
- package/build/tools/interactionTools.js +190 -59
- package/build/tools/interactionTools.js.map +1 -1
- package/build/tools/logTools.d.ts +0 -13
- package/build/tools/logTools.d.ts.map +1 -1
- package/build/tools/logTools.js +2 -126
- package/build/tools/logTools.js.map +1 -1
- package/build/tools/metaTools.js +0 -10
- package/build/tools/metaTools.js.map +1 -1
- package/build/tools/networkTools.js +4 -43
- package/build/tools/networkTools.js.map +1 -1
- package/build/tools/requestTools.js +0 -5
- package/build/tools/requestTools.js.map +1 -1
- package/build/tools/screenshotTools.js +5 -111
- package/build/tools/screenshotTools.js.map +1 -1
- package/package.json +2 -2
- package/tools.json +16 -1
|
@@ -2,9 +2,6 @@ import { executeInApp, delay } from "./jsExecute.js";
|
|
|
2
2
|
import { iconSemanticHint } from "./iconSemantics.js";
|
|
3
3
|
import { VISIBILITY_HELPERS_JS, detectNativeSheet, NATIVE_SHEET_MARKER_RE_SRC } from "./injected/visibility.js";
|
|
4
4
|
import { RN_PRIMITIVES_SRC, GENERIC_COMPONENT_SRC } from "./injectedFilters.js";
|
|
5
|
-
// ============================================================================
|
|
6
|
-
// Pure helpers (exported for unit tests)
|
|
7
|
-
// ============================================================================
|
|
8
5
|
export function markPressablesCoveredByOverlay(pressables, overlayBounds) {
|
|
9
6
|
for (const p of pressables) {
|
|
10
7
|
const b = p.bounds;
|
|
@@ -17,18 +14,7 @@ export function markPressablesCoveredByOverlay(pressables, overlayBounds) {
|
|
|
17
14
|
}
|
|
18
15
|
return pressables;
|
|
19
16
|
}
|
|
20
|
-
/** A count badge such as "1" or "99+" — the only "label" an icon button like a cart carries. */
|
|
21
17
|
const COUNT_BADGE_LABEL = /^\d{1,3}\+?$/;
|
|
22
|
-
/**
|
|
23
|
-
* Replace component-name fallback labels with semantic icon labels when the
|
|
24
|
-
* pressable's icon child name carries recognizable semantics:
|
|
25
|
-
* { label: "[FloatingHeader]", icon: "SvgChevronBackward" }
|
|
26
|
-
* → label "[SvgChevronBackward — possibly back button]"
|
|
27
|
-
* An icon button whose only text is a count badge (cart with "1") keeps that
|
|
28
|
-
* count as nearby context while the label is upgraded to the icon's meaning:
|
|
29
|
-
* { label: "1", icon: "SvgCartNew" } → label "[SvgCartNew — possibly cart button]", nearbyText "1"
|
|
30
|
-
* Labels from text/a11y are never touched (icon is null for those).
|
|
31
|
-
*/
|
|
32
18
|
export function applyIconHintToLabel(p) {
|
|
33
19
|
if (!p.icon)
|
|
34
20
|
return p;
|
|
@@ -45,20 +31,17 @@ export function applyIconHintToLabel(p) {
|
|
|
45
31
|
return p;
|
|
46
32
|
}
|
|
47
33
|
const identityCoords = (item) => ({ center: item.center, frame: item.bounds });
|
|
48
|
-
/** Stand-in when no keyboard state was read: nothing is blocked. */
|
|
49
34
|
const NO_KEYBOARD = { visible: false, height: null, screenY: null, width: null };
|
|
50
35
|
const TEXT_DISPLAY_MAX = 80;
|
|
51
36
|
const IMAGE_SRC_DISPLAY_MAX = 60;
|
|
52
37
|
function truncate(s, max) {
|
|
53
38
|
return s.length > max ? s.slice(0, max) + "…" : s;
|
|
54
39
|
}
|
|
55
|
-
/** One merged-list line for a static text node — coordinates match pressable lines. */
|
|
56
40
|
export function formatTextEntry(t, convert = identityCoords, opts = {}) {
|
|
57
41
|
const { center, frame } = convert(t);
|
|
58
42
|
const body = opts.fullText ? t.text : truncate(t.text, TEXT_DISPLAY_MAX);
|
|
59
43
|
return ` (${center.x}, ${center.y}) 📝 "${body}" frame:(${frame.x},${frame.y} ${frame.width}x${frame.height})`;
|
|
60
44
|
}
|
|
61
|
-
/** One merged-list line for an image node — coordinates match pressable lines. */
|
|
62
45
|
export function formatImageEntry(img, convert = identityCoords) {
|
|
63
46
|
const { center, frame } = convert(img);
|
|
64
47
|
const src = img.src ? ` src="${truncate(img.src, IMAGE_SRC_DISPLAY_MAX)}"` : "";
|
|
@@ -67,44 +50,17 @@ export function formatImageEntry(img, convert = identityCoords) {
|
|
|
67
50
|
}
|
|
68
51
|
const TEXT_CAP = 60;
|
|
69
52
|
const IMAGE_CAP = 40;
|
|
70
|
-
|
|
71
|
-
* Render a ScreenState as the orientation summary used by get_screen_state and the
|
|
72
|
-
* screenshot tools. By default it merges pressables, static text (📝), and images
|
|
73
|
-
* (🖼) into one spatially-ordered list per reachability group — enough to read and
|
|
74
|
-
* navigate the screen without a screenshot:
|
|
75
|
-
* 📍 Detail [Detail]
|
|
76
|
-
* 🎯 Pressables:
|
|
77
|
-
* (210, 175) 🖼 Image 420x350 src="…"
|
|
78
|
-
* (146, 394) 📝 "Valya product" frame:(20,382 251x24)
|
|
79
|
-
* (210, 838) <Button /> "In cart" frame:(20,810 380x56)
|
|
80
|
-
* pressablesOnly restores the lean pressable-only snapshot; fullText disables the
|
|
81
|
-
* 80-char text truncation.
|
|
82
|
-
*/
|
|
83
|
-
/**
|
|
84
|
-
* One line describing the keyboard, or "" when it is down and known to be.
|
|
85
|
-
*
|
|
86
|
-
* The point is layout validation: a raised keyboard shrinks the usable area,
|
|
87
|
-
* and that is exactly when bottom-anchored UI misbehaves. Reporting the height
|
|
88
|
-
* and the remaining content area makes that inspectable without a screenshot.
|
|
89
|
-
*/
|
|
90
|
-
export function formatKeyboardLine(k) {
|
|
53
|
+
export function formatKeyboardLine(k, pixelScale = 1) {
|
|
91
54
|
if (k.error)
|
|
92
55
|
return `⌨️ Keyboard: unknown (${k.error})`;
|
|
93
56
|
if (!k.visible || k.height == null || k.screenY == null)
|
|
94
57
|
return "";
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const
|
|
58
|
+
const s = pixelScale > 0 ? pixelScale : 1;
|
|
59
|
+
const r = (n) => Math.round(n * s);
|
|
60
|
+
const unit = s === 1 ? "pt" : "px";
|
|
98
61
|
const width = k.width != null ? `${r(k.width)}x` : "";
|
|
99
|
-
return `⌨️ Keyboard: visible, ${r(k.height)}
|
|
62
|
+
return `⌨️ Keyboard: visible, ${r(k.height)}${unit} — content area above it ${width}${r(k.screenY)}${unit}`;
|
|
100
63
|
}
|
|
101
|
-
/**
|
|
102
|
-
* Splits elements the keyboard covers from those still reachable.
|
|
103
|
-
*
|
|
104
|
-
* Mirrors the existing overlay handling rather than inventing a second notion
|
|
105
|
-
* of "blocked": an element under the keyboard cannot be tapped, for the same
|
|
106
|
-
* reason and with the same consequence as one under a sheet.
|
|
107
|
-
*/
|
|
108
64
|
export function partitionByKeyboard(items, k) {
|
|
109
65
|
if (!k.visible || k.screenY == null)
|
|
110
66
|
return { reachable: items, blocked: [] };
|
|
@@ -115,18 +71,11 @@ export function partitionByKeyboard(items, k) {
|
|
|
115
71
|
}
|
|
116
72
|
return { reachable, blocked };
|
|
117
73
|
}
|
|
118
|
-
/**
|
|
119
|
-
* Renders an input's state so the value is unmistakably the value and the
|
|
120
|
-
* placeholder is unmistakably a placeholder. Returns "" for non-inputs.
|
|
121
|
-
*/
|
|
122
74
|
export function formatInputState(p) {
|
|
123
75
|
if (!p.isInput)
|
|
124
76
|
return "";
|
|
125
77
|
if (p.inputValue)
|
|
126
78
|
return ` [input] value:${JSON.stringify(p.inputValue)}`;
|
|
127
|
-
// inputValue/inputPlaceholder are absent on entries captured before this
|
|
128
|
-
// field existed (or by other producers); fall back to the bare marker
|
|
129
|
-
// rather than asserting the field is empty.
|
|
130
79
|
if (p.inputValue === undefined && p.inputPlaceholder === undefined)
|
|
131
80
|
return " [input]";
|
|
132
81
|
return p.inputPlaceholder
|
|
@@ -146,7 +95,7 @@ export function formatScreenStateSummary(ss, convert = identityCoords, opts = {}
|
|
|
146
95
|
lines.push("📍 Currently focused screen: unknown (no React Navigation / Expo Router detected)");
|
|
147
96
|
}
|
|
148
97
|
if (opts.keyboard) {
|
|
149
|
-
const kbLine = formatKeyboardLine(opts.keyboard);
|
|
98
|
+
const kbLine = formatKeyboardLine(opts.keyboard, opts.pixelScale);
|
|
150
99
|
if (kbLine)
|
|
151
100
|
lines.push(kbLine);
|
|
152
101
|
}
|
|
@@ -161,17 +110,12 @@ export function formatScreenStateSummary(ss, convert = identityCoords, opts = {}
|
|
|
161
110
|
}
|
|
162
111
|
const formatPressable = (p) => {
|
|
163
112
|
const { center, frame } = convert(p);
|
|
164
|
-
// 🔘 marks tap targets in the enriched view (where 📝 text / 🖼 images also
|
|
165
|
-
// appear); omitted under pressablesOnly to keep the lean legacy lines.
|
|
166
113
|
const marker = opts.pressablesOnly ? "" : " 🔘";
|
|
167
114
|
return ` (${center.x}, ${center.y})${marker}${p.component ? ` <${p.component} />` : ""} ${p.label ? `"${p.label}"` : "(unlabeled)"}` +
|
|
168
115
|
`${p.nearbyText ? ` near "${p.nearbyText}"` : ""}${p.onPressHint ? ` ${p.onPressHint}` : ""}` +
|
|
169
116
|
`${p.testID ? ` testID="${p.testID}"` : ""}${formatInputState(p)}` +
|
|
170
117
|
` frame:(${frame.x},${frame.y} ${frame.width}x${frame.height})`;
|
|
171
118
|
};
|
|
172
|
-
// Merge pressables + (unless pressablesOnly) texts + images for one reachability
|
|
173
|
-
// group, sorted spatially (top→bottom, then left→right). A text duplicating a
|
|
174
|
-
// pressable's nearbyText is dropped; texts/images cap with an explicit marker.
|
|
175
119
|
const renderGroup = (pressables, texts, images) => {
|
|
176
120
|
const out = [];
|
|
177
121
|
const nearby = new Set(pressables.map((p) => (p.nearbyText || "").trim()).filter(Boolean));
|
|
@@ -195,9 +139,6 @@ export function formatScreenStateSummary(ss, convert = identityCoords, opts = {}
|
|
|
195
139
|
}
|
|
196
140
|
return out;
|
|
197
141
|
};
|
|
198
|
-
// A native sheet has no entry in ss.overlays (it's not in the fiber-measured tree), but
|
|
199
|
-
// it flags the underlying pressables blockedByOverlay — so take the split reachable/blocked
|
|
200
|
-
// path even when overlays is empty, so those flags surface in the summary.
|
|
201
142
|
if (ss.overlays.length > 0 || ss.nativeOverlay) {
|
|
202
143
|
for (const overlay of ss.overlays) {
|
|
203
144
|
lines.push(`\n🔲 ${overlay.type}${overlay.title ? ` — "${overlay.title}"` : ""}:`);
|
|
@@ -227,8 +168,6 @@ export function formatScreenStateSummary(ss, convert = identityCoords, opts = {}
|
|
|
227
168
|
}
|
|
228
169
|
}
|
|
229
170
|
else {
|
|
230
|
-
// A raised keyboard blocks taps exactly as an overlay does, so it gets
|
|
231
|
-
// the same treatment rather than a second notion of "blocked".
|
|
232
171
|
const kb = opts.keyboard;
|
|
233
172
|
const splitP = partitionByKeyboard(ss.pressables, kb ?? NO_KEYBOARD);
|
|
234
173
|
const splitT = partitionByKeyboard(ss.texts, kb ?? NO_KEYBOARD);
|
|
@@ -246,14 +185,6 @@ export function formatScreenStateSummary(ss, convert = identityCoords, opts = {}
|
|
|
246
185
|
}
|
|
247
186
|
return lines.join("\n");
|
|
248
187
|
}
|
|
249
|
-
/**
|
|
250
|
-
* Turn raw onPress handler info ({ n: fn.name, s: source head }) into a
|
|
251
|
-
* displayable hint, or null when nothing meaningful survives:
|
|
252
|
-
* - real names ("handleSubmit", "bound goBack") → "handleSubmit()" / "goBack()"
|
|
253
|
-
* - generic/minified names ("onPress", "anonymous", "t12") are rejected
|
|
254
|
-
* - anonymous with retained source → "{() => setAccepted(prev => !prev)…}"
|
|
255
|
-
* - Hermes bytecode bundles (source = "[bytecode]", stripped in-app) → null
|
|
256
|
-
*/
|
|
257
188
|
const GENERIC_HANDLER_NAMES = new Set(["", "anonymous", "onpress", "onclick", "handler", "callback", "fn", "press", "value"]);
|
|
258
189
|
function meaningfulHandlerName(n) {
|
|
259
190
|
let name = (n || "").trim();
|
|
@@ -262,7 +193,7 @@ function meaningfulHandlerName(n) {
|
|
|
262
193
|
if (!name || GENERIC_HANDLER_NAMES.has(name.toLowerCase()))
|
|
263
194
|
return null;
|
|
264
195
|
if (/^[a-zA-Z_$]\d{1,4}$/.test(name) || name.length === 1)
|
|
265
|
-
return null;
|
|
196
|
+
return null;
|
|
266
197
|
return name;
|
|
267
198
|
}
|
|
268
199
|
export function describePressHandler(raw) {
|
|
@@ -277,17 +208,6 @@ export function describePressHandler(raw) {
|
|
|
277
208
|
return `{${src.length > 70 ? src.slice(0, 70) + "…" : src}}`;
|
|
278
209
|
return null;
|
|
279
210
|
}
|
|
280
|
-
/**
|
|
281
|
-
* Fallback handler context from the custom component's on* props, for when the
|
|
282
|
-
* direct onPress is anonymous (Hermes discards source even in dev bundles, and
|
|
283
|
-
* names like navigation.goBack are lost to computed assignment):
|
|
284
|
-
* - only trust the prop whose value IS the touchable's onPress (pass-through);
|
|
285
|
-
* a non-matched candidate is an unverifiable guess that mislabels every button
|
|
286
|
-
* in a multi-button container (FloatingHeader exposes only onBack, but its menu
|
|
287
|
-
* and cart buttons run internal handlers) — so it yields null
|
|
288
|
-
* - named fn → "onBack=goBack()"; nameless → "onPress→onBack" (the prop name
|
|
289
|
-
* alone is greppable context); a bare nameless "onPress" prop adds nothing → null
|
|
290
|
-
*/
|
|
291
211
|
export function describePropHandlers(raw) {
|
|
292
212
|
if (!Array.isArray(raw) || raw.length === 0)
|
|
293
213
|
return null;
|
|
@@ -318,9 +238,6 @@ export function parseScreenStateResponse(raw) {
|
|
|
318
238
|
notes: r.notes ?? [],
|
|
319
239
|
};
|
|
320
240
|
}
|
|
321
|
-
// ============================================================================
|
|
322
|
-
// Main function (dispatch phase — Task 3; resolve phase added in Task 4)
|
|
323
|
-
// ============================================================================
|
|
324
241
|
export async function getScreenState(options = {}) {
|
|
325
242
|
const { device } = options;
|
|
326
243
|
const dispatchExpression = `
|
|
@@ -618,6 +535,83 @@ export async function getScreenState(options = {}) {
|
|
|
618
535
|
return 'Unknown';
|
|
619
536
|
}
|
|
620
537
|
|
|
538
|
+
// style can be an object, a nested array, or null. Only the flattened result can be
|
|
539
|
+
// asked about position/backgroundColor, and the previous heuristic read the raw prop —
|
|
540
|
+
// so any component passing style={[base, override]} was silently skipped.
|
|
541
|
+
function flattenStyle(s) {
|
|
542
|
+
if (!s) return null;
|
|
543
|
+
if (Array.isArray(s)) {
|
|
544
|
+
var out = null;
|
|
545
|
+
for (var fi = 0; fi < s.length; fi++) {
|
|
546
|
+
var f = flattenStyle(s[fi]);
|
|
547
|
+
if (!f) continue;
|
|
548
|
+
if (!out) out = {};
|
|
549
|
+
for (var k in f) out[k] = f[k];
|
|
550
|
+
}
|
|
551
|
+
return out;
|
|
552
|
+
}
|
|
553
|
+
return typeof s === 'object' ? s : null;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// "Opaque enough to hide what is behind it." Colours reach the fiber either as CSS
|
|
557
|
+
// strings or, on Fabric, as processed ARGB integers; both carry the alpha that decides
|
|
558
|
+
// whether this is a cover or just a tint. A translucent scrim is deliberately NOT a
|
|
559
|
+
// cover — the screen shows through it and its elements stay readable.
|
|
560
|
+
function isOpaqueBackground(st) {
|
|
561
|
+
if (st.opacity != null && st.opacity < 0.95) return false;
|
|
562
|
+
var bg = st.backgroundColor;
|
|
563
|
+
if (bg == null) return false;
|
|
564
|
+
if (typeof bg === 'number') return ((bg >>> 24) & 255) >= 242;
|
|
565
|
+
if (typeof bg !== 'string') return false;
|
|
566
|
+
var v = bg.replace(/\\s/g, '').toLowerCase();
|
|
567
|
+
if (v === 'transparent') return false;
|
|
568
|
+
var m = v.match(/^rgba\\(([^)]*)\\)$/);
|
|
569
|
+
if (m) {
|
|
570
|
+
var parts = m[1].split(',');
|
|
571
|
+
if (parts.length === 4 && parseFloat(parts[3]) < 0.95) return false;
|
|
572
|
+
}
|
|
573
|
+
if (v.charAt(0) === '#' && (v.length === 9 || v.length === 5)) {
|
|
574
|
+
var hex = v.length === 9 ? v.slice(7, 9) : (v.charAt(4) + v.charAt(4));
|
|
575
|
+
var alpha = parseInt(hex, 16);
|
|
576
|
+
if (!isNaN(alpha) && alpha < 242) return false;
|
|
577
|
+
}
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// The opaque surface is usually NOT on the positioned node. The common shape is a
|
|
582
|
+
// transparent absolutely-positioned wrapper whose child paints the panel — a bottom
|
|
583
|
+
// sheet is typically an absolute View wrapping an inner (often animated) View that
|
|
584
|
+
// carries the opaque backgroundColor. Inspecting only the wrapper's own style (the
|
|
585
|
+
// first version of this rule) therefore recognises almost no real sheet.
|
|
586
|
+
function hasOpaqueSurface(fiber, ownStyle) {
|
|
587
|
+
// A wrapper that is itself faded out is not covering anything, whatever its
|
|
588
|
+
// children declare.
|
|
589
|
+
if (ownStyle && ownStyle.opacity != null && ownStyle.opacity < 0.95) return false;
|
|
590
|
+
if (ownStyle && isOpaqueBackground(ownStyle)) return true;
|
|
591
|
+
var found = false;
|
|
592
|
+
(function scan(n, d) {
|
|
593
|
+
if (!n || d > 4 || found) return;
|
|
594
|
+
if (typeof n.type === 'string') {
|
|
595
|
+
var st = flattenStyle(n.memoizedProps && n.memoizedProps.style);
|
|
596
|
+
if (st && isOpaqueBackground(st)) { found = true; return; }
|
|
597
|
+
}
|
|
598
|
+
scan(n.child, d + 1);
|
|
599
|
+
if (!found) scan(n.sibling, d);
|
|
600
|
+
})(fiber.child, 0);
|
|
601
|
+
return found;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
function hasPressableDescendant(f) {
|
|
605
|
+
var found = false;
|
|
606
|
+
(function scan(n, d) {
|
|
607
|
+
if (!n || d > 12 || found) return;
|
|
608
|
+
if (n.memoizedProps && typeof n.memoizedProps.onPress === 'function') { found = true; return; }
|
|
609
|
+
scan(n.child, d + 1);
|
|
610
|
+
if (!found) scan(n.sibling, d);
|
|
611
|
+
})(f.child, 0);
|
|
612
|
+
return found;
|
|
613
|
+
}
|
|
614
|
+
|
|
621
615
|
// Walk to find viewport dimensions (reused for heuristic overlay detection)
|
|
622
616
|
var viewportW = 9999, viewportH = 9999;
|
|
623
617
|
var rootHostFiber = findFirstHost(roots[0].current, 0);
|
|
@@ -660,35 +654,35 @@ export async function getScreenState(options = {}) {
|
|
|
660
654
|
}
|
|
661
655
|
}
|
|
662
656
|
|
|
663
|
-
//
|
|
664
|
-
//
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
657
|
+
// Geometric occluder: an opaque, absolutely-positioned host view holding at least
|
|
658
|
+
// one pressable. This is the branch that catches a sheet mounted as an ordinary
|
|
659
|
+
// view rather than as a Modal, a BottomSheet or a native presentation — a
|
|
660
|
+
// third-party in-app devtool panel, a hand-rolled dialog — which none of the
|
|
661
|
+
// name/prop classifiers above can recognise. Without it every element underneath
|
|
662
|
+
// such a sheet is reported as reachable and taps on them silently hit the sheet.
|
|
663
|
+
//
|
|
664
|
+
// Two deliberate changes from the rule this replaces:
|
|
665
|
+
// - the size test moves to the resolve pass, which works on MEASURED frames.
|
|
666
|
+
// Requiring literal numeric style.width/height here missed every sheet sized
|
|
667
|
+
// by flex, percentages or an animated value, which is nearly all of them.
|
|
668
|
+
// - opacity is required. A translucent scrim leaves the screen visible and its
|
|
669
|
+
// elements legitimately reachable, so it must not count as a cover.
|
|
670
|
+
// react-native-screens wraps every route in an absolutely-positioned, opaque
|
|
671
|
+
// container full of pressables — structurally identical to a sheet and, measured,
|
|
672
|
+
// 78% of the viewport. It is a route container, never an overlay: a screen
|
|
673
|
+
// presented ON TOP of another is caught by the stackPresentation branch above,
|
|
674
|
+
// which runs first. Excluding the family here is what keeps the whole visible
|
|
675
|
+
// screen from being filed under an overlay group.
|
|
676
|
+
var NAV_CONTAINER_HOST = /^RNS/;
|
|
677
|
+
if (typeof fiber.type === 'string' && !NAV_CONTAINER_HOST.test(fiber.type)) {
|
|
678
|
+
var style = flattenStyle(props.style);
|
|
679
|
+
if (style && (style.zIndex > 999 || style.position === 'absolute') &&
|
|
680
|
+
hasOpaqueSurface(fiber, style) && hasPressableDescendant(fiber)) {
|
|
681
|
+
var hosts2 = [];
|
|
682
|
+
findHostsInSubtree(fiber, 0, hosts2, 64);
|
|
683
|
+
if (hosts2.length > 0) {
|
|
684
|
+
overlayFiberMeta.push({ type: 'Unknown', fiber: fiber, hostFibers: hosts2, geometric: true });
|
|
685
|
+
return;
|
|
692
686
|
}
|
|
693
687
|
}
|
|
694
688
|
}
|
|
@@ -708,6 +702,8 @@ export async function getScreenState(options = {}) {
|
|
|
708
702
|
|
|
709
703
|
var hostFibers = [];
|
|
710
704
|
var fiberMeta = [];
|
|
705
|
+
// overlayFiberMeta index -> fiberMeta index at which that overlay's subtree was entered.
|
|
706
|
+
var overlayEnterIdx = [];
|
|
711
707
|
// A count badge ("1", "99+") is the only text on icon buttons like a cart — treat it
|
|
712
708
|
// as no-own-label so the icon child still surfaces (the count is kept as nearby text).
|
|
713
709
|
var COUNT_BADGE = /^\\d{1,3}\\+?$/;
|
|
@@ -886,7 +882,17 @@ export async function getScreenState(options = {}) {
|
|
|
886
882
|
// geometric containment wrongly swallows the underlying screen's pressables.
|
|
887
883
|
if (ovIdx == null) {
|
|
888
884
|
for (var ofi = 0; ofi < overlayFiberMeta.length; ofi++) {
|
|
889
|
-
if (overlayFiberMeta[ofi].fiber === fiber) {
|
|
885
|
+
if (overlayFiberMeta[ofi].fiber === fiber) {
|
|
886
|
+
ovIdx = ofi;
|
|
887
|
+
// Paint position of the overlay, expressed on the same counter as the
|
|
888
|
+
// pressables. This walk is DFS pre-order over siblings in order, which
|
|
889
|
+
// is RN's paint order, so "collected earlier" == "painted underneath".
|
|
890
|
+
// Anything collected AFTER the overlay is drawn on top of it and must
|
|
891
|
+
// not be reported as blocked by it — a LogBox banner over a sheet, a
|
|
892
|
+
// toast over a dialog.
|
|
893
|
+
if (overlayEnterIdx[ofi] == null) overlayEnterIdx[ofi] = fiberMeta.length;
|
|
894
|
+
break;
|
|
895
|
+
}
|
|
890
896
|
}
|
|
891
897
|
}
|
|
892
898
|
|
|
@@ -1155,7 +1161,7 @@ export async function getScreenState(options = {}) {
|
|
|
1155
1161
|
|
|
1156
1162
|
// Store overlay host fibers separately
|
|
1157
1163
|
var overlayHostFibers = [];
|
|
1158
|
-
var overlayMetaList = overlayFiberMeta.map(function(om) {
|
|
1164
|
+
var overlayMetaList = overlayFiberMeta.map(function(om, omIdx) {
|
|
1159
1165
|
var startIdx = overlayHostFibers.length;
|
|
1160
1166
|
for (var hi = 0; hi < om.hostFibers.length; hi++) {
|
|
1161
1167
|
overlayHostFibers.push(om.hostFibers[hi]);
|
|
@@ -1166,7 +1172,11 @@ export async function getScreenState(options = {}) {
|
|
|
1166
1172
|
title: (title && title.length > 2) ? title.slice(0, 60) : null,
|
|
1167
1173
|
hostStart: startIdx,
|
|
1168
1174
|
hostEnd: overlayHostFibers.length,
|
|
1169
|
-
fullCover: !!om.fullCover
|
|
1175
|
+
fullCover: !!om.fullCover,
|
|
1176
|
+
geometric: !!om.geometric,
|
|
1177
|
+
// null means "never entered during the pressable walk" — treat as painted last
|
|
1178
|
+
// (Infinity) so a subtree with no pressables of its own cannot block anything.
|
|
1179
|
+
enterIdx: overlayEnterIdx[omIdx] == null ? -1 : overlayEnterIdx[omIdx]
|
|
1170
1180
|
};
|
|
1171
1181
|
});
|
|
1172
1182
|
|
|
@@ -1240,7 +1250,7 @@ export async function getScreenState(options = {}) {
|
|
|
1240
1250
|
if (dp.error)
|
|
1241
1251
|
return { success: false, error: dp.error };
|
|
1242
1252
|
}
|
|
1243
|
-
catch {
|
|
1253
|
+
catch { }
|
|
1244
1254
|
await delay(300);
|
|
1245
1255
|
const resolveExpression = `
|
|
1246
1256
|
(function() {
|
|
@@ -1311,6 +1321,26 @@ export async function getScreenState(options = {}) {
|
|
|
1311
1321
|
if (mm.y + mm.height > cMaxY) cMaxY = mm.y + mm.height;
|
|
1312
1322
|
}
|
|
1313
1323
|
if (!bValid) continue;
|
|
1324
|
+
// Size gate for geometric candidates, applied here because this is the first
|
|
1325
|
+
// point where a measured frame exists.
|
|
1326
|
+
//
|
|
1327
|
+
// The upper bound is the important half. A candidate covering essentially the
|
|
1328
|
+
// whole viewport is far more likely to be a screen container (react-native-screens
|
|
1329
|
+
// wraps routes in absoluteFill views, which are opaque and full of pressables)
|
|
1330
|
+
// than a sheet, and promoting one to "overlay" would file the entire visible
|
|
1331
|
+
// screen under an overlay group. Genuine full-screen covers arrive as Modal or as
|
|
1332
|
+
// a covering stackPresentation and are classified above, before this branch runs.
|
|
1333
|
+
if (om.geometric) {
|
|
1334
|
+
var gArea = (bMaxX - bMinX) * (bMaxY - bMinY);
|
|
1335
|
+
if (!(vArea > 0) || gArea < vArea * 0.15 || gArea > vArea * 0.92) continue;
|
|
1336
|
+
// A closed drawer is an opaque, absolutely-positioned, pressable-filled panel
|
|
1337
|
+
// that happens to be parked off-screen (measured at x = -width). It covers
|
|
1338
|
+
// nothing until it slides in, so candidacy has to be judged on the visible
|
|
1339
|
+
// intersection rather than the panel's own size.
|
|
1340
|
+
var visW = Math.min(bMaxX, viewportW) - Math.max(bMinX, 0);
|
|
1341
|
+
var visH = Math.min(bMaxY, viewportH) - Math.max(bMinY, 0);
|
|
1342
|
+
if (visW <= 0 || visH <= 0 || (visW * visH) < gArea * 0.6) continue;
|
|
1343
|
+
}
|
|
1314
1344
|
// Native covering modals occlude the whole screen — expand their block region to
|
|
1315
1345
|
// the full viewport so elements that extend past the modal's measured content
|
|
1316
1346
|
// frame (e.g. the bottom tab bar) are still flagged as blocked, not reachable.
|
|
@@ -1323,7 +1353,14 @@ export async function getScreenState(options = {}) {
|
|
|
1323
1353
|
var contentBounds = cValid
|
|
1324
1354
|
? { x: Math.round(cMinX), y: Math.round(cMinY), width: Math.round(cMaxX - cMinX), height: Math.round(cMaxY - cMinY) }
|
|
1325
1355
|
: blockBounds;
|
|
1326
|
-
|
|
1356
|
+
// Geometric overlays never adopt by geometry. A classified overlay may portal its
|
|
1357
|
+
// content elsewhere in the tree, so containment is a needed fallback for it; a
|
|
1358
|
+
// geometric candidate is a plain in-tree view whose content is exactly its fiber
|
|
1359
|
+
// descendants. Letting it claim everything inside its rect would file the bottom
|
|
1360
|
+
// tab bar as part of the sheet drawn over it, when the truth is the opposite —
|
|
1361
|
+
// the tab bar is behind it and blocked.
|
|
1362
|
+
var geometric = !!om.geometric;
|
|
1363
|
+
overlays.push({ origIdx: oi, type: om.type, title: om.title, blockBounds: blockBounds, contentBounds: contentBounds, hasContent: cValid && !geometric, geometric: geometric, enterIdx: om.enterIdx, pressables: [] });
|
|
1327
1364
|
}
|
|
1328
1365
|
|
|
1329
1366
|
// Build pressable list
|
|
@@ -1335,6 +1372,9 @@ export async function getScreenState(options = {}) {
|
|
|
1335
1372
|
if (m.x + m.width < 0 || m.y + m.height < 0) continue;
|
|
1336
1373
|
if (m.x > viewportW || m.y > viewportH) continue;
|
|
1337
1374
|
allPressables.push({
|
|
1375
|
+
// Position in the DFS collection order == paint order. Kept so occlusion can
|
|
1376
|
+
// ask "was this drawn before the overlay?" rather than only "is it inside it?".
|
|
1377
|
+
paintIdx: i,
|
|
1338
1378
|
label: meta[i].label,
|
|
1339
1379
|
component: meta[i].component || null,
|
|
1340
1380
|
center: { x: Math.round(m.x + m.width / 2), y: Math.round(m.y + m.height / 2) },
|
|
@@ -1402,6 +1442,37 @@ export async function getScreenState(options = {}) {
|
|
|
1402
1442
|
b.x + b.width <= ob.x + ob.width &&
|
|
1403
1443
|
b.y + b.height <= ob.y + ob.height;
|
|
1404
1444
|
}
|
|
1445
|
+
|
|
1446
|
+
// A geometric candidate has to earn its place: it must either own pressable content or
|
|
1447
|
+
// actually cover something. The name-based classifiers describe a real widget whether
|
|
1448
|
+
// or not it currently holds a button, but "opaque absolute view" is a guess, and a
|
|
1449
|
+
// guess that occludes nothing buys no information — it only adds an empty overlay
|
|
1450
|
+
// group to the output and invites the reader to treat a plain view as a sheet.
|
|
1451
|
+
// True when this overlay is painted over that pressable: the pressable is inside its
|
|
1452
|
+
// rect, is not part of its own subtree, and was collected before it.
|
|
1453
|
+
function occludes(o, p) {
|
|
1454
|
+
return p.overlayIdx !== o.origIdx &&
|
|
1455
|
+
o.enterIdx >= 0 && p.paintIdx < o.enterIdx &&
|
|
1456
|
+
inside(p.bounds, o.blockBounds);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
var keptOverlays = [];
|
|
1460
|
+
for (var fo = 0; fo < overlays.length; fo++) {
|
|
1461
|
+
var cand = overlays[fo];
|
|
1462
|
+
if (!cand.geometric) { keptOverlays.push(cand); continue; }
|
|
1463
|
+
// A geometric candidate must actually cover something that is not its own content.
|
|
1464
|
+
// Owning pressables is NOT enough: react-native-screens wraps every route in an
|
|
1465
|
+
// absolutely-positioned container that paints an opaque background and is full of
|
|
1466
|
+
// pressables, and promoting one to "overlay" files the whole visible screen under
|
|
1467
|
+
// an overlay group and empties the reachable list. Occluding a foreign element is
|
|
1468
|
+
// what distinguishes a sheet from a screen container.
|
|
1469
|
+
var earns = false;
|
|
1470
|
+
for (var cp = 0; cp < allPressables.length && !earns; cp++) {
|
|
1471
|
+
if (occludes(cand, allPressables[cp])) earns = true;
|
|
1472
|
+
}
|
|
1473
|
+
if (earns) keptOverlays.push(cand);
|
|
1474
|
+
}
|
|
1475
|
+
overlays = keptOverlays;
|
|
1405
1476
|
for (var pi = 0; pi < allPressables.length; pi++) {
|
|
1406
1477
|
var p = allPressables[pi];
|
|
1407
1478
|
var assignedToOverlay = false;
|
|
@@ -1417,7 +1488,14 @@ export async function getScreenState(options = {}) {
|
|
|
1417
1488
|
// Covered pressables stay in the list but are flagged — agents see what's
|
|
1418
1489
|
// behind the sheet while knowing taps won't reach it until it closes.
|
|
1419
1490
|
for (var ov2 = 0; ov2 < overlays.length; ov2++) {
|
|
1420
|
-
|
|
1491
|
+
// Geometric overlays respect paint order, so a banner drawn on top of a
|
|
1492
|
+
// sheet is not reported as hidden by it. The name-classified overlays keep
|
|
1493
|
+
// the original containment-only rule: a Modal or a native sheet occludes
|
|
1494
|
+
// what is behind it regardless of where its subtree sits in the walk.
|
|
1495
|
+
var blocks = overlays[ov2].geometric
|
|
1496
|
+
? occludes(overlays[ov2], p)
|
|
1497
|
+
: inside(p.bounds, overlays[ov2].blockBounds);
|
|
1498
|
+
if (blocks) { p.blockedByOverlay = true; break; }
|
|
1421
1499
|
}
|
|
1422
1500
|
rootPressables.push(p);
|
|
1423
1501
|
}
|
|
@@ -1425,6 +1503,7 @@ export async function getScreenState(options = {}) {
|
|
|
1425
1503
|
for (var si = 0; si < allPressables.length; si++) {
|
|
1426
1504
|
delete allPressables[si].overlayIdx;
|
|
1427
1505
|
delete allPressables[si].hasOwnLabel;
|
|
1506
|
+
delete allPressables[si].paintIdx;
|
|
1428
1507
|
}
|
|
1429
1508
|
|
|
1430
1509
|
// Build typed text/image lists (pair each measurement with its meta by index,
|
|
@@ -1505,7 +1584,6 @@ export async function getScreenState(options = {}) {
|
|
|
1505
1584
|
}
|
|
1506
1585
|
if (!screenState)
|
|
1507
1586
|
return { success: false, error: "Empty screen state response" };
|
|
1508
|
-
// Deduplicate pressables by center coordinates (PDV + onPress fallback can both fire)
|
|
1509
1587
|
const dedupPressables = (list) => {
|
|
1510
1588
|
const seen = new Set();
|
|
1511
1589
|
return list.filter((p) => {
|
|
@@ -1520,8 +1598,6 @@ export async function getScreenState(options = {}) {
|
|
|
1520
1598
|
for (const overlay of screenState.overlays) {
|
|
1521
1599
|
overlay.pressables = dedupPressables(overlay.pressables);
|
|
1522
1600
|
}
|
|
1523
|
-
// Dedup texts/images: a single visual element often maps to nested host nodes
|
|
1524
|
-
// (Image > ExpoImage) or repeated text spans that all measure to the same box.
|
|
1525
1601
|
const dedupBy = (list, keyExtra) => {
|
|
1526
1602
|
const seen = new Set();
|
|
1527
1603
|
return list.filter((item) => {
|
|
@@ -1533,16 +1609,6 @@ export async function getScreenState(options = {}) {
|
|
|
1533
1609
|
});
|
|
1534
1610
|
};
|
|
1535
1611
|
screenState.texts = dedupBy(screenState.texts, (t) => t.text);
|
|
1536
|
-
// Images need geometry-only dedup, not center+src.
|
|
1537
|
-
//
|
|
1538
|
-
// RN's <Image> and the <ExpoImage> it renders both match IMG_NAME and climb to the
|
|
1539
|
-
// same measurable host, but their sources stringify differently — "asset#77" for the
|
|
1540
|
-
// required asset, the resolved "http://127.0.0.1:8083/assets/…?unstable_path=…" URL
|
|
1541
|
-
// for the inner one. Keying on src therefore treated one picture as two, and every
|
|
1542
|
-
// local asset on screen was listed twice at identical coordinates.
|
|
1543
|
-
//
|
|
1544
|
-
// Keep the more informative source: "asset#N" is an opaque registry index, while the
|
|
1545
|
-
// resolved URL carries the actual filename.
|
|
1546
1612
|
const OPAQUE_ASSET_REF = /^asset#\d+$/;
|
|
1547
1613
|
const dedupImages = (list) => {
|
|
1548
1614
|
const byBox = new Map();
|
|
@@ -1566,7 +1632,6 @@ export async function getScreenState(options = {}) {
|
|
|
1566
1632
|
if (overlay.images)
|
|
1567
1633
|
overlay.images = dedupImages(overlay.images);
|
|
1568
1634
|
}
|
|
1569
|
-
// Semantic icon hints + onPress handler hints
|
|
1570
1635
|
const decorate = (p) => {
|
|
1571
1636
|
applyIconHintToLabel(p);
|
|
1572
1637
|
const direct = describePressHandler(p.handler);
|
|
@@ -1580,7 +1645,6 @@ export async function getScreenState(options = {}) {
|
|
|
1580
1645
|
for (const overlay of screenState.overlays) {
|
|
1581
1646
|
overlay.pressables.forEach(decorate);
|
|
1582
1647
|
}
|
|
1583
|
-
// Apply TS-side overlay marking as a safety pass
|
|
1584
1648
|
for (const overlay of screenState.overlays) {
|
|
1585
1649
|
if (overlay.pressables.length === 0)
|
|
1586
1650
|
continue;
|
|
@@ -1591,9 +1655,6 @@ export async function getScreenState(options = {}) {
|
|
|
1591
1655
|
const overlayBounds = { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
1592
1656
|
markPressablesCoveredByOverlay(screenState.pressables, overlayBounds);
|
|
1593
1657
|
}
|
|
1594
|
-
// Native-presented sheet detection: when an open native sheet covers the screen, its
|
|
1595
|
-
// (and the underlying screen's) coordinates are unreliable — flag it and mark the
|
|
1596
|
-
// underlying pressables blocked so agents fall back to screenshot/OCR.
|
|
1597
1658
|
try {
|
|
1598
1659
|
const parsedRaw = JSON.parse(resolveResult.result || "{}");
|
|
1599
1660
|
const markers = Array.isArray(parsedRaw.nativeMarkers) ? parsedRaw.nativeMarkers : [];
|
|
@@ -1604,13 +1665,11 @@ export async function getScreenState(options = {}) {
|
|
|
1604
1665
|
`unreliable. Use ios_screenshot / ocr_screenshot to read and tap it.`;
|
|
1605
1666
|
screenState.nativeOverlay = { kind: sheet.kind, component: sheet.component, note };
|
|
1606
1667
|
screenState.notes = [...(screenState.notes ?? []), note];
|
|
1607
|
-
// The native sheet dims/blocks the underlying screen — flag root pressables.
|
|
1608
1668
|
for (const p of screenState.pressables)
|
|
1609
1669
|
p.blockedByOverlay = true;
|
|
1610
1670
|
}
|
|
1611
1671
|
}
|
|
1612
1672
|
catch {
|
|
1613
|
-
/* detection is best-effort; never fail the call over it */
|
|
1614
1673
|
}
|
|
1615
1674
|
const json = JSON.stringify(screenState, null, 2);
|
|
1616
1675
|
return { success: true, result: json, screenState };
|