@everframe/react-native 1.5.0 → 1.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/EverframeRN.podspec +1 -1
- package/README.md +136 -17
- package/android/build.gradle.kts +12 -19
- package/android/src/main/java/dev/everframe/rn/EverframeModule.kt +16 -962
- package/dist/NativeEverframe.d.ts +7 -67
- package/dist/index.d.ts +63 -178
- package/dist/index.js +23 -23
- package/dist/index.web.d.ts +2 -2
- package/dist/{launch-C8wbMunK.d.ts → launch-aXtOOfNU.d.ts} +1 -2
- package/ios/Sources/EverframeBridge.swift +16 -456
- package/ios/Sources/EverframeEventEmitter.swift +9 -126
- package/ios/Sources/EverframeModule.mm +2 -52
- package/package.json +4 -4
- package/src/NativeEverframe.ts +11 -107
package/EverframeRN.podspec
CHANGED
|
@@ -40,7 +40,7 @@ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
|
40
40
|
# 1.2.0, so the range already asks for 1.2 while package.json is still 1.1.0.
|
|
41
41
|
# The 1.2.0 release moves package.json to match.
|
|
42
42
|
native_version_override = ENV['EVERFRAME_NATIVE_POD_VERSION'].to_s.strip
|
|
43
|
-
native_minor_range = native_version_override.empty? ? '~> 1.
|
|
43
|
+
native_minor_range = native_version_override.empty? ? '~> 1.6.0' : native_version_override
|
|
44
44
|
|
|
45
45
|
Pod::Spec.new do |s|
|
|
46
46
|
s.name = 'EverframeRN'
|
package/README.md
CHANGED
|
@@ -414,15 +414,22 @@ In a crash-only session:
|
|
|
414
414
|
- Session replay uses the app's crash-only sampling rate, which is 0 by
|
|
415
415
|
default. An error carries a replay only while the session records.
|
|
416
416
|
- Network bodies aren't captured.
|
|
417
|
-
- Crash and error capture, breadcrumbs, vitals
|
|
418
|
-
|
|
417
|
+
- Crash and error capture, breadcrumbs, vitals and release health work as
|
|
418
|
+
usual.
|
|
419
419
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
420
|
+
See [crash-only sessions](../../docs/session-replay.md#crash-only-sessions).
|
|
421
|
+
|
|
422
|
+
### Companion (removed)
|
|
423
|
+
|
|
424
|
+
Everframe Companion (phone / TV pairing) has been removed. The `companion`
|
|
425
|
+
namespace and `useCompanion()` remain as deprecated no-ops until the next
|
|
426
|
+
major version: `companion.start()` logs one warning and reaches no native
|
|
427
|
+
code, every `on*` subscription returns an unsubscribe and never fires, and
|
|
428
|
+
`useCompanion()` always returns `{ state: 'unpaired', running: false, … }`
|
|
429
|
+
with every other value `null`. The `attachPinUi`, `companionDeviceId` and
|
|
430
|
+
`companionBadge` config options are accepted and ignored. To capture from a
|
|
431
|
+
real device, link it under Settings → Devices in the dashboard and use quick
|
|
432
|
+
capture.
|
|
426
433
|
|
|
427
434
|
## Navigation breadcrumbs
|
|
428
435
|
|
|
@@ -708,16 +715,23 @@ dashboard disable.
|
|
|
708
715
|
|
|
709
716
|
In React Native and Expo development builds, use
|
|
710
717
|
`shakeToReport: { enabled: !__DEV__ }` because the React Native development
|
|
711
|
-
menu also uses shake. Production remains enabled by default.
|
|
718
|
+
menu also uses shake. Production remains enabled by default. This only stops
|
|
719
|
+
shake from opening the reporter: on a real phone, a development build still
|
|
720
|
+
takes a quick capture on shake, and a linked phone captures in any build (see
|
|
721
|
+
[Quick capture on phones](#quick-capture-on-phones)).
|
|
712
722
|
|
|
713
723
|
#### Quick capture on simulators and emulators
|
|
714
724
|
|
|
715
725
|
Debug builds on an iOS simulator or Android emulator can file a report without
|
|
716
|
-
opening the reporter:
|
|
717
|
-
`npx @everframe/cli capture`
|
|
718
|
-
|
|
726
|
+
opening the reporter: press ⇧B in the app (outside a `TextInput`), or run
|
|
727
|
+
`npx @everframe/cli capture` from your terminal. iOS simulators also take the
|
|
728
|
+
other bindings the dashboard offers (double Shift, ⌘ combos); Android
|
|
729
|
+
emulators use the dashboard binding only when it is Shift plus a letter or
|
|
730
|
+
digit, and ⇧B otherwise. Run `npx @everframe/cli login` once so captures are attributed
|
|
719
731
|
to you. It stays dark until the dashboard turns the capture hotkey on for the
|
|
720
|
-
app
|
|
732
|
+
app. Real phones use shake instead; see
|
|
733
|
+
[Quick capture on phones](#quick-capture-on-phones). To opt this app out
|
|
734
|
+
locally (simulators, emulators and phones alike, including device linking):
|
|
721
735
|
|
|
722
736
|
```tsx
|
|
723
737
|
<EverframeProvider
|
|
@@ -729,7 +743,112 @@ app, and never runs on devices or release builds. To opt this app out locally:
|
|
|
729
743
|
dashboard disable. A session started with `capture.screenshot` off ignores quick
|
|
730
744
|
capture.
|
|
731
745
|
|
|
732
|
-
|
|
746
|
+
#### Quick capture on phones
|
|
747
|
+
|
|
748
|
+
On a real iPhone, iPad, or Android phone or tablet, **shake** takes a quick
|
|
749
|
+
capture: the same screenshot, replay window, logs, breadcrumbs and network as
|
|
750
|
+
⇧B in a simulator, filed as a draft that you title on the dashboard. The native
|
|
751
|
+
iOS and Android SDKs do all of it; there is no JavaScript API and nothing to
|
|
752
|
+
add to your app. A shake captures when the device is linked, or when the build is a
|
|
753
|
+
debug build:
|
|
754
|
+
|
|
755
|
+
| Device | Shake |
|
|
756
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
757
|
+
| Linked to you | Quick capture, a private draft for you. Toast `Captured · <your name>`. |
|
|
758
|
+
| Linked as a team device | Quick capture, a shared draft. Toast `Captured · team device`. |
|
|
759
|
+
| Unlinked, debug build | Quick capture, a shared draft. Toast `Captured · <device name>`. Also answers a dashboard link window. |
|
|
760
|
+
| Unlinked, release build | As before: the reporter opens if `shakeToReport` allows it. Also answers a dashboard link window. |
|
|
761
|
+
|
|
762
|
+
- **Link a phone.** On the dashboard, open **Settings → Devices → Link a
|
|
763
|
+
device**, then shake the phone with the app running. A banner shows
|
|
764
|
+
`Linking to Everframe · 47` with the line
|
|
765
|
+
`A teammate is linking a device. If that's not you, ignore this.` Click the
|
|
766
|
+
same number on the dashboard; the phone shows `Linked to <your name>`.
|
|
767
|
+
Nothing links on its own: a teammate always picks the number. On iOS, if the
|
|
768
|
+
Keychain refuses to store the link, the phone shows `Linking failed` instead
|
|
769
|
+
and stays unlinked.
|
|
770
|
+
- **Team devices.** An admin can pick **Link as team device** instead. The
|
|
771
|
+
phone shows `Linked as team device`, and its captures go to the shared inbox
|
|
772
|
+
for whoever is on the dashboard.
|
|
773
|
+
- **Hand a phone over.** A linked phone keeps capturing for its owner. When
|
|
774
|
+
another teammate opens **Link a device** and the phone is shaken, the capture
|
|
775
|
+
is filed as usual and the banner shows a number; picking it moves the phone,
|
|
776
|
+
and that capture, to the new teammate.
|
|
777
|
+
- **Unlinking.** Unlink a phone under **Settings → Devices**. It finds out at
|
|
778
|
+
its next capture or config fetch and behaves as unlinked again. A capture
|
|
779
|
+
refused this way is not filed anywhere and shows `This device was unlinked`.
|
|
780
|
+
Android also shows that toast when a config fetch reports the unlink; iOS
|
|
781
|
+
clears the link silently then.
|
|
782
|
+
- **Other toasts.** `Capture didn't upload` follows a capture whose upload was
|
|
783
|
+
rejected and not queued; `Capture failed` replaces `Captured` when the
|
|
784
|
+
screenshot or the evidence could not be taken.
|
|
785
|
+
- **Debug builds.** React Native sends `__DEV__` as the build type (override it
|
|
786
|
+
with `debugBuild`), so a Metro development build on a phone counts as debug
|
|
787
|
+
and a shake takes a shared capture without linking. In those builds the
|
|
788
|
+
React Native development menu also opens on the same shake, on both
|
|
789
|
+
platforms. To stop development builds from capturing, set
|
|
790
|
+
`quickCapture: { enabled: !__DEV__ }`, which also turns linking off for them.
|
|
791
|
+
- **`shakeToReport` controls only the reporter.** While quick capture or device
|
|
792
|
+
linking is on, the native shake detector runs whatever `shakeToReport` says,
|
|
793
|
+
and `shakeToReport` decides only whether an unlinked release build opens the
|
|
794
|
+
reporter. Linked and debug phones keep capturing with it off.
|
|
795
|
+
- **Replay.** With the dashboard's capture hotkey replay setting on, linked
|
|
796
|
+
phones (any build) and debug builds record session replay while quick capture
|
|
797
|
+
is armed, as simulators do.
|
|
798
|
+
- **End users see no change.** An unlinked release build never takes a quick
|
|
799
|
+
capture and never records replay because of it. The only new thing it can
|
|
800
|
+
show is the matching-number banner, if someone shakes it while a teammate has
|
|
801
|
+
a link window open.
|
|
802
|
+
- **Off switches.** The dashboard's per-app **Device linking** switch stops
|
|
803
|
+
phones from asking to link. The dashboard's capture hotkey switch,
|
|
804
|
+
`quickCapture: { enabled: false }` or `reporter: { disabled: true }` turn off
|
|
805
|
+
quick capture and linking together, and shake then behaves as before.
|
|
806
|
+
- **The token.** The device token is kept in the iOS Keychain, or encrypted
|
|
807
|
+
under an AndroidKeyStore key on Android. It is bound to the ingest endpoint
|
|
808
|
+
and SDK key that linked it, sent only there, and never logged. A linked
|
|
809
|
+
capture queued offline is sent later only while the same link is still
|
|
810
|
+
stored; otherwise it is dropped, never filed into another inbox.
|
|
811
|
+
- **Platform differences.** On Android, one long shake can fire the detector
|
|
812
|
+
more than once, so a shake within 2 seconds of a capture is ignored. Phones
|
|
813
|
+
and tablets are covered on both platforms. Apple TV behaves as before;
|
|
814
|
+
Android TV uses a remote gesture instead (below). The Android behavior ships
|
|
815
|
+
with the native Android SDK release that includes it.
|
|
816
|
+
|
|
817
|
+
#### Quick capture on Android TV
|
|
818
|
+
|
|
819
|
+
On Android TV the native Android SDK takes the same quick capture from a
|
|
820
|
+
remote gesture that the dashboard sets per app. The default is **holding
|
|
821
|
+
Play/Pause for 1.5 seconds**. Link the TV like a phone: open **Link a device**
|
|
822
|
+
on the dashboard, do the gesture on the TV, and click the number its banner
|
|
823
|
+
shows.
|
|
824
|
+
|
|
825
|
+
| Device | Remote gesture |
|
|
826
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
827
|
+
| Linked to you | Quick capture, a private draft for you. Toast `Captured · <your name>`. |
|
|
828
|
+
| Linked as a team device | Quick capture, a shared draft. Toast `Captured · team device`. |
|
|
829
|
+
| Unlinked, debug build | Quick capture, a shared draft. Toast `Captured · <device name>`. Also answers a dashboard link window. |
|
|
830
|
+
| Unlinked, release build | Nothing visible. Only answers a dashboard link window. |
|
|
831
|
+
|
|
832
|
+
- **Bindings.** In the dashboard's Quick capture card a binding is a long
|
|
833
|
+
press, a sequence (keys in order within a time window) or a chord (keys held
|
|
834
|
+
together). **Record on device** sets one from the remote you actually have:
|
|
835
|
+
pick one of your linked TVs, relaunch the app or bring it to the foreground,
|
|
836
|
+
and press the keys while it shows `Recording remote keys for 10 seconds`.
|
|
837
|
+
- **Key handling.** An unlinked TV never has a key swallowed or changed, so
|
|
838
|
+
`TVEventHandler` sees every event as before. On a linked TV the first press
|
|
839
|
+
always reaches the app, so holding Play/Pause toggles playback once when the
|
|
840
|
+
press starts, before the capture. Once the gesture is recognized, a long
|
|
841
|
+
press's repeats are swallowed and its key-up arrives canceled; a sequence or
|
|
842
|
+
chord swallows only the key that completes it.
|
|
843
|
+
- **Debug builds** follow `__DEV__` (or `debugBuild`), as on phones.
|
|
844
|
+
- Everything else (end users, replay, takeover, unlinking, token storage and
|
|
845
|
+
the off switches) works as on phones. Apple TV gets no remote gesture yet.
|
|
846
|
+
|
|
847
|
+
For the full rules, see the iOS SDK README's "Real iPhones and iPads" section
|
|
848
|
+
and the Android SDK README's "Quick capture on real phones" and "Quick capture
|
|
849
|
+
on Android TV" sections.
|
|
850
|
+
|
|
851
|
+
Apart from quick capture, gestures and keys are host-owned. The host app
|
|
733
852
|
calls `useEverframe().open()` (or the top-level `open()`)
|
|
734
853
|
from whatever trigger makes sense for the target form factor.
|
|
735
854
|
|
|
@@ -1019,13 +1138,13 @@ Target annotations enrich supported automatic native observations, including IME
|
|
|
1019
1138
|
|
|
1020
1139
|
### Reporter boundaries and developer tools
|
|
1021
1140
|
|
|
1022
|
-
Native phone reporter opens
|
|
1141
|
+
Native phone reporter opens add this custom breadcrumb before freezing evidence:
|
|
1023
1142
|
|
|
1024
1143
|
```json
|
|
1025
1144
|
{"kind":"custom","message":"reporter_opened","data":{"source":"everframe_reporter","trigger":"button"}}
|
|
1026
1145
|
```
|
|
1027
1146
|
|
|
1028
|
-
`trigger` is `button`, `shake`, `menu`, or `companion
|
|
1147
|
+
`trigger` is `button`, `shake`, `menu`, or `companion` (older builds only; Companion has been removed). Pending text/scroll summaries are flushed before this boundary. Native shake uses `shake`; existing `open()` calls use `button`. To identify a host menu entry explicitly, call `open({ trigger: 'menu' })`. Closing or cancelling the native flow adds `reporter_closed` with `data.source: 'everframe_reporter'` to the live trail. Both events retain breadcrumb capture/config gates.
|
|
1029
1148
|
|
|
1030
1149
|
A reporter call crosses the React Native bridge after its native input can already have been recorded. It cannot prove that the previous tap or remote key opened the reporter. For a button, annotate its native host ref before interaction:
|
|
1031
1150
|
|
|
@@ -1037,7 +1156,7 @@ return <Pressable ref={reporterRef} onPress={() => void open()}><Text>Report</Te
|
|
|
1037
1156
|
|
|
1038
1157
|
That target's tap/activation carries `data.origin: 'reporter'` and `data.trigger: 'button'`. On a remote, only Select/Enter activation is attributed to a `button` target; arrows, Menu and Play/Pause retain their ordinary meaning. An explicitly annotated `reporterTrigger: 'menu'` target attributes only its Menu activation. Attribution survives masking without retaining the target's text. Removing/recycling the bound ref removes attribution.
|
|
1039
1158
|
|
|
1040
|
-
Hosts owning a reporting flow outside `open()` can `await markReporterOpened('menu')` before showing their reporter UI and `await markReporterClosed()` when it closes. These promises resolve after the native UI-thread boundary work; await them before adding subsequent host breadcrumbs or changing reporter UI. These explicit markers do not claim or remove earlier native keys: a TV event callback may run after native key capture.
|
|
1159
|
+
Hosts owning a reporting flow outside `open()` can `await markReporterOpened('menu')` before showing their reporter UI and `await markReporterClosed()` when it closes. These promises resolve after the native UI-thread boundary work; await them before adding subsequent host breadcrumbs or changing reporter UI. These explicit markers do not claim or remove earlier native keys: a TV event callback may run after native key capture. Never infer reporter intent from a button label, a Menu/Play/Pause key, or proximity to `open()`.
|
|
1041
1160
|
|
|
1042
1161
|
Native target capture adds `data.origin: 'devtools'` to supported taps and structured text/control/scroll observations whose native ancestry belongs to React Native LogBox, the native development menu, or Expo development-client UI. This comes from framework view/window/controller identity, an RN-owned development-menu controller, or a framework root module identity. In a development host, the inline LogBox notification/inspector is also registered by the exact React Native component exports through the existing React DevTools commit hook; application components with the same name are not attributed. This observer reads component identity and native refs, never warning text or component props, and removes registrations when their committed hosts disappear or the provider unmounts. Production JavaScript leaves this observer inert. A development JavaScript host can still attribute LogBox when its native SDK was built in Release mode. Display text such as “Dismiss” never grants an origin. A missing React DevTools hook, unavailable RN private module exports at runtime, initial asynchronous module loading, unknown framework versions and surfaces outside the native capture adapters leave attribution unavailable; origin tagging does not install a new dialog capture mechanism. The observer depends on the LogBox module paths in supported React Native versions; a future version removing those paths requires an SDK compatibility update before Metro can bundle it.
|
|
1043
1162
|
|
package/android/build.gradle.kts
CHANGED
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
// includeBuild("../../../packages/sdk-android/android") // surfaces :everframe-core, :everframe-reporter-ui
|
|
9
9
|
// This library declares the two project deps below which resolve through the
|
|
10
10
|
// composite-build mechanism. The on-device :everframe-tv Activity was removed
|
|
11
|
-
// alongside the iOS tvOS modal
|
|
12
|
-
// phone-companion (QR → phone browser SPA) flow via CompanionCaptureBridge.
|
|
11
|
+
// alongside the iOS tvOS modal.
|
|
13
12
|
//
|
|
14
13
|
// CODEGEN:
|
|
15
14
|
// The `com.facebook.react` Gradle plugin reads `codegenConfig` from
|
|
@@ -81,17 +80,15 @@ android {
|
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
// Task 11 (Plan 5) — `EverframeModuleTest.kt`
|
|
85
|
-
//
|
|
83
|
+
// Task 11 (Plan 5) — `EverframeModuleTest.kt` exercises a
|
|
84
|
+
// `EverframeModule` contract that no longer exists on `main`
|
|
86
85
|
// (captureNow/submit/openAnnotationOverlay were removed by the
|
|
87
|
-
// D-05/D-07 flip
|
|
88
|
-
// `Companion.__setState`/`__setPairUrl` are `internal` to
|
|
89
|
-
// :everframe-core and unreachable from this separate Gradle module) —
|
|
86
|
+
// D-05/D-07 flip) —
|
|
90
87
|
// confirmed pre-existing and unrelated to Task 11 (Plan 4 Task 14 first
|
|
91
88
|
// hit this reproducing against unmodified HEAD; see
|
|
92
89
|
// .superpowers/sdd/task-11-report.md for the full compile-error dump).
|
|
93
90
|
// `compileDebugUnitTestKotlin` compiles the entire `test` source set as
|
|
94
|
-
// one Kotlin unit, so
|
|
91
|
+
// one Kotlin unit, so this permanently-broken file blocks
|
|
95
92
|
// `RnReplayBridgeTest.kt` (Task 11's actual subject, itself fixed by the
|
|
96
93
|
// `BridgeReactContext` swap in this same change) from ever compiling.
|
|
97
94
|
// Excluded here — NOT deleted — pending a follow-up ticket to either
|
|
@@ -101,10 +98,7 @@ android {
|
|
|
101
98
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>()
|
|
102
99
|
.matching { it.name.endsWith("UnitTestKotlin") } // compileDebugUnitTestKotlin + compileReleaseUnitTestKotlin
|
|
103
100
|
.configureEach {
|
|
104
|
-
exclude(
|
|
105
|
-
"**/EverframeModuleTest.kt",
|
|
106
|
-
"**/EverframeCompanionModuleTest.kt",
|
|
107
|
-
)
|
|
101
|
+
exclude("**/EverframeModuleTest.kt")
|
|
108
102
|
}
|
|
109
103
|
|
|
110
104
|
// Derive the native-AAR range from this package's own npm version (single
|
|
@@ -130,7 +124,7 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>()
|
|
|
130
124
|
//
|
|
131
125
|
// That window is not an edge case, it is every native minor. `package.json`
|
|
132
126
|
// only reaches the new version when `changeset version` runs at RELEASE
|
|
133
|
-
// time, so while
|
|
127
|
+
// time, so while one such feature sat unreleased, this file
|
|
134
128
|
// resolved `0.4.+` -> the stale 0.4.4 AAR while the bridge source called
|
|
135
129
|
// APIs added in native 0.5.0. Gradle resolved it happily (0.4.4 was in
|
|
136
130
|
// mavenLocal from an earlier release) and the failure surfaced as three
|
|
@@ -153,7 +147,7 @@ val rnSdkPkg = groovy.json.JsonSlurper()
|
|
|
153
147
|
val rnSdkVersion = rnSdkPkg["version"] as String
|
|
154
148
|
// Native 1.2.0 is the release that renamed the SDK key to `sdkKey`; the
|
|
155
149
|
// bridge moves with it, ahead of package.json, which the 1.2.0 release bumps.
|
|
156
|
-
val nativeMinorRange: String = nativeVersionOverride ?: "[1.
|
|
150
|
+
val nativeMinorRange: String = nativeVersionOverride ?: "[1.6.0,1.7.0)"
|
|
157
151
|
if (nativeVersionOverride != null) {
|
|
158
152
|
logger.lifecycle(
|
|
159
153
|
"[everframe-rn] native AAR pinned to $nativeVersionOverride via everframeNativeVersion " +
|
|
@@ -193,11 +187,10 @@ dependencies {
|
|
|
193
187
|
// relying on transitive promotion.
|
|
194
188
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
|
|
195
189
|
|
|
196
|
-
// kotlinx-serialization-json — used by the
|
|
197
|
-
// to
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
// direct reference here to call the Json { } factory.
|
|
190
|
+
// kotlinx-serialization-json — used by the interaction-event
|
|
191
|
+
// registration to parse its options JSON. Already on the classpath
|
|
192
|
+
// transitively via :everframe-protocol (implementation-scoped there),
|
|
193
|
+
// but we need a direct reference here to call the Json factory.
|
|
201
194
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
|
|
202
195
|
|
|
203
196
|
// Unit tests (Plan 06-03 Task 3). Versions mirror :everframe-core (see
|