yaver-feedback-react-native 0.7.6 → 0.7.7
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/dist/FeedbackModal.js +16 -7
- package/dist/MachinePickerScreen.js +23 -5
- package/dist/P2PClient.js +15 -8
- package/dist/YaverFeedback.js +12 -13
- package/package.json +1 -1
- package/src/FeedbackModal.tsx +18 -7
- package/src/MachinePickerScreen.tsx +19 -5
- package/src/P2PClient.ts +21 -9
- package/src/YaverFeedback.ts +12 -12
package/dist/FeedbackModal.js
CHANGED
|
@@ -105,18 +105,27 @@ const FeedbackModal = () => {
|
|
|
105
105
|
await fn(client);
|
|
106
106
|
}
|
|
107
107
|
catch (err) {
|
|
108
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
const
|
|
108
|
+
const msg = (err instanceof Error ? err.message : String(err)) || '';
|
|
109
|
+
// Avoid unbounded `.*` in regex — on RN 0.81 / Hermes rope
|
|
110
|
+
// strings plus a background SSE reconnect, that pattern has
|
|
111
|
+
// reliably SIGSEGV'd Hermes's string-view flattening path.
|
|
112
|
+
// Split into short, literal-only alternations.
|
|
113
|
+
const lower = msg.toLowerCase();
|
|
114
|
+
const authFailed = lower.indexOf('invalid token') >= 0 ||
|
|
115
|
+
lower.indexOf('unauthor') >= 0 ||
|
|
116
|
+
lower.indexOf(' 401') >= 0 ||
|
|
117
|
+
lower.indexOf(' 403') >= 0;
|
|
114
118
|
if (authFailed) {
|
|
115
119
|
await YaverFeedback_1.YaverFeedback.signOut();
|
|
116
120
|
YaverFeedback_1.YaverFeedback.showLogin();
|
|
117
121
|
throw new Error('Session expired — please sign in again.');
|
|
118
122
|
}
|
|
119
|
-
const transient =
|
|
123
|
+
const transient = lower.indexOf('network request failed') >= 0 ||
|
|
124
|
+
lower.indexOf('econnrefused') >= 0 ||
|
|
125
|
+
lower.indexOf('failed to fetch') >= 0 ||
|
|
126
|
+
lower.indexOf('fetch failed') >= 0 ||
|
|
127
|
+
lower.indexOf('aborted') >= 0 ||
|
|
128
|
+
lower.indexOf('timeout') >= 0;
|
|
120
129
|
if (!transient)
|
|
121
130
|
throw err;
|
|
122
131
|
const ok = await YaverFeedback_1.YaverFeedback.reconnect();
|
|
@@ -94,15 +94,33 @@ const YaverMachinePickerScreen = ({ token, currentDeviceId, onPick, onCancel, })
|
|
|
94
94
|
: device.needsAuth
|
|
95
95
|
? '#f59e0b'
|
|
96
96
|
: '#22c55e';
|
|
97
|
+
// Derive a single short status phrase the user can act on.
|
|
98
|
+
let statusLine = device.platform;
|
|
99
|
+
if (!device.isOnline) {
|
|
100
|
+
statusLine = 'Offline — start `yaver serve` on the Mac';
|
|
101
|
+
}
|
|
102
|
+
else if (device.needsAuth) {
|
|
103
|
+
statusLine =
|
|
104
|
+
'Needs pairing — open the Yaver app to adopt this machine';
|
|
105
|
+
}
|
|
106
|
+
else if (device.runnerDown) {
|
|
107
|
+
statusLine = 'Runner down — restart the coding agent on the Mac';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Happy-path subtitle: platform + optional host/share hint.
|
|
111
|
+
statusLine = device.platform;
|
|
112
|
+
if (device.isGuest && device.hostEmail) {
|
|
113
|
+
statusLine = `${statusLine} • ${device.hostEmail}`;
|
|
114
|
+
}
|
|
115
|
+
else if (device.accessScope === 'shared-scoped') {
|
|
116
|
+
statusLine = `${statusLine} • paylaşılan`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
97
119
|
return (<react_native_1.TouchableOpacity key={device.deviceId} style={[styles.deviceRow, selected && styles.deviceSelected]} onPress={() => handlePick(device)}>
|
|
98
120
|
<react_native_1.View style={[styles.health, { backgroundColor: healthColor }]}/>
|
|
99
121
|
<react_native_1.View style={{ flex: 1 }}>
|
|
100
122
|
<react_native_1.Text style={styles.deviceName}>{device.name || device.deviceId}</react_native_1.Text>
|
|
101
|
-
<react_native_1.Text style={styles.deviceMeta}>
|
|
102
|
-
{device.platform}
|
|
103
|
-
{device.isGuest && device.hostEmail ? ` • ${device.hostEmail}` : ''}
|
|
104
|
-
{device.accessScope === 'shared-scoped' ? ' • paylaşılan' : ''}
|
|
105
|
-
</react_native_1.Text>
|
|
123
|
+
<react_native_1.Text style={styles.deviceMeta}>{statusLine}</react_native_1.Text>
|
|
106
124
|
</react_native_1.View>
|
|
107
125
|
{selected && <react_native_1.Text style={styles.selectedBadge}>seçili</react_native_1.Text>}
|
|
108
126
|
</react_native_1.TouchableOpacity>);
|
package/dist/P2PClient.js
CHANGED
|
@@ -13,21 +13,28 @@ const react_native_1 = require("react-native");
|
|
|
13
13
|
* running on the host machine".
|
|
14
14
|
*/
|
|
15
15
|
function friendlyReloadError(status, body) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
// Plain .indexOf instead of regex — short literal tests sidestep
|
|
17
|
+
// a Hermes rope-flatten SIGSEGV we saw on RN 0.81 / iOS 18.3.1
|
|
18
|
+
// when the same body was already being processed by a concurrent
|
|
19
|
+
// SSE reconnect loop.
|
|
20
|
+
const lower = (body || '').toLowerCase();
|
|
21
|
+
const hasRefused = lower.indexOf('connection refused') >= 0 ||
|
|
22
|
+
lower.indexOf('econnrefused') >= 0;
|
|
23
|
+
const hasLoopback = lower.indexOf('127.0.0.1') >= 0 || lower.indexOf('localhost') >= 0;
|
|
24
|
+
if (hasRefused && hasLoopback) {
|
|
19
25
|
return ('No dev server running on your machine. ' +
|
|
20
26
|
'Start Metro with `yaver dev start` or use "Screenshot & Fix" instead.');
|
|
21
27
|
}
|
|
22
|
-
if (
|
|
28
|
+
if (lower.indexOf('no dev server') >= 0 ||
|
|
29
|
+
lower.indexOf('not running') >= 0) {
|
|
23
30
|
return 'No dev server running on your machine. Start Metro first.';
|
|
24
31
|
}
|
|
25
|
-
if (status === 403)
|
|
32
|
+
if (status === 401 || status === 403) {
|
|
26
33
|
return 'Agent rejected the session — please sign in again.';
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (status >= 500)
|
|
34
|
+
}
|
|
35
|
+
if (status >= 500) {
|
|
30
36
|
return 'Agent hit an internal error while reloading. Check `yaver logs`.';
|
|
37
|
+
}
|
|
31
38
|
return `Reload failed (${status}).`;
|
|
32
39
|
}
|
|
33
40
|
/**
|
package/dist/YaverFeedback.js
CHANGED
|
@@ -171,19 +171,18 @@ class YaverFeedback {
|
|
|
171
171
|
});
|
|
172
172
|
}
|
|
173
173
|
});
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
174
|
+
// NOTE: BlackBox.start() is intentionally NOT auto-called here.
|
|
175
|
+
// An earlier version (0.7.6) did auto-start it, and when the
|
|
176
|
+
// agent was in bootstrap / needs-auth mode — which can happen
|
|
177
|
+
// any time after `yaver serve` restarts before the user pairs —
|
|
178
|
+
// the SSE channel retried with exponential backoff on 401s,
|
|
179
|
+
// producing a tight loop of string concatenation + JSON parse
|
|
180
|
+
// that tripped a Hermes rope-string SIGSEGV on iOS 18.3.1
|
|
181
|
+
// during any other JS-thread regex work (e.g. react-native-
|
|
182
|
+
// view-shot's internal string handling during Screenshot &
|
|
183
|
+
// Fix). Host apps call BlackBox.start() explicitly once they
|
|
184
|
+
// know the agent URL + token are valid (SFMG does this inside
|
|
185
|
+
// its YaverFeedbackWidget after auth).
|
|
187
186
|
}
|
|
188
187
|
// NOTE: We intentionally do NOT hook ErrorUtils.setGlobalHandler().
|
|
189
188
|
// Sentry, Crashlytics, Bugsnag, and other tools all compete for that
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yaver-feedback-react-native",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.7",
|
|
4
4
|
"description": "Visual feedback SDK for Yaver — bug reports, screen recording, voice annotations, and local-first developer workflows",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/src/FeedbackModal.tsx
CHANGED
|
@@ -116,18 +116,29 @@ export const FeedbackModal: React.FC = () => {
|
|
|
116
116
|
try {
|
|
117
117
|
await fn(client);
|
|
118
118
|
} catch (err) {
|
|
119
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
const
|
|
119
|
+
const msg = (err instanceof Error ? err.message : String(err)) || '';
|
|
120
|
+
// Avoid unbounded `.*` in regex — on RN 0.81 / Hermes rope
|
|
121
|
+
// strings plus a background SSE reconnect, that pattern has
|
|
122
|
+
// reliably SIGSEGV'd Hermes's string-view flattening path.
|
|
123
|
+
// Split into short, literal-only alternations.
|
|
124
|
+
const lower = msg.toLowerCase();
|
|
125
|
+
const authFailed =
|
|
126
|
+
lower.indexOf('invalid token') >= 0 ||
|
|
127
|
+
lower.indexOf('unauthor') >= 0 ||
|
|
128
|
+
lower.indexOf(' 401') >= 0 ||
|
|
129
|
+
lower.indexOf(' 403') >= 0;
|
|
125
130
|
if (authFailed) {
|
|
126
131
|
await YaverFeedback.signOut();
|
|
127
132
|
YaverFeedback.showLogin();
|
|
128
133
|
throw new Error('Session expired — please sign in again.');
|
|
129
134
|
}
|
|
130
|
-
const transient =
|
|
135
|
+
const transient =
|
|
136
|
+
lower.indexOf('network request failed') >= 0 ||
|
|
137
|
+
lower.indexOf('econnrefused') >= 0 ||
|
|
138
|
+
lower.indexOf('failed to fetch') >= 0 ||
|
|
139
|
+
lower.indexOf('fetch failed') >= 0 ||
|
|
140
|
+
lower.indexOf('aborted') >= 0 ||
|
|
141
|
+
lower.indexOf('timeout') >= 0;
|
|
131
142
|
if (!transient) throw err;
|
|
132
143
|
const ok = await YaverFeedback.reconnect();
|
|
133
144
|
if (!ok) throw err;
|
|
@@ -87,6 +87,24 @@ export const YaverMachinePickerScreen: React.FC<YaverMachinePickerProps> = ({
|
|
|
87
87
|
: device.needsAuth
|
|
88
88
|
? '#f59e0b'
|
|
89
89
|
: '#22c55e';
|
|
90
|
+
// Derive a single short status phrase the user can act on.
|
|
91
|
+
let statusLine = device.platform;
|
|
92
|
+
if (!device.isOnline) {
|
|
93
|
+
statusLine = 'Offline — start `yaver serve` on the Mac';
|
|
94
|
+
} else if (device.needsAuth) {
|
|
95
|
+
statusLine =
|
|
96
|
+
'Needs pairing — open the Yaver app to adopt this machine';
|
|
97
|
+
} else if (device.runnerDown) {
|
|
98
|
+
statusLine = 'Runner down — restart the coding agent on the Mac';
|
|
99
|
+
} else {
|
|
100
|
+
// Happy-path subtitle: platform + optional host/share hint.
|
|
101
|
+
statusLine = device.platform;
|
|
102
|
+
if (device.isGuest && device.hostEmail) {
|
|
103
|
+
statusLine = `${statusLine} • ${device.hostEmail}`;
|
|
104
|
+
} else if (device.accessScope === 'shared-scoped') {
|
|
105
|
+
statusLine = `${statusLine} • paylaşılan`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
90
108
|
return (
|
|
91
109
|
<TouchableOpacity
|
|
92
110
|
key={device.deviceId}
|
|
@@ -96,11 +114,7 @@ export const YaverMachinePickerScreen: React.FC<YaverMachinePickerProps> = ({
|
|
|
96
114
|
<View style={[styles.health, { backgroundColor: healthColor }]} />
|
|
97
115
|
<View style={{ flex: 1 }}>
|
|
98
116
|
<Text style={styles.deviceName}>{device.name || device.deviceId}</Text>
|
|
99
|
-
<Text style={styles.deviceMeta}>
|
|
100
|
-
{device.platform}
|
|
101
|
-
{device.isGuest && device.hostEmail ? ` • ${device.hostEmail}` : ''}
|
|
102
|
-
{device.accessScope === 'shared-scoped' ? ' • paylaşılan' : ''}
|
|
103
|
-
</Text>
|
|
117
|
+
<Text style={styles.deviceMeta}>{statusLine}</Text>
|
|
104
118
|
</View>
|
|
105
119
|
{selected && <Text style={styles.selectedBadge}>seçili</Text>}
|
|
106
120
|
</TouchableOpacity>
|
package/src/P2PClient.ts
CHANGED
|
@@ -18,22 +18,34 @@ export interface FeedbackEvent {
|
|
|
18
18
|
* running on the host machine".
|
|
19
19
|
*/
|
|
20
20
|
function friendlyReloadError(status: number, body: string): string {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
)
|
|
21
|
+
// Plain .indexOf instead of regex — short literal tests sidestep
|
|
22
|
+
// a Hermes rope-flatten SIGSEGV we saw on RN 0.81 / iOS 18.3.1
|
|
23
|
+
// when the same body was already being processed by a concurrent
|
|
24
|
+
// SSE reconnect loop.
|
|
25
|
+
const lower = (body || '').toLowerCase();
|
|
26
|
+
const hasRefused =
|
|
27
|
+
lower.indexOf('connection refused') >= 0 ||
|
|
28
|
+
lower.indexOf('econnrefused') >= 0;
|
|
29
|
+
const hasLoopback =
|
|
30
|
+
lower.indexOf('127.0.0.1') >= 0 || lower.indexOf('localhost') >= 0;
|
|
31
|
+
if (hasRefused && hasLoopback) {
|
|
26
32
|
return (
|
|
27
33
|
'No dev server running on your machine. ' +
|
|
28
34
|
'Start Metro with `yaver dev start` or use "Screenshot & Fix" instead.'
|
|
29
35
|
);
|
|
30
36
|
}
|
|
31
|
-
if (
|
|
37
|
+
if (
|
|
38
|
+
lower.indexOf('no dev server') >= 0 ||
|
|
39
|
+
lower.indexOf('not running') >= 0
|
|
40
|
+
) {
|
|
32
41
|
return 'No dev server running on your machine. Start Metro first.';
|
|
33
42
|
}
|
|
34
|
-
if (status ===
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
if (status === 401 || status === 403) {
|
|
44
|
+
return 'Agent rejected the session — please sign in again.';
|
|
45
|
+
}
|
|
46
|
+
if (status >= 500) {
|
|
47
|
+
return 'Agent hit an internal error while reloading. Check `yaver logs`.';
|
|
48
|
+
}
|
|
37
49
|
return `Reload failed (${status}).`;
|
|
38
50
|
}
|
|
39
51
|
|
package/src/YaverFeedback.ts
CHANGED
|
@@ -185,18 +185,18 @@ export class YaverFeedback {
|
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
187
|
});
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
188
|
+
// NOTE: BlackBox.start() is intentionally NOT auto-called here.
|
|
189
|
+
// An earlier version (0.7.6) did auto-start it, and when the
|
|
190
|
+
// agent was in bootstrap / needs-auth mode — which can happen
|
|
191
|
+
// any time after `yaver serve` restarts before the user pairs —
|
|
192
|
+
// the SSE channel retried with exponential backoff on 401s,
|
|
193
|
+
// producing a tight loop of string concatenation + JSON parse
|
|
194
|
+
// that tripped a Hermes rope-string SIGSEGV on iOS 18.3.1
|
|
195
|
+
// during any other JS-thread regex work (e.g. react-native-
|
|
196
|
+
// view-shot's internal string handling during Screenshot &
|
|
197
|
+
// Fix). Host apps call BlackBox.start() explicitly once they
|
|
198
|
+
// know the agent URL + token are valid (SFMG does this inside
|
|
199
|
+
// its YaverFeedbackWidget after auth).
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
// NOTE: We intentionally do NOT hook ErrorUtils.setGlobalHandler().
|