@synostudios/app-reporter 0.4.0 → 0.5.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.tsx +10 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synostudios/app-reporter",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "A draggable bug-report button for Expo apps: screenshot, note and context, sent to your own endpoint. Shows only in dev and TestFlight builds.",
5
5
  "license": "MIT",
6
6
  "main": "src/index.tsx",
package/src/index.tsx CHANGED
@@ -66,7 +66,7 @@ function Reporter({ harnessUrl, getToken, buildSha, getContext, insets = { top:
66
66
  // Let the button disappear from the screen before capturing it.
67
67
  await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
68
68
  try {
69
- setShot(await captureScreen({ format: "png", result: "base64" }));
69
+ setShot(await captureScreen({ format: "jpg", quality: 0.8, result: "base64" })); // a full-screen PNG ran to 3–5 MB, over the harness's 4.5 MB limit (413)
70
70
  } catch {
71
71
  setShot(""); // report without a screenshot rather than not at all
72
72
  } finally {
@@ -175,7 +175,7 @@ function Sheet({ shot, top, onClose, send }: { shot: string; top: number; onClos
175
175
  ) : (
176
176
  <View style={styles.body}>
177
177
  {/* eslint-disable-next-line jsx-a11y/alt-text -- a web rule; React Native's Image is labelled with accessibilityLabel */}
178
- {shot ? <Image source={{ uri: `data:image/png;base64,${shot}` }} style={styles.thumb} resizeMode="contain" accessibilityLabel="Screenshot of the screen you were on" /> : <Text style={styles.muted}>No screenshot (capture failed).</Text>}
178
+ {shot ? <Image source={{ uri: `data:image/jpeg;base64,${shot}` }} style={styles.thumb} resizeMode="contain" accessibilityLabel="Screenshot of the screen you were on" /> : <Text style={styles.muted}>No screenshot (capture failed).</Text>}
179
179
  <TextInput
180
180
  value={note}
181
181
  onChangeText={setNote}
@@ -208,10 +208,13 @@ async function send(r: {
208
208
  if (!r.token) return { error: "Sign in to the app first: the harness takes reports from its testers only." };
209
209
  // One JSON body with the screenshot as base64: multipart file parts differ between React Native's fetch and Expo's
210
210
  // (Expo's rejects { uri, name, type } parts with "Unsupported FormDataPart implementation").
211
+ // The harness runs on Vercel, which answers 413 to a request body over 4.5 MB. A screenshot that would push the report
212
+ // past that is left out (and the note says so) rather than losing the whole report.
213
+ const tooBig = !!r.shot && r.shot.length > MAX_SHOT_CHARS;
211
214
  const payload = JSON.stringify({
212
- screenshot: r.shot || undefined,
215
+ screenshot: tooBig ? undefined : r.shot || undefined,
213
216
  report: {
214
- note: r.note.trim(),
217
+ note: r.note.trim() + (tooBig ? "\n\n(The screenshot was too large to send and was left out.)" : ""),
215
218
  expected: r.expected.trim() || undefined,
216
219
  meta: {
217
220
  bundleId: Application.applicationId,
@@ -241,6 +244,9 @@ async function send(r: {
241
244
  }
242
245
  }
243
246
 
247
+ // About 3 MB of image once decoded: the rest of the 4.5 MB request is the JSON and base64's overhead.
248
+ export const MAX_SHOT_CHARS = 4_000_000;
249
+
244
250
  const styles = StyleSheet.create({
245
251
  button: {
246
252
  position: "absolute",