peachsim 0.1.627 → 0.1.628
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/LICENSE +1 -1
- package/cli/bin.ts +6 -2
- package/cli/bridge-flow-runner.ts +79 -72
- package/cli/commands/cleanup.ts +6 -6
- package/cli/commands/control.ts +4 -5
- package/cli/commands/detox.ts +25 -11
- package/cli/commands/flow.ts +3 -2
- package/cli/commands/inspect.ts +22 -37
- package/cli/commands/mode.ts +11 -7
- package/cli/commands/report-issue.ts +1 -1
- package/cli/commands/setup.ts +16 -11
- package/cli/commands/show-touches-mode.ts +33 -0
- package/cli/commands/skills.ts +16 -0
- package/cli/commands/test.ts +8 -1
- package/cli/commands/welcome.ts +3 -3
- package/cli/drivers/playwright-sim-host.ts +6 -5
- package/cli/help-core.ts +9 -4
- package/cli/internal-child.ts +14 -2
- package/cli/levenshtein.ts +27 -0
- package/cli/main.ts +28 -18
- package/cli/ws-bridge.ts +3 -2
- package/detox/index.ts +234 -7
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +170 -13
- package/dist-lib/dev-bundle-resolution.cjs +2 -2
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +42 -37
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +44 -5
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +7 -1
- package/dist-lib/menu.mjs +7 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +43 -4
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +140 -149
- package/dist-lib/swift-compile.cjs +1 -1
- package/dist-lib/swift-compile.mjs +1 -1
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +7234 -7069
- package/dist-lib/vite-kotlin.cjs +1 -1
- package/dist-lib/vite-swift.cjs +1 -1
- package/dist-lib/vite.cjs +43 -4
- package/package.json +1 -1
- package/skills/contrast/SKILL.md +1 -1
- package/src/dev-bundle-resolution.ts +1 -1
- package/src/host/bridge-host.ts +2 -34
- package/src/menu.ts +7 -0
- package/src/native-seam-manifest.ts +4 -16
- package/src/runtime-assets.ts +59 -2
- package/src/vite-plugin.ts +723 -25
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -4707,7 +4707,7 @@ var init_supported_native_packages = __esm({
|
|
|
4707
4707
|
"expo-sensors",
|
|
4708
4708
|
// semantic-proof
|
|
4709
4709
|
"expo-sharing",
|
|
4710
|
-
// semantic-proof
|
|
4710
|
+
// semantic-proof+coverage
|
|
4711
4711
|
"expo-sms",
|
|
4712
4712
|
// semantic-proof
|
|
4713
4713
|
"expo-speech",
|
|
@@ -5210,6 +5210,8 @@ var init_supported_native_packages = __esm({
|
|
|
5210
5210
|
// preset+visual-proof+seam
|
|
5211
5211
|
"react-native-widget-picker",
|
|
5212
5212
|
// seam
|
|
5213
|
+
"react-native-widgetkit",
|
|
5214
|
+
// seam+coverage
|
|
5213
5215
|
"react-native-wifi-p2p",
|
|
5214
5216
|
// seam
|
|
5215
5217
|
"react-native-worklets",
|
|
@@ -5801,8 +5803,8 @@ var init_registry = __esm({
|
|
|
5801
5803
|
id: "navigation-controls",
|
|
5802
5804
|
usage: 3,
|
|
5803
5805
|
importance: 3,
|
|
5804
|
-
estimate: 0.
|
|
5805
|
-
rationale: "Reload and injection work. HTML fragment navigation now follows the observed iOS URL and callback sequence, and local link requests expose decisions with matching payloads. The remaining
|
|
5806
|
+
estimate: 0.8,
|
|
5807
|
+
rationale: "Reload and injection work. HTML fragment navigation now follows the observed iOS URL and callback sequence, and local link requests expose decisions with matching payloads. Initial http(s) loads and form submits are asked with matching payloads and resume through the lock callback, a stopped reload reports its start with no finish, and refused local connections and same-origin HTTP errors report onError/onHttpError with native shapes plus renderError. The remaining 20% judgment allowance retains remote history traversal and reload decisions, data:/about:/file initial-load decisions, and remote failure reporting."
|
|
5806
5808
|
},
|
|
5807
5809
|
{
|
|
5808
5810
|
id: "layout-scroll-presentation",
|
|
@@ -5828,9 +5830,9 @@ var init_registry = __esm({
|
|
|
5828
5830
|
],
|
|
5829
5831
|
capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-webview"],
|
|
5830
5832
|
strictCoverage: REACT_NATIVE_WEBVIEW_STRICT_COVERAGE,
|
|
5831
|
-
note: "native-seam only: the published package runs unchanged and routes RNCWebView through the tenant-to-shell hosted iframe surface. the implementation estimate uses reviewed feature weights; the separate equal-surface strict diagnostic includes the shared, iOS, and Android public prop and ref surface. paired native and Peach runtime conformance covers local HTML, base URL, URI loading, load and navigation callbacks, both injection phases, two-way messaging, imperative URI reload and injection, local HTML fragment navigation and link-request decisions, content scrolling, parent translation, and onOpenWindow target delivery.",
|
|
5832
|
-
working: "source.uri/source.html/source.baseUrl, Chromium cross-origin URI loading under the shell COEP, same-origin URI cookies, source.html persistent localStorage, document-start ReactNativeWebView bootstrap and injectedJavaScriptBeforeContentLoaded/injectedJavaScript on source.html, strict ReactNativeWebView.postMessage bridge envelope in both directions, onMessage synthetic event with navigation fields, onOpenWindow target delivery for source.html, successful onLoad/Start/End and onNavigationStateChange, ref.reload on URI pages, ref.injectJavaScript/postMessage, local HTML fragment URL/callback behavior, onShouldStartLoadWithRequest for local link clicks with native-shaped request and loading payloads, internal content scrolling, renderLoading, javaScriptEnabled sandbox, layout, inherited clipping and visibility, parked/live presentation",
|
|
5833
|
-
missing: "Safari/WebKit cross-origin URI pages without COEP-compatible response headers remain permanently loading because WebKit ignores iframe credentialless; Chromium credentialless cross-origin URI frames send no credentials, including cookies set by their own origin, and use ephemeral storage; iframe pixels in canvas screenshots; script injection, ReactNativeWebView bootstrap, and onOpenWindow for remote pages, which get no bridge at all because a browser cannot script a cross-origin frame; cross-origin
|
|
5833
|
+
note: "native-seam only: the published package runs unchanged and routes RNCWebView through the tenant-to-shell hosted iframe surface. the implementation estimate uses reviewed feature weights; the separate equal-surface strict diagnostic includes the shared, iOS, and Android public prop and ref surface. paired native and Peach runtime conformance covers local HTML, base URL, URI loading, load and navigation callbacks, both injection phases, two-way messaging, imperative URI reload and injection, local HTML fragment navigation and link-request decisions, initial-load and form request decisions, local stopLoading cancellation, refused-host and restricted-port onError with renderError, content scrolling, parent translation, and onOpenWindow target delivery. same-origin onHttpError follows RNCWebViewImpl but runs on Peach only, since no local HTTP error source is reachable from both targets.",
|
|
5834
|
+
working: "source.uri/source.html/source.baseUrl, Chromium cross-origin URI loading under the shell COEP, same-origin URI cookies, source.html persistent localStorage, document-start ReactNativeWebView bootstrap and injectedJavaScriptBeforeContentLoaded/injectedJavaScript on source.html, strict ReactNativeWebView.postMessage bridge envelope in both directions, onMessage synthetic event with navigation fields, onOpenWindow target delivery for source.html, successful onLoad/Start/End and onNavigationStateChange, ref.reload on URI pages, ref.injectJavaScript/postMessage, local HTML fragment URL/callback behavior, onShouldStartLoadWithRequest for local link clicks with native-shaped request and loading payloads, initial-load onShouldStartLoadWithRequest for http(s) documents with the native other/top-frame/lockIdentifier payload allowed or denied through the lock callback, form-submit onShouldStartLoadWithRequest with navigationType formsubmit and, for a get form, the form data as the url query, resumed in place, ref.stopLoading cancelling an in-flight reload with no following callbacks, onError with the native NSURLErrorDomain code/description for a refused local connection and WebKitErrorDomain 103 for a port on the WebKit blocked list, each plus onLoadEnd and renderError(domain, code, description), onHttpError with the native url/statusCode for a same-origin local HTTP error, internal content scrolling, renderLoading, javaScriptEnabled sandbox, layout, inherited clipping and visibility, parked/live presentation",
|
|
5835
|
+
missing: "Safari/WebKit cross-origin URI pages without COEP-compatible response headers remain permanently loading because WebKit ignores iframe credentialless; Chromium credentialless cross-origin URI frames send no credentials, including cookies set by their own origin, and use ephemeral storage; iframe pixels in canvas screenshots; script injection, ReactNativeWebView bootstrap, and onOpenWindow for remote pages, which get no bridge at all because a browser cannot script a cross-origin frame; cross-origin history truthfulness (goBack/goForward across documents, truthful canGoBack/canGoForward) plus reload and history-traversal policy decisions; initial-load decisions for data:/about:/file documents, which stay ungated with no paired native ask observed; remote HTTP error statuses and refused remote connections, which a cross-origin frame never exposes to the browser, and the HTTP status of a non-get form submit; allowsBackForwardNavigationGestures, userAgent, dataDetectorTypes, cacheEnabled, incognito, scalesPageToFit, originWhitelist enforcement"
|
|
5834
5836
|
}
|
|
5835
5837
|
]
|
|
5836
5838
|
},
|
|
@@ -5861,10 +5863,10 @@ var init_registry = __esm({
|
|
|
5861
5863
|
},
|
|
5862
5864
|
{
|
|
5863
5865
|
range: ">=56.0.0 <58.0.0",
|
|
5864
|
-
coverage: 0.
|
|
5865
|
-
note:
|
|
5866
|
-
working:
|
|
5867
|
-
missing: "Expo modules bridge, any bridge or script injection on a remote page because a browser cannot script a cross-origin frame, cross-origin scrolling, the re-encoded data: URI a page reports as its own location.href, exact native scroll physics and native-only media/keyboard props, iframe pixels in canvas screenshots"
|
|
5866
|
+
coverage: 0.5,
|
|
5867
|
+
note: 'native-seam only: the published Expo 57.0.1 wrapper and an Expo "use dom" component pass the same paired library case on a native iPhone 16 and in Peach (ExpoDomWebViewLibraryCase).',
|
|
5868
|
+
working: 'DomWebView/WebView exports, source.uri rendering, onMessage data/url/title, ref.reload/injectJavaScript/scrollTo, document-start ReactNativeWebView bootstrap and injectedJavaScriptBeforeContentLoaded, injectedJavaScriptObject, reload-on-update behavior for injectedJavaScriptObject/injectedJavaScript, "use dom" components (mount with initial props, prop updates, native actions that resolve or reject, useDOMImperativeHandle methods, reload), layout and parked/live presentation',
|
|
5869
|
+
missing: "Expo modules bridge (unstable_useExpoModulesBridge is accepted and ignored), any bridge or script injection on a remote page because a browser cannot script a cross-origin frame, cross-origin scrolling, the re-encoded data: URI a page reports as its own location.href, exact native scroll physics and native-only media/keyboard props, iframe pixels in canvas screenshots"
|
|
5868
5870
|
}
|
|
5869
5871
|
]
|
|
5870
5872
|
},
|
|
@@ -6145,9 +6147,9 @@ var init_registry = __esm({
|
|
|
6145
6147
|
{
|
|
6146
6148
|
range: ">=11.0.0",
|
|
6147
6149
|
coverage: 0.95,
|
|
6148
|
-
note: "runtime font registry backed by
|
|
6149
|
-
working: "useFonts (URL/object/require sources), loadAsync, isLoaded, getLoadedFonts, isLoading,
|
|
6150
|
-
missing: "
|
|
6150
|
+
note: "runtime font registry backed by the engine CanvasKit provider; renderToImageAsync rasterizes in the tenant worker on a cpu surface into the tmp file store",
|
|
6151
|
+
working: "useFonts (URL/object/require sources), loadAsync, isLoaded, getLoadedFonts, isLoading, processFontFamily, renderToImageAsync (tenant cpu raster, tmp file uri, dp width/height/scale); a file that is not a font rejects with ERR_FONT_REGISTRATION_FAILED; unloadAsync and unloadAllAsync throw UnavailabilityError, as the iOS and Android modules define neither",
|
|
6152
|
+
missing: "exact Expo asset integration for numeric bundled font ids"
|
|
6151
6153
|
}
|
|
6152
6154
|
]
|
|
6153
6155
|
},
|
|
@@ -6170,10 +6172,10 @@ var init_registry = __esm({
|
|
|
6170
6172
|
versions: [
|
|
6171
6173
|
{
|
|
6172
6174
|
range: ">=1.0.0",
|
|
6173
|
-
coverage: 0.
|
|
6174
|
-
note: "the
|
|
6175
|
-
working: "Image
|
|
6176
|
-
missing: "
|
|
6175
|
+
coverage: 0.93,
|
|
6176
|
+
note: "the published Image, ImageBackground, and ExpoImage.tsx JS runs unchanged; the ExpoImage native view and native module follow the installed ImageView.swift and ImageModule.swift over the engine's sootsim-image host. paired native and Peach runtime proof covers cover, contain, fill, and scale-down contentFit, right-edge contentPosition, tint, opacity, uri, blurhash, and thumbhash placeholders, the cross-dissolve transition frame by frame, onLoad cache type and image facts, onDisplay, animated GIF frame playback with native durations, blurRadius, onProgress events, the placeholder generators, and a loaded image ref.",
|
|
6177
|
+
working: "Image, ImageBackground, useImage; contentFit cover, contain, fill, none, and scale-down; contentPosition; tintColor; blurRadius with the native halved radius; animated GIF playback with native frame durations and loop count (isAnimated, mediaType, autoplay, startAnimating, stopAnimating); source selection by view size; uri, blurhash, and thumbhash placeholders with placeholderContentFit; transition duration and timing curves with skipOnCacheHit; recyclingKey; onLoadStart, onLoad (cacheType by cachePolicy, url, size, mediaType, isAnimated), onProgress (loaded, total, progress) for data uris and remote sources the browser can read, onLoadEnd, onError, onDisplay; Image.prefetch with its cache policy, clearMemoryCache and clearDiskCache, loadAsync with maxWidth and maxHeight, readFromCacheAsync, writeToCacheAsync, generateBlurhashAsync and generateThumbhashAsync (the swift encoders), ImageRef rendering, a reload after every prop update, lockResourceAsync, unlockResourceAsync, and reloadAsync, the imageLoaded event",
|
|
6178
|
+
missing: "the flip, curl, and SF Symbol transition effects draw a cross-dissolve; SF Symbol sources; the disk cache lasts only as long as the page and has no files, so getCachePathAsync is null; prefetch ignores headers; source.cacheKey is ignored, so an image written with writeToCacheAsync does not render from its key; onProgress for a remote image served without CORS headers; animated WebP and APNG decode through the same player but have no paired proof"
|
|
6177
6179
|
}
|
|
6178
6180
|
]
|
|
6179
6181
|
},
|
|
@@ -6560,10 +6562,10 @@ var init_registry = __esm({
|
|
|
6560
6562
|
versions: [
|
|
6561
6563
|
{
|
|
6562
6564
|
range: ">=17.0.0",
|
|
6563
|
-
coverage: 0.
|
|
6565
|
+
coverage: 0.8,
|
|
6564
6566
|
note: "the published SDK 57 package runs unchanged against one ExpoLocation native seam backed by host browser geolocation and the shared app-scoped permission registry",
|
|
6565
|
-
working: "upstream enums, validation, subscriber bookkeeping and permission hooks; getProviderStatusAsync, getCurrentPositionAsync, filtered getLastKnownPositionAsync, watchPositionAsync with native watch-id event routing and removal
|
|
6566
|
-
missing: "device-orientation heading readings, an app-selected geocoder,
|
|
6567
|
+
working: "upstream enums, validation, subscriber bookkeeping and permission hooks; native exception codes and reasons; two-key getProviderStatusAsync with backgroundModeEnabled always true like native; start* gated on the location UIBackgroundModes from the resolved expo config (infoPlist modes or the expo-location plugin flag), unavailable when undeclared; getCurrentPositionAsync, foreground-gated filtered getLastKnownPositionAsync, watchPositionAsync with native watch-id event routing and removal; foreground/background permission getters and requests; hasServicesEnabledAsync; isBackgroundLocationAvailableAsync=true; simulator-exact motion-activity unavailability; background location task registration and { locations } delivery through the task-manager seam with foreground no-deferral and distanceInterval filtering; startGeofencingAsync rejecting with ERR_GEOFENCING_UNAVAILABLE after the background permission check, as the reference iOS 27 simulator does (CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) is false there)",
|
|
6568
|
+
missing: "device-orientation heading readings, an app-selected geocoder, Android network-provider enablement, deferred background delivery (deferredUpdatesInterval and deferredUpdatesDistance batching while the app is backgrounded), and task error delivery when the location manager fails"
|
|
6567
6569
|
}
|
|
6568
6570
|
]
|
|
6569
6571
|
},
|
|
@@ -6573,10 +6575,10 @@ var init_registry = __esm({
|
|
|
6573
6575
|
versions: [
|
|
6574
6576
|
{
|
|
6575
6577
|
range: ">=0.20.0",
|
|
6576
|
-
coverage: 0.
|
|
6577
|
-
note: 'real local notification delivery via browser Notification + sootsim in-engine overlay; full upstream API surface present; matches iOS-simulator behavior where APNs registration silently fails. per docs/compat-scoring.md "score it high only when the full public API surface is present and returns the same unavailable/clean state an app should expect in development."',
|
|
6578
|
-
working: "getPermissionsAsync/requestPermissionsAsync through the shared system permission registry, scheduleNotificationAsync (fires real browser Notification when host capability allows, plus the in-engine banner), cancelScheduledNotificationAsync, cancelAllScheduledNotificationsAsync, getAllScheduledNotificationsAsync, getPresentedNotificationsAsync, dismissNotificationAsync, dismissAllNotificationsAsync, setBadgeCountAsync (navigator.setAppBadge if available), getBadgeCountAsync, addNotificationReceivedListener/ResponseReceivedListener/DroppedListener/PushTokenListener, getLastNotificationResponseAsync + sync, clearLastNotificationResponseAsync + sync, useLastNotificationResponse hook, getNextTriggerDateAsync, setNotificationHandler, presentNotificationAsync, channel + channel-group CRUD, category CRUD, AndroidImportance/AndroidNotificationVisibility/IosAuthorizationStatus/PermissionStatus enums",
|
|
6579
|
-
missing: "real push token registration (getDevicePushTokenAsync returns a placeholder UUID \u2014 there is no FCM/APNs provisioning, service-worker push subscription, or backend-uploadable token); background task delivery (registerTaskAsync/unregisterTaskAsync/isTaskRegisteredAsync are noops \u2014 service-worker push wiring is not implemented); scheduled-notification persistence across reload (setTimeout-only \u2014 page refresh drops the queue); subscribeToTopicAsync/unsubscribeFromTopicAsync FCM topic binding; setAutoServerRegistrationEnabledAsync"
|
|
6578
|
+
coverage: 0.95,
|
|
6579
|
+
note: 'real local notification delivery via browser Notification + sootsim in-engine overlay, plus push notifications from Detox sendUserNotification and launchApp({ userNotification }) dispatched the way DetoxUserNotificationDispatcher dispatches them (willPresent for an active app, the tap response otherwise and at launch, held until the emitter exists); full upstream API surface present; matches iOS-simulator behavior where APNs registration silently fails. per docs/compat-scoring.md "score it high only when the full public API surface is present and returns the same unavailable/clean state an app should expect in development."',
|
|
6580
|
+
working: "getPermissionsAsync/requestPermissionsAsync through the shared system permission registry, scheduleNotificationAsync (fires real browser Notification when host capability allows, plus the in-engine banner), cancelScheduledNotificationAsync, cancelAllScheduledNotificationsAsync, getAllScheduledNotificationsAsync, getPresentedNotificationsAsync, dismissNotificationAsync, dismissAllNotificationsAsync, setBadgeCountAsync (navigator.setAppBadge if available), getBadgeCountAsync, addNotificationReceivedListener/ResponseReceivedListener/DroppedListener/PushTokenListener, getLastNotificationResponseAsync + sync, clearLastNotificationResponseAsync + sync, useLastNotificationResponse hook, getNextTriggerDateAsync, setNotificationHandler, presentNotificationAsync, push notifications dispatched like Detox (onDidReceiveNotification with trigger { type: push, payload } and data from the user info body, tap responses with action identifier and user text, the launch tap as the last response), the native handler timeout presenting with the default options, channel + channel-group CRUD, category CRUD, AndroidImportance/AndroidNotificationVisibility/IosAuthorizationStatus/PermissionStatus enums",
|
|
6581
|
+
missing: "real push token registration (getDevicePushTokenAsync returns a placeholder UUID \u2014 there is no FCM/APNs provisioning, service-worker push subscription, or backend-uploadable token); background task delivery (registerTaskAsync/unregisterTaskAsync/isTaskRegisteredAsync are noops \u2014 service-worker push wiring is not implemented); scheduled-notification persistence across reload (setTimeout-only \u2014 page refresh drops the queue); subscribeToTopicAsync/unsubscribeFromTopicAsync FCM topic binding; setAutoServerRegistrationEnabledAsync; push notifications arriving from APNs or simctl push (only the Detox dispatch path exists, so there is no system banner for a push to a backgrounded app and no didReceiveRemoteNotification background delivery)"
|
|
6580
6582
|
}
|
|
6581
6583
|
]
|
|
6582
6584
|
},
|
|
@@ -7416,8 +7418,8 @@ var init_registry = __esm({
|
|
|
7416
7418
|
range: ">=2.11.4 <3.0.0",
|
|
7417
7419
|
coverage: 0.76,
|
|
7418
7420
|
note: "the real upstream PickerIOS wrapper runs from the guest bundle and resolves codegenNativeComponent('RNCPicker') to the engine UIPickerView wheel. upstream owns Picker.Item mapping, controlled selection, and callback fan-out.",
|
|
7419
|
-
working: "real upstream Picker, PickerIOS, Picker.Item label/value, selectedValue, onValueChange(value, index), itemStyle color/fontSize, MODE_DIALOG and MODE_DROPDOWN constants",
|
|
7420
|
-
missing: "
|
|
7421
|
+
working: "real upstream Picker, PickerIOS, Picker.Item label/value, selectedValue, onValueChange(value, index), itemStyle color/fontSize/fontFamily/fontWeight/fontStyle (fontSize Int32-truncated, 0 keeps the 21pt system font), per-item textColor over the itemStyle color, Picker.Item testID row labels, themeVariant dark/light interface-style override, numberOfLines label and row height, MODE_DIALOG and MODE_DROPDOWN constants",
|
|
7422
|
+
missing: "textAlign (dead prop on the native host: row alignment reads themeVariant), multi-line numberOfLines proof; the dark/light default label color, a loaded fontFamily, themeVariant-driven label alignment, and fontSize truncation follow RNCPicker but have no paired proof, controlled native selection restore proof, deprecated onChange proof, android dialog/dropdown presentation (mode/prompt/dropdownIconColor render as the iOS wheel), focus()/blur() imperative handle, onFocus/onBlur; selectionColor is ignored by the exact 2.11.4 Fabric iOS host and Peach matches that behavior"
|
|
7421
7423
|
}
|
|
7422
7424
|
]
|
|
7423
7425
|
},
|
|
@@ -7572,10 +7574,10 @@ var init_registry = __esm({
|
|
|
7572
7574
|
versions: [
|
|
7573
7575
|
{
|
|
7574
7576
|
range: ">=12.0.0",
|
|
7575
|
-
coverage: 0.
|
|
7576
|
-
note: "upstream expo-sharing JS runs unchanged; package-local wrapper only registers the ExpoSharing native module.
|
|
7577
|
-
working: "isAvailableAsync
|
|
7578
|
-
missing: "
|
|
7577
|
+
coverage: 0.9,
|
|
7578
|
+
note: "upstream expo-sharing JS runs unchanged; package-local wrapper only registers the ExpoSharing native module. shareAsync presents the same canvas share sheet core RN Share uses; a declared app group id reads the empty inbox a browser preview should report.",
|
|
7579
|
+
working: "isAvailableAsync through upstream js, shareAsync presenting the shared canvas sheet and resolving on dismissal whatever the outcome, dialogTitle accepted and not shown as on iOS, ERR_FILE_PERMISSION for unreadable files, ERR_MISSING_CURRENT_VIEW_CONTROLLER without a sheet host, ERR_FAILED_TO_RESOLVE_APP_GROUP_ID from all three share-into entries when the app declares no ExpoShareIntoAppGroupId, empty incoming-share inbox when it does",
|
|
7580
|
+
missing: "incoming share extension app-group storage (no extension writes into the group from a preview, so a declared key always reads empty); UTI/mimeType file restaging and iPad popover anchoring have no visible effect on the iPhone-idiom sheet"
|
|
7579
7581
|
}
|
|
7580
7582
|
]
|
|
7581
7583
|
},
|
|
@@ -8003,10 +8005,10 @@ var init_registry = __esm({
|
|
|
8003
8005
|
versions: [
|
|
8004
8006
|
{
|
|
8005
8007
|
range: ">=4.0.0",
|
|
8006
|
-
coverage: 0.
|
|
8008
|
+
coverage: 0.95,
|
|
8007
8009
|
note: "the published two-function package runs unchanged; its native seam applies processed colors to the tenant-owned app root that Peach synchronizes to the CanvasKit compositor",
|
|
8008
|
-
working: "setBackgroundColorAsync and getBackgroundColorAsync round-trip the visible app-surface background, including React Native processed-color conversion; null
|
|
8009
|
-
missing: "
|
|
8010
|
+
working: "setBackgroundColorAsync and getBackgroundColorAsync round-trip the visible app-surface background, including React Native processed-color conversion; set colors persist across restarts through tenant storage and are reapplied at launch (falling back to the app-config background color the config plugin writes to Info.plist); null snapshots the current interface style (black in dark, white otherwise) and clears the stored color; a fresh launch with no stored or app-config color reads that snapshot; the getter returns uppercase #RRGGBB",
|
|
8011
|
+
missing: "persistence across restarts and the app-config fallback have no paired relaunch proof"
|
|
8010
8012
|
}
|
|
8011
8013
|
]
|
|
8012
8014
|
},
|
|
@@ -9986,9 +9988,10 @@ var init_registry = __esm({
|
|
|
9986
9988
|
versions: [
|
|
9987
9989
|
{
|
|
9988
9990
|
range: ">=2.0.0",
|
|
9989
|
-
coverage: 0,
|
|
9990
|
-
note: "the
|
|
9991
|
-
|
|
9991
|
+
coverage: 0.6,
|
|
9992
|
+
note: "the published TrueSheet JS runs unchanged; TrueSheetView presents through the engine's react-native-screens form sheet. paired native and Peach runtime proof covers present at a half detent, resize to the large detent, dismiss, and the mount, willPresent, didPresent, detentChange, willDismiss, and didDismiss events.",
|
|
9993
|
+
working: "present, resize, and dismiss, by ref or by name; fractional detents, initialDetentIndex, maxContentHeight, and maxContentWidth; cornerRadius, backgroundColor, grabber, dimmed, dimmedDetentIndex, and dismissible; header; onMount, onWillPresent, onDidPresent, onDetentChange, onWillDismiss, onDidDismiss, and the focus and blur events",
|
|
9994
|
+
missing: "onPositionChange fires only when a detent settles, and onDragBegin, onDragChange, and onDragEnd never fire; the footer is not pinned to the bottom edge; a sheet mounted with initialDetentIndex presents without onWillFocus and onWillPresent; the auto detent reports the large card position and index -1 while the sheet draws fitted to its content; the peek detent; insetAdjustment never also drops the bottom inset on iPad; scrollable, backgroundBlur, blurOptions, detached, anchor, draggable, and grabberOptions"
|
|
9992
9995
|
}
|
|
9993
9996
|
]
|
|
9994
9997
|
},
|
|
@@ -10046,9 +10049,10 @@ var init_registry = __esm({
|
|
|
10046
10049
|
versions: [
|
|
10047
10050
|
{
|
|
10048
10051
|
range: ">=1.0.0",
|
|
10049
|
-
coverage: 0,
|
|
10050
|
-
note: "the
|
|
10051
|
-
|
|
10052
|
+
coverage: 0.75,
|
|
10053
|
+
note: "the published ContextMenu JS runs unchanged; the ContextMenu native view follows the installed ContextMenuView.m over the engine's UIMenu presenter. paired native and Peach runtime proof covers a long-press menu with a title, subtitles, system icons, a submenu, and destructive, selected, and disabled actions, the onPress index, indexPath, and name, onCancel after a backdrop dismiss, and a dropdownMenuMode tap menu.",
|
|
10054
|
+
working: "long-press context menu with a title; actions with subtitle, systemIcon, iconColor, titleColor, destructive, selected, disabled, and nested actions as submenus; onPress with index, indexPath, and name; onCancel with an empty event only when the menu closes without an action; dropdownMenuMode; disabled",
|
|
10055
|
+
missing: "the custom preview and onPreviewPress (the lifted view is the content itself); asset `icon` images; inlineChildren; previewBackgroundColor, the border radius props that clip the lifted preview, and disableShadow; fontName"
|
|
10052
10056
|
}
|
|
10053
10057
|
]
|
|
10054
10058
|
},
|
|
@@ -10220,9 +10224,10 @@ var init_registry = __esm({
|
|
|
10220
10224
|
versions: [
|
|
10221
10225
|
{
|
|
10222
10226
|
range: ">=1.0.0",
|
|
10223
|
-
coverage: 0,
|
|
10224
|
-
note: "the
|
|
10225
|
-
|
|
10227
|
+
coverage: 0.8,
|
|
10228
|
+
note: "the published LiquidGlassView and LiquidGlassContainerView JS runs unchanged; the native views draw through the engine's liquid glass material. paired native and Peach runtime proof covers clear, tinted regular, dark regular, and none effects over a striped backdrop, and isLiquidGlassSupported.",
|
|
10229
|
+
working: "LiquidGlassView effect clear, regular, and none, tintColor, colorScheme, interactive, and its border radius; LiquidGlassContainerView layout; isLiquidGlassSupported",
|
|
10230
|
+
missing: "LiquidGlassContainerView does not merge neighbouring glass, so spacing does nothing; an effect change does not animate; isLiquidGlassSupported is always true, including when the app sets UIDesignRequiresCompatibility"
|
|
10226
10231
|
}
|
|
10227
10232
|
]
|
|
10228
10233
|
},
|
|
@@ -11504,9 +11509,10 @@ var init_registry = __esm({
|
|
|
11504
11509
|
versions: [
|
|
11505
11510
|
{
|
|
11506
11511
|
range: ">=1.0.0",
|
|
11507
|
-
coverage: 0,
|
|
11508
|
-
note: "
|
|
11509
|
-
|
|
11512
|
+
coverage: 0.9,
|
|
11513
|
+
note: "Widgetkit native module: App Group UserDefaults getItem/setItem, sharing suites with react-native-shared-group-preferences; timeline reloads accepted",
|
|
11514
|
+
working: "getItem, setItem, reloadAllTimelines, reloadTimelines",
|
|
11515
|
+
missing: "no home screen widgets render in Peach, so reloads refresh nothing"
|
|
11510
11516
|
}
|
|
11511
11517
|
]
|
|
11512
11518
|
},
|
|
@@ -18717,7 +18723,7 @@ function formatDetailedScanLines(result) {
|
|
|
18717
18723
|
);
|
|
18718
18724
|
}
|
|
18719
18725
|
lines.push(
|
|
18720
|
-
"
|
|
18726
|
+
"Peach may still work. The simulator will report a concrete runtime error if it finds a gap."
|
|
18721
18727
|
);
|
|
18722
18728
|
}
|
|
18723
18729
|
return lines;
|
|
@@ -21108,10 +21114,12 @@ function createRuntimeDelivery(product) {
|
|
|
21108
21114
|
);
|
|
21109
21115
|
import_node_fs6.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
21110
21116
|
try {
|
|
21111
|
-
|
|
21117
|
+
if (!opts.quiet)
|
|
21118
|
+
process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
|
|
21112
21119
|
`);
|
|
21113
21120
|
await downloadToFile(tarUrl, runtimeArchivePath);
|
|
21114
|
-
|
|
21121
|
+
if (!opts.quiet)
|
|
21122
|
+
process.stderr.write(`${product.id}: extracting runtime ${version}\u2026
|
|
21115
21123
|
`);
|
|
21116
21124
|
const actualSha = await sha256File(runtimeArchivePath);
|
|
21117
21125
|
if (actualSha !== entry.sha256) {
|
|
@@ -21453,6 +21461,41 @@ function resolveRuntimeRootForHostname(hostname) {
|
|
|
21453
21461
|
const version = runtimeVersionFromHostname(hostname);
|
|
21454
21462
|
return version ? resolveInstalledRuntimeRoot(version) : null;
|
|
21455
21463
|
}
|
|
21464
|
+
function sendFileWithRanges(req, res, filePath, total, headers) {
|
|
21465
|
+
const head = (req?.method || "GET").toUpperCase() === "HEAD";
|
|
21466
|
+
const range = /^bytes=(\d*)-(\d*)$/.exec(req?.headers?.range || "");
|
|
21467
|
+
const invalid = range && range[1] && range[2] && Number(range[2]) < Number(range[1]);
|
|
21468
|
+
if (range && (range[1] || range[2]) && !invalid) {
|
|
21469
|
+
const [, startRaw, endRaw] = range;
|
|
21470
|
+
const start = startRaw ? Number(startRaw) : Math.max(0, total - Number(endRaw));
|
|
21471
|
+
const end = startRaw && endRaw ? Math.min(Number(endRaw), total - 1) : total - 1;
|
|
21472
|
+
if (start > end || start >= total) {
|
|
21473
|
+
res.writeHead(416, { ...headers, "Content-Range": `bytes */${total}` });
|
|
21474
|
+
res.end();
|
|
21475
|
+
return;
|
|
21476
|
+
}
|
|
21477
|
+
res.writeHead(206, {
|
|
21478
|
+
...headers,
|
|
21479
|
+
"Content-Range": `bytes ${start}-${end}/${total}`,
|
|
21480
|
+
"Accept-Ranges": "bytes",
|
|
21481
|
+
"Content-Length": String(end - start + 1)
|
|
21482
|
+
});
|
|
21483
|
+
if (head) res.end();
|
|
21484
|
+
else streamFile(res, import_fs.default.createReadStream(filePath, { start, end }));
|
|
21485
|
+
return;
|
|
21486
|
+
}
|
|
21487
|
+
res.writeHead(200, {
|
|
21488
|
+
...headers,
|
|
21489
|
+
"Accept-Ranges": "bytes",
|
|
21490
|
+
"Content-Length": String(total)
|
|
21491
|
+
});
|
|
21492
|
+
if (head || total === 0) res.end();
|
|
21493
|
+
else streamFile(res, import_fs.default.createReadStream(filePath, { start: 0, end: total - 1 }));
|
|
21494
|
+
}
|
|
21495
|
+
function streamFile(res, stream) {
|
|
21496
|
+
stream.on("error", (error) => res.destroy(error));
|
|
21497
|
+
stream.pipe(res);
|
|
21498
|
+
}
|
|
21456
21499
|
var import_fs, import_path, import_url, _monorepoRootCache, RUNTIME_VERSION_HOSTNAME_SUFFIX;
|
|
21457
21500
|
var init_runtime_assets = __esm({
|
|
21458
21501
|
"src/runtime-assets.ts"() {
|
|
@@ -29799,42 +29842,10 @@ var init_bridge_host = __esm({
|
|
|
29799
29842
|
return;
|
|
29800
29843
|
}
|
|
29801
29844
|
const contentType = HTTP_MIME_TYPES[import_path3.default.extname(filePath).toLowerCase()] || "application/octet-stream";
|
|
29802
|
-
|
|
29803
|
-
const range = /^bytes=(\d*)-(\d*)$/.exec(req.headers.range || "");
|
|
29804
|
-
if (range) {
|
|
29805
|
-
const [, startRaw, endRaw] = range;
|
|
29806
|
-
const start = startRaw ? Number(startRaw) : 0;
|
|
29807
|
-
const end = endRaw ? Math.min(Number(endRaw), total - 1) : total - 1;
|
|
29808
|
-
if (!Number.isFinite(start) || start > end || start >= total) {
|
|
29809
|
-
res.writeHead(416, { ...cors, "Content-Range": `bytes */${total}` });
|
|
29810
|
-
res.end();
|
|
29811
|
-
return;
|
|
29812
|
-
}
|
|
29813
|
-
res.writeHead(206, {
|
|
29814
|
-
...cors,
|
|
29815
|
-
"Content-Type": contentType,
|
|
29816
|
-
"Content-Range": `bytes ${start}-${end}/${total}`,
|
|
29817
|
-
"Accept-Ranges": "bytes",
|
|
29818
|
-
"Content-Length": String(end - start + 1)
|
|
29819
|
-
});
|
|
29820
|
-
if (method === "HEAD") {
|
|
29821
|
-
res.end();
|
|
29822
|
-
return;
|
|
29823
|
-
}
|
|
29824
|
-
import_fs3.default.createReadStream(filePath, { start, end }).pipe(res);
|
|
29825
|
-
return;
|
|
29826
|
-
}
|
|
29827
|
-
res.writeHead(200, {
|
|
29845
|
+
sendFileWithRanges(req, res, filePath, stats.size, {
|
|
29828
29846
|
...cors,
|
|
29829
|
-
"Content-Type": contentType
|
|
29830
|
-
"Accept-Ranges": "bytes",
|
|
29831
|
-
"Content-Length": String(total)
|
|
29847
|
+
"Content-Type": contentType
|
|
29832
29848
|
});
|
|
29833
|
-
if (method === "HEAD") {
|
|
29834
|
-
res.end();
|
|
29835
|
-
return;
|
|
29836
|
-
}
|
|
29837
|
-
import_fs3.default.createReadStream(filePath).pipe(res);
|
|
29838
29849
|
}
|
|
29839
29850
|
handleServerScan(res) {
|
|
29840
29851
|
const sendJson = (body) => {
|
|
@@ -31357,7 +31368,7 @@ function resolveDefaultDevBridgeLockfile() {
|
|
|
31357
31368
|
) ?? sameCheckout[0];
|
|
31358
31369
|
}
|
|
31359
31370
|
}
|
|
31360
|
-
return lockfiles.find((lockfile) => lockfile.bridgePort === DEFAULT_SOOTSIM_BRIDGE_PORT) ??
|
|
31371
|
+
return lockfiles.find((lockfile) => lockfile.bridgePort === DEFAULT_SOOTSIM_BRIDGE_PORT) ?? null;
|
|
31361
31372
|
}
|
|
31362
31373
|
function resolveBridgeWorld() {
|
|
31363
31374
|
const homeDir = rnxHomeDir();
|
|
@@ -31923,7 +31934,7 @@ var init_app_url = __esm({
|
|
|
31923
31934
|
// src/dev-bundle-resolution.ts
|
|
31924
31935
|
function buildUnresolvedTargetError(targetLabel) {
|
|
31925
31936
|
return new Error(
|
|
31926
|
-
`could not resolve a native bundle for ${targetLabel}. pass an explicit bundle URL or open Connect and choose the app there.`
|
|
31937
|
+
`could not resolve a native bundle for ${targetLabel}. start the app's dev server (for example npx expo start), pass an explicit bundle URL, or open Connect and choose the app there.`
|
|
31927
31938
|
);
|
|
31928
31939
|
}
|
|
31929
31940
|
function inferManifestFramework(launchUrl2, sdkVersion) {
|
|
@@ -35606,8 +35617,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
35606
35617
|
deviceArg,
|
|
35607
35618
|
false,
|
|
35608
35619
|
void 0,
|
|
35609
|
-
postureArg === "open" ? "open" : "closed"
|
|
35610
|
-
true
|
|
35620
|
+
postureArg === "open" ? "open" : "closed"
|
|
35611
35621
|
) : void 0;
|
|
35612
35622
|
const osVersionArg = args.find((_, i) => args[i - 1] === "--os-version");
|
|
35613
35623
|
if (osVersionArg && !/^\d+\.\d+$/.test(osVersionArg)) {
|
|
@@ -37305,11 +37315,9 @@ function normalizeFlowScreenshotSpec(step) {
|
|
|
37305
37315
|
function parsePoint(value, bounds) {
|
|
37306
37316
|
const [rawX, rawY] = value.split(",").map((part) => part.trim());
|
|
37307
37317
|
const parseCoord = (coord, max) => coord.endsWith("%") ? Number.parseFloat(coord) / 100 * max : Number.parseFloat(coord);
|
|
37308
|
-
const originX = bounds?.x ?? 0;
|
|
37309
|
-
const originY = bounds?.y ?? 0;
|
|
37310
37318
|
return {
|
|
37311
|
-
x:
|
|
37312
|
-
y:
|
|
37319
|
+
x: bounds.x + parseCoord(rawX, bounds.width),
|
|
37320
|
+
y: bounds.y + parseCoord(rawY, bounds.height)
|
|
37313
37321
|
};
|
|
37314
37322
|
}
|
|
37315
37323
|
function normalizeBareStringStep(verb) {
|
|
@@ -37345,7 +37353,7 @@ function parseFlowSteps(content) {
|
|
|
37345
37353
|
const parsed = import_yaml.default.parse(candidate);
|
|
37346
37354
|
return Array.isArray(parsed) ? parsed : [];
|
|
37347
37355
|
}
|
|
37348
|
-
var fs19, path19, import_settings3, import_yaml, import_proof_frame, DEFAULT_TIMEOUT, ASSERTION_LOOKUP_MS, FLOW_TIMEOUT_SCALE, scaledTimeout,
|
|
37356
|
+
var fs19, path19, import_settings3, import_yaml, import_proof_frame, DEFAULT_TIMEOUT, ASSERTION_LOOKUP_MS, FLOW_TIMEOUT_SCALE, scaledTimeout, MAESTRO_SELECTOR_KEYS, SELECTOR_FILTER_KEYS, UNSUPPORTED_SELECTOR_KEYS, MAESTRO_PERMISSION_KINDS, MAESTRO_PERMISSION_STATUS, SootSimBridgeFlowRunner;
|
|
37349
37357
|
var init_bridge_flow_runner = __esm({
|
|
37350
37358
|
"cli/bridge-flow-runner.ts"() {
|
|
37351
37359
|
"use strict";
|
|
@@ -37368,8 +37376,6 @@ var init_bridge_flow_runner = __esm({
|
|
|
37368
37376
|
ASSERTION_LOOKUP_MS = 17e3;
|
|
37369
37377
|
FLOW_TIMEOUT_SCALE = flowTimeoutScale();
|
|
37370
37378
|
scaledTimeout = (ms) => Math.round(ms * FLOW_TIMEOUT_SCALE);
|
|
37371
|
-
SCREEN_W = 393;
|
|
37372
|
-
SCREEN_H = 852;
|
|
37373
37379
|
MAESTRO_SELECTOR_KEYS = /* @__PURE__ */ new Set([
|
|
37374
37380
|
"text",
|
|
37375
37381
|
"id",
|
|
@@ -37494,6 +37500,16 @@ var init_bridge_flow_runner = __esm({
|
|
|
37494
37500
|
args
|
|
37495
37501
|
});
|
|
37496
37502
|
}
|
|
37503
|
+
async screenBounds() {
|
|
37504
|
+
const snapshot = await this.callTest(
|
|
37505
|
+
"getSurfaceMetricsSnapshot"
|
|
37506
|
+
);
|
|
37507
|
+
const window2 = snapshot?.window;
|
|
37508
|
+
if (!window2 || typeof window2 !== "object" || !("width" in window2) || !("height" in window2) || typeof window2.width !== "number" || typeof window2.height !== "number" || !Number.isFinite(window2.width) || !Number.isFinite(window2.height) || window2.width <= 0 || window2.height <= 0) {
|
|
37509
|
+
throw new Error("live screen dimensions are unavailable");
|
|
37510
|
+
}
|
|
37511
|
+
return { x: 0, y: 0, width: window2.width, height: window2.height };
|
|
37512
|
+
}
|
|
37497
37513
|
// ordered input batch executed inside the page in one round-trip; the
|
|
37498
37514
|
// engine emits agent-cursor actions for every step natively.
|
|
37499
37515
|
async perform(steps) {
|
|
@@ -37730,6 +37746,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
37730
37746
|
// (match scoped to a container). a nested selector resolves the same way,
|
|
37731
37747
|
// and a relative filter holds when ANY match of its anchor satisfies it.
|
|
37732
37748
|
async findElementScoped(opts) {
|
|
37749
|
+
const screen = await this.screenBounds();
|
|
37733
37750
|
const needsEveryNode = !opts.id || opts.childOf != null || SELECTOR_FILTER_KEYS.some((key) => opts[key] != null);
|
|
37734
37751
|
return this.evaluate(`(async () => {
|
|
37735
37752
|
const test = window.__sootsimTest
|
|
@@ -37833,7 +37850,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
37833
37850
|
// paints nothing, and maestro's hierarchy never holds it.
|
|
37834
37851
|
const onScreen = candidates.filter((n) => {
|
|
37835
37852
|
const cy = n.absolutePosition.y + n.layout.height / 2
|
|
37836
|
-
return cy > 0 && cy < ${
|
|
37853
|
+
return cy > 0 && cy < ${screen.height}
|
|
37837
37854
|
})
|
|
37838
37855
|
if (candidates.some(painted)) candidates = candidates.filter(painted)
|
|
37839
37856
|
else if (onScreen.length > 0) candidates = onScreen
|
|
@@ -37998,7 +38015,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
37998
38015
|
async resolveInteractionPoint(opts) {
|
|
37999
38016
|
if (opts.point && !opts.id && !opts.text && opts.index === void 0 && !opts.childOf) {
|
|
38000
38017
|
return {
|
|
38001
|
-
...parsePoint(opts.point),
|
|
38018
|
+
...parsePoint(opts.point, await this.screenBounds()),
|
|
38002
38019
|
element: null,
|
|
38003
38020
|
target: void 0
|
|
38004
38021
|
};
|
|
@@ -38459,32 +38476,14 @@ var init_bridge_flow_runner = __esm({
|
|
|
38459
38476
|
}
|
|
38460
38477
|
return outputDir;
|
|
38461
38478
|
}
|
|
38462
|
-
|
|
38463
|
-
|
|
38464
|
-
|
|
38465
|
-
|
|
38466
|
-
|
|
38467
|
-
|
|
38468
|
-
|
|
38469
|
-
|
|
38470
|
-
switch (direction.toUpperCase()) {
|
|
38471
|
-
case "UP":
|
|
38472
|
-
fromY += distance;
|
|
38473
|
-
toY -= distance;
|
|
38474
|
-
break;
|
|
38475
|
-
case "DOWN":
|
|
38476
|
-
fromY -= distance;
|
|
38477
|
-
toY += distance;
|
|
38478
|
-
break;
|
|
38479
|
-
case "LEFT":
|
|
38480
|
-
fromX += distance;
|
|
38481
|
-
toX -= distance;
|
|
38482
|
-
break;
|
|
38483
|
-
case "RIGHT":
|
|
38484
|
-
fromX -= distance;
|
|
38485
|
-
toX += distance;
|
|
38486
|
-
break;
|
|
38487
|
-
}
|
|
38479
|
+
// maestro's ios driver: a directional swipe spans the screen, from 90% to
|
|
38480
|
+
// 10% for UP, 20% to 90% for DOWN, and 10% to 90% across for LEFT/RIGHT,
|
|
38481
|
+
// over the command's 400ms default.
|
|
38482
|
+
async swipe(direction = "UP", duration = 400) {
|
|
38483
|
+
const screen = await this.screenBounds();
|
|
38484
|
+
const midX = screen.width / 2;
|
|
38485
|
+
const midY = screen.height / 2;
|
|
38486
|
+
const [fromX, fromY, toX, toY] = direction.toUpperCase() === "DOWN" ? [midX, screen.height * 0.2, midX, screen.height * 0.9] : direction.toUpperCase() === "LEFT" ? [screen.width * 0.9, midY, screen.width * 0.1, midY] : direction.toUpperCase() === "RIGHT" ? [screen.width * 0.1, midY, screen.width * 0.9, midY] : [midX, screen.height * 0.9, midX, screen.height * 0.1];
|
|
38488
38487
|
const steps = Math.max(10, Math.round(duration / 16));
|
|
38489
38488
|
await this.drag(fromX, fromY, toX, toY, steps, 16);
|
|
38490
38489
|
}
|
|
@@ -38505,34 +38504,22 @@ var init_bridge_flow_runner = __esm({
|
|
|
38505
38504
|
}
|
|
38506
38505
|
await this.settleAfterInput();
|
|
38507
38506
|
}
|
|
38508
|
-
async swipeCoords(start, end, duration =
|
|
38509
|
-
const
|
|
38510
|
-
const
|
|
38507
|
+
async swipeCoords(start, end, duration = 400) {
|
|
38508
|
+
const screen = await this.screenBounds();
|
|
38509
|
+
const from = parsePoint(start, screen);
|
|
38510
|
+
const to = parsePoint(end, screen);
|
|
38511
38511
|
const steps = Math.max(10, Math.round(duration / 16));
|
|
38512
38512
|
await this.drag(from.x, from.y, to.x, to.y, steps, 16);
|
|
38513
38513
|
}
|
|
38514
|
-
|
|
38514
|
+
// maestro's ios driver swipes from the element's center to the 10% or 90%
|
|
38515
|
+
// edge in the swipe's direction.
|
|
38516
|
+
async swipeFrom(from, direction = "UP", duration = 400) {
|
|
38515
38517
|
const element = await this.findElement(from);
|
|
38516
38518
|
if (!element) throw new Error(`swipeFrom: element not found: ${JSON.stringify(from)}`);
|
|
38517
38519
|
const startX = element.absolutePosition.x + element.layout.width / 2;
|
|
38518
38520
|
const startY = element.absolutePosition.y + element.layout.height / 2;
|
|
38519
|
-
const
|
|
38520
|
-
|
|
38521
|
-
let endY = startY;
|
|
38522
|
-
switch (direction.toUpperCase()) {
|
|
38523
|
-
case "UP":
|
|
38524
|
-
endY -= distance;
|
|
38525
|
-
break;
|
|
38526
|
-
case "DOWN":
|
|
38527
|
-
endY += distance;
|
|
38528
|
-
break;
|
|
38529
|
-
case "LEFT":
|
|
38530
|
-
endX -= distance;
|
|
38531
|
-
break;
|
|
38532
|
-
case "RIGHT":
|
|
38533
|
-
endX += distance;
|
|
38534
|
-
break;
|
|
38535
|
-
}
|
|
38521
|
+
const screen = await this.screenBounds();
|
|
38522
|
+
const [endX, endY] = direction.toUpperCase() === "DOWN" ? [startX, screen.height * 0.9] : direction.toUpperCase() === "LEFT" ? [screen.width * 0.1, startY] : direction.toUpperCase() === "RIGHT" ? [screen.width * 0.9, startY] : [startX, screen.height * 0.1];
|
|
38536
38523
|
const steps = Math.max(10, Math.round(duration / 16));
|
|
38537
38524
|
await this.drag(startX, startY, endX, endY, steps, 16);
|
|
38538
38525
|
}
|
|
@@ -38617,16 +38604,17 @@ var init_bridge_flow_runner = __esm({
|
|
|
38617
38604
|
);
|
|
38618
38605
|
const deadline = Date.now() + (opts.timeout || 2e4);
|
|
38619
38606
|
const direction = opts.direction?.toUpperCase() || "DOWN";
|
|
38620
|
-
const centerX = SCREEN_W / 2;
|
|
38621
|
-
const centerY = SCREEN_H / 2;
|
|
38622
|
-
const swipeEnd = direction === "UP" ? { x: centerX, y: SCREEN_H * 0.9 } : direction === "LEFT" ? { x: SCREEN_W * 0.9, y: centerY } : direction === "RIGHT" ? { x: SCREEN_W * 0.1, y: centerY } : { x: centerX, y: SCREEN_H * 0.1 };
|
|
38623
38607
|
while (Date.now() < deadline) {
|
|
38608
|
+
const screen = await this.screenBounds();
|
|
38609
|
+
const centerX = screen.width / 2;
|
|
38610
|
+
const centerY = screen.height / 2;
|
|
38611
|
+
const swipeEnd = direction === "UP" ? { x: centerX, y: screen.height * 0.9 } : direction === "LEFT" ? { x: screen.width * 0.9, y: centerY } : direction === "RIGHT" ? { x: screen.width * 0.1, y: centerY } : { x: centerX, y: screen.height * 0.1 };
|
|
38624
38612
|
const element = await this.findElement(target);
|
|
38625
38613
|
if (element) {
|
|
38626
38614
|
const { x, y } = element.absolutePosition;
|
|
38627
38615
|
const { width, height } = element.layout;
|
|
38628
|
-
const shownX = Math.max(0, Math.min(x + width,
|
|
38629
|
-
const shownY = Math.max(0, Math.min(y + height,
|
|
38616
|
+
const shownX = Math.max(0, Math.min(x + width, screen.width) - Math.max(x, 0));
|
|
38617
|
+
const shownY = Math.max(0, Math.min(y + height, screen.height) - Math.max(y, 0));
|
|
38630
38618
|
const share = width * height > 0 ? shownX * shownY / (width * height) : 0;
|
|
38631
38619
|
if (share >= required) {
|
|
38632
38620
|
if (opts.centerElement) {
|
|
@@ -39210,7 +39198,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
39210
39198
|
await this.swipe(step.swipe.direction, step.swipe.duration);
|
|
39211
39199
|
}
|
|
39212
39200
|
} else if (step.scroll) {
|
|
39213
|
-
await this.
|
|
39201
|
+
const screen = await this.screenBounds();
|
|
39202
|
+
const midX = screen.width / 2;
|
|
39203
|
+
const toY = step.scroll.direction === "UP" ? screen.height * 0.9 : screen.height * 0.1;
|
|
39204
|
+
await this.drag(midX, screen.height / 2, midX, toY, Math.round(333 / 16), 16);
|
|
39214
39205
|
} else if (step.scrollTo) {
|
|
39215
39206
|
const target = typeof step.scrollTo.nodeId === "number" ? { nodeId: step.scrollTo.nodeId } : step.scrollTo.id;
|
|
39216
39207
|
if (!target) throw new Error("scrollTo requires id or nodeId");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.628 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|