yaver-feedback-react-native 0.9.0 → 0.9.2
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/app.plugin.js +126 -9
- package/dist/BlackBox.js +9 -1
- package/dist/DeployPanel.js +65 -0
- package/dist/Discovery.js +13 -2
- package/dist/FeedbackModal.js +160 -6
- package/dist/P2PClient.d.ts +64 -1
- package/dist/P2PClient.js +222 -2
- package/dist/ShakeDetector.js +2 -0
- package/dist/YaverFeedback.d.ts +98 -0
- package/dist/YaverFeedback.js +509 -46
- package/dist/__tests__/BlackBox.relayPassword.test.d.ts +1 -0
- package/dist/__tests__/BlackBox.relayPassword.test.js +105 -0
- package/dist/__tests__/BlackBoxAutoStart.test.d.ts +1 -0
- package/dist/__tests__/BlackBoxAutoStart.test.js +91 -0
- package/dist/__tests__/BlackBoxAutoStartColdStart.test.d.ts +1 -0
- package/dist/__tests__/BlackBoxAutoStartColdStart.test.js +156 -0
- package/dist/__tests__/BrowserLaneIcon.test.d.ts +3 -0
- package/dist/__tests__/BrowserLaneIcon.test.js +80 -0
- package/dist/__tests__/P2PClient.test.js +2 -2
- package/dist/__tests__/ReportIdentity.test.d.ts +1 -0
- package/dist/__tests__/ReportIdentity.test.js +168 -0
- package/dist/__tests__/SDKToken.test.js +1 -1
- package/dist/__tests__/ShakeToggle.test.d.ts +1 -0
- package/dist/__tests__/ShakeToggle.test.js +121 -0
- package/dist/__tests__/pickTargetDevice.test.d.ts +1 -0
- package/dist/__tests__/pickTargetDevice.test.js +89 -0
- package/dist/__tests__/reloadActions.test.d.ts +1 -0
- package/dist/__tests__/reloadActions.test.js +129 -0
- package/dist/__tests__/reloadActionsParity.test.d.ts +1 -0
- package/dist/__tests__/reloadActionsParity.test.js +42 -0
- package/dist/__tests__/types.test.js +5 -5
- package/dist/_core/device.d.ts +19 -9
- package/dist/_core/device.js +20 -14
- package/dist/index.d.ts +4 -0
- package/dist/index.js +11 -1
- package/dist/reloadActions.d.ts +88 -0
- package/dist/reloadActions.js +200 -0
- package/dist/storeShots.d.ts +67 -0
- package/dist/storeShots.js +137 -0
- package/dist/types.d.ts +158 -1
- package/package.json +2 -2
- package/src/BlackBox.ts +10 -1
- package/src/DeployPanel.tsx +74 -0
- package/src/Discovery.ts +13 -2
- package/src/FeedbackModal.tsx +176 -14
- package/src/P2PClient.ts +235 -2
- package/src/ShakeDetector.ts +1 -0
- package/src/YaverFeedback.ts +498 -46
- package/src/__tests__/BlackBox.relayPassword.test.ts +129 -0
- package/src/__tests__/BlackBoxAutoStart.test.ts +111 -0
- package/src/__tests__/BlackBoxAutoStartColdStart.test.ts +191 -0
- package/src/__tests__/BrowserLaneIcon.test.ts +85 -0
- package/src/__tests__/P2PClient.test.ts +2 -2
- package/src/__tests__/ReportIdentity.test.ts +203 -0
- package/src/__tests__/SDKToken.test.ts +1 -1
- package/src/__tests__/ShakeToggle.test.ts +153 -0
- package/src/__tests__/pickTargetDevice.test.ts +101 -0
- package/src/__tests__/reloadActions.test.ts +171 -0
- package/src/__tests__/reloadActionsParity.test.ts +49 -0
- package/src/__tests__/types.test.ts +5 -5
- package/src/_core/device.ts +20 -14
- package/src/index.ts +21 -0
- package/src/reloadActions.ts +273 -0
- package/src/storeShots.ts +189 -0
- package/src/types.ts +164 -1
package/dist/P2PClient.js
CHANGED
|
@@ -35,7 +35,16 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.P2PClient = void 0;
|
|
37
37
|
exports.resolveAppIdentity = resolveAppIdentity;
|
|
38
|
+
exports.resolveReportIdentity = resolveReportIdentity;
|
|
38
39
|
const react_native_1 = require("react-native");
|
|
40
|
+
const endpoints_1 = require("./_core/endpoints");
|
|
41
|
+
const reloadActions_1 = require("./reloadActions");
|
|
42
|
+
function unrefTimer(timer) {
|
|
43
|
+
const maybeNodeTimer = timer;
|
|
44
|
+
if (typeof maybeNodeTimer.unref === 'function') {
|
|
45
|
+
maybeNodeTimer.unref();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
39
48
|
/**
|
|
40
49
|
* Try to resolve `{projectName, bundleId}` for the running app so the
|
|
41
50
|
* agent can map the reload request to a MobileProject in its scan
|
|
@@ -84,6 +93,140 @@ function resolveAppIdentity(opts) {
|
|
|
84
93
|
out.projectPath = projectPath;
|
|
85
94
|
return out;
|
|
86
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Is this JS running inside Yaver's own container as a pushed Hermes guest?
|
|
98
|
+
*
|
|
99
|
+
* The YaverInfo native module is registered only by Yaver's app, so its
|
|
100
|
+
* presence means the ambient runtime describes Yaver rather than the app
|
|
101
|
+
* whose code is executing. Mirrors the checks in YaverFeedback.ts,
|
|
102
|
+
* ShakeDetector.ts and QuickActionIcon.tsx.
|
|
103
|
+
*/
|
|
104
|
+
function isInsideYaverContainer() {
|
|
105
|
+
try {
|
|
106
|
+
const { NativeModules } = require('react-native');
|
|
107
|
+
return !!NativeModules?.YaverInfo;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Read the guest project Yaver's host shell pinned for this bundle.
|
|
115
|
+
*
|
|
116
|
+
* When an app's JS is pushed into Yaver's container as a Hermes guest, the
|
|
117
|
+
* ambient runtime describes the HOST — `expo-constants` and `SettingsManager`
|
|
118
|
+
* both answer `Yaver` / `io.yaver.mobile`. Auto-resolution would therefore
|
|
119
|
+
* file every guest report against Yaver's own repo, and the fix task would
|
|
120
|
+
* edit the SDK instead of the app under test.
|
|
121
|
+
*
|
|
122
|
+
* Yaver already knows the right answer: picking a project in the Hot Reload
|
|
123
|
+
* tab calls `YaverInfo.setInheritedGuestProject(name, path)`. Only the name
|
|
124
|
+
* is used here — the agent resolves the path itself and deliberately ignores
|
|
125
|
+
* client-supplied ones on feedback reports.
|
|
126
|
+
*/
|
|
127
|
+
function resolveInheritedGuestProjectName() {
|
|
128
|
+
try {
|
|
129
|
+
const { NativeModules } = require('react-native');
|
|
130
|
+
const name = String(NativeModules?.YaverInfo?.inheritedGuestProjectName || '').trim();
|
|
131
|
+
return name || undefined;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Not inside Yaver's container, or react-native unavailable (unit tests).
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Build the app-identity half of a feedback report's metadata.
|
|
140
|
+
*
|
|
141
|
+
* `resolveAppIdentity()` has always fed /vibing/execute and /dev/reload-app,
|
|
142
|
+
* so the agent could route a "vibe on THIS app" request to the right repo —
|
|
143
|
+
* but nothing fed /feedback. Reports arrived with no identity at all, so the
|
|
144
|
+
* agent's fix router fell through to its own working directory and edited
|
|
145
|
+
* whichever repo it happened to be sitting in. This closes that gap by
|
|
146
|
+
* reusing the same resolver for the feedback path.
|
|
147
|
+
*
|
|
148
|
+
* Precedence, most to least trustworthy:
|
|
149
|
+
* 1. What the host app declared (`FeedbackConfig.projectName`/`bundleId`).
|
|
150
|
+
* An app knows its own identity; nothing should override it.
|
|
151
|
+
* 2. The guest project Yaver's host shell pinned, when running as a Hermes
|
|
152
|
+
* guest. Ambient lookups describe Yaver there, not the guest.
|
|
153
|
+
* 3. Ambient expo-constants / native modules — correct for a standalone
|
|
154
|
+
* build, which is the common case.
|
|
155
|
+
*
|
|
156
|
+
* Every lookup is best-effort: a bare RN app with no expo-constants still
|
|
157
|
+
* produces a report, just one the agent resolves by its own means.
|
|
158
|
+
*/
|
|
159
|
+
function resolveReportIdentity(opts) {
|
|
160
|
+
let projectName = (opts?.projectName || '').trim() || undefined;
|
|
161
|
+
let bundleId = (opts?.bundleId || '').trim() || undefined;
|
|
162
|
+
let version;
|
|
163
|
+
let buildNumber;
|
|
164
|
+
if (isInsideYaverContainer()) {
|
|
165
|
+
// Every ambient lookup answers for the HOST here. Because the agent
|
|
166
|
+
// routes on bundle id first, letting Yaver's id through would resolve
|
|
167
|
+
// straight to Yaver's own repo and the guest's name would never be
|
|
168
|
+
// consulted — so nothing ambient is trusted in the container. The
|
|
169
|
+
// version is Yaver's too, and reporting it would only mislabel which
|
|
170
|
+
// build the report came from.
|
|
171
|
+
projectName = projectName || resolveInheritedGuestProjectName();
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
const ambient = resolveAppIdentity({ projectName, bundleId });
|
|
175
|
+
projectName = ambient.projectName;
|
|
176
|
+
bundleId = ambient.bundleId;
|
|
177
|
+
try {
|
|
178
|
+
const Constants = require('expo-constants').default ?? require('expo-constants');
|
|
179
|
+
const cfg = Constants?.expoConfig ?? Constants?.manifest ?? {};
|
|
180
|
+
version = Constants?.nativeAppVersion || cfg?.version;
|
|
181
|
+
buildNumber =
|
|
182
|
+
Constants?.nativeBuildVersion ||
|
|
183
|
+
cfg?.ios?.buildNumber ||
|
|
184
|
+
(cfg?.android?.versionCode != null ? String(cfg.android.versionCode) : undefined);
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// expo-constants not installed (bare RN). Version is cosmetic — the
|
|
188
|
+
// router keys off appName/bundleId, both of which survive without it.
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const app = {};
|
|
192
|
+
if (bundleId)
|
|
193
|
+
app.bundleId = bundleId;
|
|
194
|
+
if (version)
|
|
195
|
+
app.version = version;
|
|
196
|
+
if (buildNumber)
|
|
197
|
+
app.buildNumber = buildNumber;
|
|
198
|
+
if (!projectName && !bundleId) {
|
|
199
|
+
return { app };
|
|
200
|
+
}
|
|
201
|
+
const project = { surface: opts?.surface ?? 'mobile' };
|
|
202
|
+
if (projectName) {
|
|
203
|
+
project.projectName = projectName;
|
|
204
|
+
project.appName = projectName;
|
|
205
|
+
}
|
|
206
|
+
// Note: projectPath is intentionally omitted — the agent ignores
|
|
207
|
+
// client-supplied paths on feedback reports and resolves them itself.
|
|
208
|
+
if (bundleId)
|
|
209
|
+
project.bundleId = bundleId;
|
|
210
|
+
if (opts?.surfaces)
|
|
211
|
+
project.surfaces = opts.surfaces;
|
|
212
|
+
if (opts?.stack)
|
|
213
|
+
project.stack = opts.stack;
|
|
214
|
+
if (opts?.stacks)
|
|
215
|
+
project.stacks = opts.stacks;
|
|
216
|
+
if (opts?.testSurfaces)
|
|
217
|
+
project.testSurfaces = opts.testSurfaces;
|
|
218
|
+
if (opts?.feedbackSdk)
|
|
219
|
+
project.feedbackSdk = opts.feedbackSdk;
|
|
220
|
+
if (opts?.feedbackTransport)
|
|
221
|
+
project.feedbackTransport = opts.feedbackTransport;
|
|
222
|
+
if (opts?.voiceCapabilities)
|
|
223
|
+
project.voiceCapabilities = opts.voiceCapabilities;
|
|
224
|
+
if (opts?.sttProvider)
|
|
225
|
+
project.sttProvider = opts.sttProvider;
|
|
226
|
+
if (opts?.ttsProvider)
|
|
227
|
+
project.ttsProvider = opts.ttsProvider;
|
|
228
|
+
return { appName: projectName, app, project };
|
|
229
|
+
}
|
|
87
230
|
/**
|
|
88
231
|
* Translate a raw Go-agent error into something a user can act on.
|
|
89
232
|
*
|
|
@@ -327,19 +470,24 @@ class P2PClient {
|
|
|
327
470
|
}
|
|
328
471
|
/** Health check — returns true if the agent is reachable. */
|
|
329
472
|
async health() {
|
|
473
|
+
let timeoutId = null;
|
|
330
474
|
try {
|
|
331
475
|
const controller = new AbortController();
|
|
332
|
-
|
|
476
|
+
timeoutId = setTimeout(() => controller.abort(), 3000);
|
|
477
|
+
unrefTimer(timeoutId);
|
|
333
478
|
const response = await fetch(`${this.baseUrl}/health`, {
|
|
334
479
|
method: 'GET',
|
|
335
480
|
signal: controller.signal,
|
|
336
481
|
});
|
|
337
|
-
clearTimeout(timeoutId);
|
|
338
482
|
return response.ok;
|
|
339
483
|
}
|
|
340
484
|
catch {
|
|
341
485
|
return false;
|
|
342
486
|
}
|
|
487
|
+
finally {
|
|
488
|
+
if (timeoutId)
|
|
489
|
+
clearTimeout(timeoutId);
|
|
490
|
+
}
|
|
343
491
|
}
|
|
344
492
|
/** Get agent info (hostname, version, platform). */
|
|
345
493
|
async info() {
|
|
@@ -488,6 +636,78 @@ class P2PClient {
|
|
|
488
636
|
* via the BlackBox command channel.
|
|
489
637
|
* @param mode - "dev" for hot reload, "bundle" for native bundle rebuild
|
|
490
638
|
*/
|
|
639
|
+
/**
|
|
640
|
+
* Read the dev server's state so the overlay can decide WHICH reload
|
|
641
|
+
* actions to offer, and disable the rest with a reason.
|
|
642
|
+
*
|
|
643
|
+
* Returns null when the machine cannot be reached at all — which the
|
|
644
|
+
* caller must render as "not connected", never as "no dev server".
|
|
645
|
+
* Those are two different problems with two different fixes.
|
|
646
|
+
*/
|
|
647
|
+
async getDevServerStatus() {
|
|
648
|
+
try {
|
|
649
|
+
const resp = await fetch(`${this.baseUrl}${endpoints_1.AGENT_ENDPOINTS.devStatus}`, {
|
|
650
|
+
headers: this.authHeaders(),
|
|
651
|
+
});
|
|
652
|
+
if (!resp.ok)
|
|
653
|
+
return null;
|
|
654
|
+
const data = await resp.json().catch(() => ({}));
|
|
655
|
+
return {
|
|
656
|
+
running: data.running === true,
|
|
657
|
+
building: data.building === true,
|
|
658
|
+
framework: typeof data.framework === 'string' ? data.framework : undefined,
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
catch {
|
|
662
|
+
return null;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Trigger a reload with an EXPLICIT fast/full mode — no bundle fallback.
|
|
667
|
+
*
|
|
668
|
+
* `reloadApp('dev')` silently falls through to a bundle rebuild when the
|
|
669
|
+
* dev server is down, which is right for a one-button UX and wrong the
|
|
670
|
+
* moment the user picks between two named actions: someone who pressed
|
|
671
|
+
* "Full Reload" must not get a 60-second bundle rebuild without being
|
|
672
|
+
* told. So this method reports the failure instead, with a named cause.
|
|
673
|
+
*
|
|
674
|
+
* Auth: the SAME bearer used for the feedback POST. `/dev/reload` is
|
|
675
|
+
* registered under `authSDKOrGuest` in desktop/agent/httpserver.go and is
|
|
676
|
+
* already in the `guest-reload` SDK-token scope list — nothing widens.
|
|
677
|
+
*/
|
|
678
|
+
async reloadWithMode(mode, snapshot) {
|
|
679
|
+
if (mode === 'bundle')
|
|
680
|
+
return this.reloadApp('bundle');
|
|
681
|
+
let resp;
|
|
682
|
+
try {
|
|
683
|
+
resp = await fetch(`${this.baseUrl}${reloadActions_1.RELOAD_PATH}`, {
|
|
684
|
+
method: 'POST',
|
|
685
|
+
headers: this.authHeaders({ 'Content-Type': 'application/json' }),
|
|
686
|
+
body: JSON.stringify({ mode }),
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
catch (err) {
|
|
690
|
+
throw new Error((0, reloadActions_1.describeReloadFailure)(0, err instanceof Error ? err.message : '', snapshot));
|
|
691
|
+
}
|
|
692
|
+
if (!resp.ok) {
|
|
693
|
+
const text = await resp.text().catch(() => '');
|
|
694
|
+
throw new Error((0, reloadActions_1.describeReloadFailure)(resp.status, text, snapshot));
|
|
695
|
+
}
|
|
696
|
+
const payload = await resp.json().catch(() => ({}));
|
|
697
|
+
const nativeChangesDetected = payload.nativeChangesDetected === true;
|
|
698
|
+
return {
|
|
699
|
+
ok: true,
|
|
700
|
+
mode: 'dev',
|
|
701
|
+
acknowledged: true,
|
|
702
|
+
nativeChangesDetected,
|
|
703
|
+
changeClass: typeof payload.changeClass === 'string' ? payload.changeClass : undefined,
|
|
704
|
+
message: nativeChangesDetected
|
|
705
|
+
? 'Reload accepted, but native files changed — a rebuild is required.'
|
|
706
|
+
: mode === 'full'
|
|
707
|
+
? 'Full reload requested.'
|
|
708
|
+
: 'Hot reload requested.',
|
|
709
|
+
};
|
|
710
|
+
}
|
|
491
711
|
async reloadApp(mode = 'bundle', opts) {
|
|
492
712
|
// Default path: always rebuild a fresh Hermes bundle.
|
|
493
713
|
//
|
package/dist/ShakeDetector.js
CHANGED
|
@@ -84,6 +84,8 @@ class ShakeDetector {
|
|
|
84
84
|
* the `ShakeEvent` name a handful of third-party shake libraries emit.
|
|
85
85
|
*/
|
|
86
86
|
subscribeDevMenu(onShake) {
|
|
87
|
+
if (typeof react_native_1.DeviceEventEmitter?.addListener !== 'function')
|
|
88
|
+
return;
|
|
87
89
|
const eventName = react_native_1.Platform.OS === 'ios' ? 'shakeEvent' : 'ShakeEvent';
|
|
88
90
|
this.devMenuSub = react_native_1.DeviceEventEmitter.addListener(eventName, () => {
|
|
89
91
|
this.fire(onShake);
|
package/dist/YaverFeedback.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FeedbackConfig, CapturedError } from './types';
|
|
2
2
|
import { P2PClient } from './P2PClient';
|
|
3
|
+
import { CaptureStoreScreenshotsOptions, CaptureStoreScreenshotsResult } from './storeShots';
|
|
3
4
|
import { QuickIconColorPreset } from './preferences';
|
|
4
5
|
/**
|
|
5
6
|
* Main entry point for the Yaver Feedback SDK.
|
|
@@ -15,7 +16,26 @@ export declare class YaverFeedback {
|
|
|
15
16
|
* If no `agentUrl` is provided, the SDK will attempt auto-discovery
|
|
16
17
|
* via `YaverDiscovery` on the first `startReport()` call.
|
|
17
18
|
*/
|
|
19
|
+
/** The runtime lane, when running on web inside a Yaver preview WebView. */
|
|
20
|
+
static detectWebLane(): 'browser' | 'webrtc' | null;
|
|
21
|
+
/**
|
|
22
|
+
* Mount a draggable DOM floating "Y" icon for the BROWSER lane (RN-web). It
|
|
23
|
+
* lives in the WebView's document.body (position:fixed, max z-index), so it
|
|
24
|
+
* renders ON TOP of the page inside the WebView and is never occluded by the
|
|
25
|
+
* fullScreen preview modal — the one occlusion-proof affordance on iOS.
|
|
26
|
+
* Tap opens the SDK's existing report flow (the RN FeedbackModal renders in
|
|
27
|
+
* the same WebView DOM, also un-occluded). No-op off-web or off-lane, and
|
|
28
|
+
* idempotent (a re-init reuses the existing node).
|
|
29
|
+
*/
|
|
30
|
+
static mountBrowserLaneIcon(): void;
|
|
18
31
|
static init(cfg: FeedbackConfig): void;
|
|
32
|
+
/**
|
|
33
|
+
* Opt-in global crash handler. This wraps the existing React Native
|
|
34
|
+
* ErrorUtils handler and still calls it, so Sentry/Crashlytics/Bugsnag can
|
|
35
|
+
* remain the system of record. The SDK only uploads a crash report and,
|
|
36
|
+
* when configured, asks the agent to create a fix task.
|
|
37
|
+
*/
|
|
38
|
+
static installCrashHandler(): void;
|
|
19
39
|
/**
|
|
20
40
|
* Run agent discovery in the background.
|
|
21
41
|
* Called automatically from init() when no agentUrl is provided.
|
|
@@ -46,6 +66,29 @@ export declare class YaverFeedback {
|
|
|
46
66
|
static setAuthToken(token: string): Promise<void>;
|
|
47
67
|
/** Returns true once the SDK has a session token it can use. */
|
|
48
68
|
static isAuthed(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* On-device App Store screenshot capture (Engine 2). Walks the routes
|
|
71
|
+
* the host hands us, screenshots each, and uploads to the agent which
|
|
72
|
+
* runs the App Store Connect backend. agentUrl / authToken / relay
|
|
73
|
+
* password default to the SDK's resolved session; the host only has to
|
|
74
|
+
* supply a navigation ref + the ordered route list.
|
|
75
|
+
*
|
|
76
|
+
* YaverFeedback.captureStoreScreenshots({
|
|
77
|
+
* app: 'sfmg',
|
|
78
|
+
* navigationRef,
|
|
79
|
+
* routes: ['/(tabs)/dashboard', '/(tabs)/messages', '/(tabs)/clients'],
|
|
80
|
+
* submit: true,
|
|
81
|
+
* })
|
|
82
|
+
*/
|
|
83
|
+
static captureStoreScreenshots(opts: Omit<CaptureStoreScreenshotsOptions, 'agentUrl' | 'authToken' | 'relayPassword'> & Partial<Pick<CaptureStoreScreenshotsOptions, 'agentUrl' | 'authToken' | 'relayPassword'>>): Promise<CaptureStoreScreenshotsResult>;
|
|
84
|
+
/**
|
|
85
|
+
* Let the mobile app / CLI kick THIS device into self-capturing. Registers
|
|
86
|
+
* a BlackBox command listener that fires captureStoreScreenshots when the
|
|
87
|
+
* agent pushes a `capture_store_shots` command (its `data` may override
|
|
88
|
+
* `submit` / `locale`). Returns an unsubscribe fn. Call once after init,
|
|
89
|
+
* passing the app's navigation ref + the routes to walk.
|
|
90
|
+
*/
|
|
91
|
+
static enableStoreShotsOnCommand(opts: Omit<CaptureStoreScreenshotsOptions, 'agentUrl' | 'authToken' | 'relayPassword'>): () => void;
|
|
49
92
|
/**
|
|
50
93
|
* Request the embedded FeedbackModal to show the login screen. Works by
|
|
51
94
|
* emitting an event the modal listens for — avoids forcing the host app
|
|
@@ -112,6 +155,46 @@ export declare class YaverFeedback {
|
|
|
112
155
|
* - All methods become active
|
|
113
156
|
*/
|
|
114
157
|
static setEnabled(value: boolean): void;
|
|
158
|
+
/**
|
|
159
|
+
* Turn shake-to-report on or off without tearing the SDK down.
|
|
160
|
+
*
|
|
161
|
+
* `trigger` is read only inside init(), so before this the only ways to
|
|
162
|
+
* stop listening for a shake were setEnabled(false) — which also kills the
|
|
163
|
+
* flight recorder and the agent command channel — or a re-init, which used
|
|
164
|
+
* to stack a duplicate command handler. Neither is what "turn the shake
|
|
165
|
+
* catcher off" should cost.
|
|
166
|
+
*
|
|
167
|
+
* Persists onto config.disableShakeGesture, so a later setEnabled(true)
|
|
168
|
+
* honours it rather than resurrecting the listener.
|
|
169
|
+
*/
|
|
170
|
+
static setShakeEnabled(value: boolean): void;
|
|
171
|
+
/** Whether the shake listener is currently armed. */
|
|
172
|
+
static isShakeEnabled(): boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Bring the shake listener in line with the current config. Idempotent —
|
|
175
|
+
* safe to call whenever `enabled`, `trigger`, or `disableShakeGesture`
|
|
176
|
+
* moves.
|
|
177
|
+
*/
|
|
178
|
+
private static syncShakeDetector;
|
|
179
|
+
private static stopShakeDetector;
|
|
180
|
+
/** Cancel a pending BlackBox auto-start retry chain. */
|
|
181
|
+
private static cancelBlackBoxAutoStart;
|
|
182
|
+
/**
|
|
183
|
+
* Start BlackBox as soon as we have BOTH an agentUrl and a token, polling
|
|
184
|
+
* until then.
|
|
185
|
+
*
|
|
186
|
+
* Both conditions are mandatory and deliberate: starting without a token
|
|
187
|
+
* makes the SSE channel 401 and retry with backoff, which is the tight
|
|
188
|
+
* string-concat + JSON-parse loop that used to SIGSEGV Hermes on iOS 18.3.1
|
|
189
|
+
* during Screenshot & Fix. This only re-checks that same guard over time.
|
|
190
|
+
*
|
|
191
|
+
* Bounded at ~60s: long enough for AsyncStorage hydration plus a Convex
|
|
192
|
+
* discovery round trip on a cold, off-LAN start, short enough that a device
|
|
193
|
+
* whose user never signs in stops polling. Giving up here costs nothing —
|
|
194
|
+
* setAuthToken() and startReport() both reschedule, so signing in later
|
|
195
|
+
* still brings the channel up.
|
|
196
|
+
*/
|
|
197
|
+
private static scheduleBlackBoxAutoStart;
|
|
115
198
|
/** Returns whether the SDK is currently enabled. */
|
|
116
199
|
static isEnabled(): boolean;
|
|
117
200
|
/** Returns the current config, or null if not initialized. */
|
|
@@ -150,6 +233,21 @@ export declare class YaverFeedback {
|
|
|
150
233
|
* // wrapper, and the chain stays intact.
|
|
151
234
|
*/
|
|
152
235
|
static wrapErrorHandler(next?: ((error: Error, isFatal?: boolean) => void) | null): (error: Error, isFatal?: boolean) => void;
|
|
236
|
+
/**
|
|
237
|
+
* Upload a crash-aware feedback bundle. Apps can call this from their own
|
|
238
|
+
* error boundary/global handler. If crashReporting.autoFix is true, the SDK
|
|
239
|
+
* also triggers the agent's feedback-fix task; reload delivery still happens
|
|
240
|
+
* through the existing BlackBox command stream.
|
|
241
|
+
*/
|
|
242
|
+
static reportCrash(error: Error, opts?: {
|
|
243
|
+
isFatal?: boolean;
|
|
244
|
+
source?: 'manual' | 'global-handler';
|
|
245
|
+
metadata?: Record<string, unknown>;
|
|
246
|
+
autoFix?: boolean;
|
|
247
|
+
}): Promise<{
|
|
248
|
+
reportId?: string;
|
|
249
|
+
taskId?: string;
|
|
250
|
+
}>;
|
|
153
251
|
/**
|
|
154
252
|
* Returns the P2P client instance.
|
|
155
253
|
* Available after init if agentUrl is set, or after first successful discovery.
|