@bbearai/react-native 0.4.0 → 0.4.1

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/index.js CHANGED
@@ -11634,6 +11634,11 @@ function captureError(error, errorInfo) {
11634
11634
  componentStack: errorInfo?.componentStack
11635
11635
  };
11636
11636
  }
11637
+ var formatPgError = (e) => {
11638
+ if (!e || typeof e !== "object") return { raw: e };
11639
+ const { message, code, details, hint } = e;
11640
+ return { message, code, details, hint };
11641
+ };
11637
11642
  var DEFAULT_SUPABASE_URL = "https://kyxgzjnqgvapvlnvqawz.supabase.co";
11638
11643
  var getEnvVar = (key) => {
11639
11644
  try {
@@ -11803,7 +11808,7 @@ var BugBearClient = class {
11803
11808
  )
11804
11809
  `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true }).limit(100);
11805
11810
  if (error) {
11806
- console.error("BugBear: Failed to fetch assignments", error);
11811
+ console.error("BugBear: Failed to fetch assignments", formatPgError(error));
11807
11812
  return [];
11808
11813
  }
11809
11814
  const mapped = (data || []).map((item) => ({
@@ -12031,7 +12036,7 @@ var BugBearClient = class {
12031
12036
  }
12032
12037
  const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
12033
12038
  if (error) {
12034
- console.error("BugBear: Failed to skip assignment", error);
12039
+ console.error("BugBear: Failed to skip assignment", formatPgError(error));
12035
12040
  return { success: false, error: error.message };
12036
12041
  }
12037
12042
  return { success: true };
@@ -12210,7 +12215,7 @@ var BugBearClient = class {
12210
12215
  p_tester_id: testerInfo.id
12211
12216
  });
12212
12217
  if (error) {
12213
- console.error("BugBear: Failed to fetch tester stats", error);
12218
+ console.error("BugBear: Failed to fetch tester stats", formatPgError(error));
12214
12219
  return null;
12215
12220
  }
12216
12221
  return data;
@@ -12361,7 +12366,7 @@ var BugBearClient = class {
12361
12366
  if (updates.platforms !== void 0) updateData.platforms = updates.platforms;
12362
12367
  const { error } = await this.supabase.from("testers").update(updateData).eq("id", testerInfo.id);
12363
12368
  if (error) {
12364
- console.error("BugBear: updateTesterProfile error", error);
12369
+ console.error("BugBear: updateTesterProfile error", formatPgError(error));
12365
12370
  return { success: false, error: error.message };
12366
12371
  }
12367
12372
  return { success: true };
@@ -12383,14 +12388,14 @@ var BugBearClient = class {
12383
12388
  */
12384
12389
  async isQAEnabled() {
12385
12390
  try {
12386
- const { data, error } = await this.supabase.from("projects").select("is_qa_enabled").eq("id", this.config.projectId).single();
12391
+ const { data, error } = await this.supabase.rpc("check_qa_enabled", {
12392
+ p_project_id: this.config.projectId
12393
+ });
12387
12394
  if (error) {
12388
- if (error.code !== "PGRST116") {
12389
- console.warn("BugBear: Could not check QA status", error.message || error.code || "Unknown error");
12390
- }
12395
+ console.warn("BugBear: Could not check QA status", error.message || error.code || "Unknown error");
12391
12396
  return true;
12392
12397
  }
12393
- return data?.is_qa_enabled ?? true;
12398
+ return data ?? true;
12394
12399
  } catch (err) {
12395
12400
  return true;
12396
12401
  }
@@ -12420,7 +12425,7 @@ var BugBearClient = class {
12420
12425
  upsert: false
12421
12426
  });
12422
12427
  if (error) {
12423
- console.error("BugBear: Failed to upload screenshot", error);
12428
+ console.error("BugBear: Failed to upload screenshot", formatPgError(error));
12424
12429
  return null;
12425
12430
  }
12426
12431
  const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
@@ -12451,7 +12456,7 @@ var BugBearClient = class {
12451
12456
  upsert: false
12452
12457
  });
12453
12458
  if (error) {
12454
- console.error("BugBear: Failed to upload image from URI", error);
12459
+ console.error("BugBear: Failed to upload image from URI", formatPgError(error));
12455
12460
  return null;
12456
12461
  }
12457
12462
  const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
@@ -12526,7 +12531,7 @@ var BugBearClient = class {
12526
12531
  }
12527
12532
  const { data, error } = await query;
12528
12533
  if (error) {
12529
- console.error("BugBear: Failed to fetch fix requests", error);
12534
+ console.error("BugBear: Failed to fetch fix requests", formatPgError(error));
12530
12535
  return [];
12531
12536
  }
12532
12537
  return (data || []).map((fr) => ({
@@ -12557,7 +12562,7 @@ var BugBearClient = class {
12557
12562
  p_tester_id: testerInfo.id
12558
12563
  });
12559
12564
  if (error) {
12560
- console.error("BugBear: Failed to fetch threads via RPC", error);
12565
+ console.error("BugBear: Failed to fetch threads via RPC", formatPgError(error));
12561
12566
  return [];
12562
12567
  }
12563
12568
  if (!data || data.length === 0) return [];
@@ -12601,7 +12606,7 @@ var BugBearClient = class {
12601
12606
  attachments
12602
12607
  `).eq("thread_id", threadId).order("created_at", { ascending: true }).limit(200);
12603
12608
  if (error) {
12604
- console.error("BugBear: Failed to fetch messages", error);
12609
+ console.error("BugBear: Failed to fetch messages", formatPgError(error));
12605
12610
  return [];
12606
12611
  }
12607
12612
  return (data || []).map((msg) => ({
@@ -12645,7 +12650,7 @@ var BugBearClient = class {
12645
12650
  }
12646
12651
  const { error } = await this.supabase.from("discussion_messages").insert(insertData);
12647
12652
  if (error) {
12648
- console.error("BugBear: Failed to send message", error);
12653
+ console.error("BugBear: Failed to send message", formatPgError(error));
12649
12654
  return false;
12650
12655
  }
12651
12656
  await this.markThreadAsRead(threadId);
@@ -12761,7 +12766,7 @@ var BugBearClient = class {
12761
12766
  p_platform: options.platform || null
12762
12767
  });
12763
12768
  if (error) {
12764
- console.error("BugBear: Failed to start session", error);
12769
+ console.error("BugBear: Failed to start session", formatPgError(error));
12765
12770
  return { success: false, error: error.message };
12766
12771
  }
12767
12772
  const session = await this.getSession(data);
@@ -12786,7 +12791,7 @@ var BugBearClient = class {
12786
12791
  p_routes_covered: options.routesCovered || null
12787
12792
  });
12788
12793
  if (error) {
12789
- console.error("BugBear: Failed to end session", error);
12794
+ console.error("BugBear: Failed to end session", formatPgError(error));
12790
12795
  return { success: false, error: error.message };
12791
12796
  }
12792
12797
  const session = this.transformSession(data);
@@ -12834,7 +12839,7 @@ var BugBearClient = class {
12834
12839
  if (!testerInfo) return [];
12835
12840
  const { data, error } = await this.supabase.from("qa_sessions").select("*").eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).order("started_at", { ascending: false }).limit(limit);
12836
12841
  if (error) {
12837
- console.error("BugBear: Failed to fetch session history", error);
12842
+ console.error("BugBear: Failed to fetch session history", formatPgError(error));
12838
12843
  return [];
12839
12844
  }
12840
12845
  return (data || []).map((s) => this.transformSession(s));
@@ -12862,7 +12867,7 @@ var BugBearClient = class {
12862
12867
  p_app_context: options.appContext || null
12863
12868
  });
12864
12869
  if (error) {
12865
- console.error("BugBear: Failed to add finding", error);
12870
+ console.error("BugBear: Failed to add finding", formatPgError(error));
12866
12871
  return { success: false, error: error.message };
12867
12872
  }
12868
12873
  const finding = this.transformFinding(data);
@@ -12880,7 +12885,7 @@ var BugBearClient = class {
12880
12885
  try {
12881
12886
  const { data, error } = await this.supabase.from("qa_findings").select("*").eq("session_id", sessionId).order("created_at", { ascending: true }).limit(100);
12882
12887
  if (error) {
12883
- console.error("BugBear: Failed to fetch findings", error);
12888
+ console.error("BugBear: Failed to fetch findings", formatPgError(error));
12884
12889
  return [];
12885
12890
  }
12886
12891
  return (data || []).map((f) => this.transformFinding(f));
@@ -12898,7 +12903,7 @@ var BugBearClient = class {
12898
12903
  p_finding_id: findingId
12899
12904
  });
12900
12905
  if (error) {
12901
- console.error("BugBear: Failed to convert finding", error);
12906
+ console.error("BugBear: Failed to convert finding", formatPgError(error));
12902
12907
  return { success: false, error: error.message };
12903
12908
  }
12904
12909
  return { success: true, bugId: data };
@@ -12919,7 +12924,7 @@ var BugBearClient = class {
12919
12924
  dismissed_at: (/* @__PURE__ */ new Date()).toISOString()
12920
12925
  }).eq("id", findingId);
12921
12926
  if (error) {
12922
- console.error("BugBear: Failed to dismiss finding", error);
12927
+ console.error("BugBear: Failed to dismiss finding", formatPgError(error));
12923
12928
  return { success: false, error: error.message };
12924
12929
  }
12925
12930
  return { success: true };
@@ -13782,7 +13787,10 @@ function TestDetailScreen({ testId, nav }) {
13782
13787
  import_react_native4.Keyboard.dismiss();
13783
13788
  setIsSubmitting(true);
13784
13789
  try {
13785
- await client.failAssignment(displayedAssignment.id);
13790
+ const result = await client.failAssignment(displayedAssignment.id);
13791
+ if (!result.success) {
13792
+ console.error("BugBear: Failed to mark assignment as failed", result.error);
13793
+ }
13786
13794
  await refreshAssignments();
13787
13795
  nav.replace({
13788
13796
  name: "REPORT",
@@ -14446,6 +14454,7 @@ function ReportScreen({ nav, prefill }) {
14446
14454
  const [submitting, setSubmitting] = (0, import_react10.useState)(false);
14447
14455
  const [error, setError] = (0, import_react10.useState)(null);
14448
14456
  const images = useImageAttachments(uploadImage, 5, "screenshots");
14457
+ const isRetestFailure = prefill?.type === "test_fail";
14449
14458
  const isBugType = reportType === "bug" || reportType === "test_fail";
14450
14459
  const handleSubmit = async () => {
14451
14460
  if (!client || !description.trim()) return;
@@ -14485,7 +14494,50 @@ function ReportScreen({ nav, prefill }) {
14485
14494
  setSubmitting(false);
14486
14495
  }
14487
14496
  };
14488
- return /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, null, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: shared.label }, "What are you reporting?"), /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, { style: styles7.typeRow }, [
14497
+ return /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, null, isRetestFailure ? /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, { style: styles7.retestBanner }, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: styles7.retestIcon }, "\u{1F504}"), /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, null, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: styles7.retestTitle }, "Bug Still Present"), /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: styles7.retestSubtitle }, "The fix did not resolve this issue"))), /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, { style: styles7.section }, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: shared.label }, "Severity"), /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, { style: styles7.severityRow }, [
14498
+ { sev: "critical", color: "#ef4444" },
14499
+ { sev: "high", color: "#f97316" },
14500
+ { sev: "medium", color: "#eab308" },
14501
+ { sev: "low", color: "#6b7280" }
14502
+ ].map(({ sev, color }) => /* @__PURE__ */ import_react10.default.createElement(
14503
+ import_react_native9.TouchableOpacity,
14504
+ {
14505
+ key: sev,
14506
+ style: [styles7.sevButton, severity === sev && { backgroundColor: `${color}30`, borderColor: color }],
14507
+ onPress: () => setSeverity(sev)
14508
+ },
14509
+ /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: [styles7.sevText, severity === sev && { color }] }, sev)
14510
+ )))), /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, { style: styles7.section }, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: shared.label }, "What went wrong?"), /* @__PURE__ */ import_react10.default.createElement(
14511
+ import_react_native9.TextInput,
14512
+ {
14513
+ style: styles7.descInput,
14514
+ value: description,
14515
+ onChangeText: setDescription,
14516
+ placeholder: "Describe what you observed. What still doesn't work?",
14517
+ placeholderTextColor: colors.textMuted,
14518
+ multiline: true,
14519
+ numberOfLines: 4,
14520
+ textAlignVertical: "top"
14521
+ }
14522
+ )), /* @__PURE__ */ import_react10.default.createElement(
14523
+ ImagePickerButtons,
14524
+ {
14525
+ images: images.images,
14526
+ maxImages: 5,
14527
+ onPickGallery: images.pickFromGallery,
14528
+ onPickCamera: images.pickFromCamera,
14529
+ onRemove: images.removeImage,
14530
+ label: "Attachments (optional)"
14531
+ }
14532
+ ), error && /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, { style: styles7.errorBanner }, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: styles7.errorText }, error)), /* @__PURE__ */ import_react10.default.createElement(
14533
+ import_react_native9.TouchableOpacity,
14534
+ {
14535
+ style: [shared.primaryButton, styles7.retestSubmitButton, (!description.trim() || submitting || images.isUploading) && shared.primaryButtonDisabled, { marginTop: 20 }],
14536
+ onPress: handleSubmit,
14537
+ disabled: !description.trim() || submitting || images.isUploading
14538
+ },
14539
+ /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: shared.primaryButtonText }, images.isUploading ? "Uploading images..." : submitting ? "Submitting..." : error ? "Retry" : "Submit Failed Retest")
14540
+ )) : /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: shared.label }, "What are you reporting?"), /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, { style: styles7.typeRow }, [
14489
14541
  { type: "bug", label: "Bug", icon: "\u{1F41B}" },
14490
14542
  { type: "feedback", label: "Feedback", icon: "\u{1F4A1}" },
14491
14543
  { type: "suggestion", label: "Idea", icon: "\u2728" }
@@ -14550,7 +14602,7 @@ function ReportScreen({ nav, prefill }) {
14550
14602
  disabled: !description.trim() || submitting || images.isUploading
14551
14603
  },
14552
14604
  /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: shared.primaryButtonText }, images.isUploading ? "Uploading images..." : submitting ? "Submitting..." : error ? "Retry" : "Submit Report")
14553
- ));
14605
+ )));
14554
14606
  }
14555
14607
  var styles7 = import_react_native9.StyleSheet.create({
14556
14608
  typeRow: { flexDirection: "row", gap: 10, marginBottom: 20 },
@@ -14567,7 +14619,12 @@ var styles7 = import_react_native9.StyleSheet.create({
14567
14619
  screenInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 12, paddingVertical: 8, fontSize: 13, color: colors.textPrimary },
14568
14620
  screenHint: { fontSize: 11, color: colors.textMuted, marginTop: 4 },
14569
14621
  errorBanner: { backgroundColor: "#7f1d1d", borderWidth: 1, borderColor: "#991b1b", borderRadius: 8, padding: 12, marginTop: 16 },
14570
- errorText: { fontSize: 13, color: "#fca5a5", lineHeight: 18 }
14622
+ errorText: { fontSize: 13, color: "#fca5a5", lineHeight: 18 },
14623
+ retestBanner: { flexDirection: "row", alignItems: "center", gap: 10, backgroundColor: "#422006", borderWidth: 1, borderColor: "#854d0e", borderRadius: 10, paddingVertical: 12, paddingHorizontal: 14, marginBottom: 20 },
14624
+ retestIcon: { fontSize: 16 },
14625
+ retestTitle: { fontSize: 15, fontWeight: "600", color: "#fbbf24", lineHeight: 20 },
14626
+ retestSubtitle: { fontSize: 12, color: "#d97706", lineHeight: 16 },
14627
+ retestSubmitButton: { backgroundColor: "#b45309" }
14571
14628
  });
14572
14629
 
14573
14630
  // src/widget/screens/ReportSuccessScreen.tsx
package/dist/index.mjs CHANGED
@@ -11601,6 +11601,11 @@ function captureError(error, errorInfo) {
11601
11601
  componentStack: errorInfo?.componentStack
11602
11602
  };
11603
11603
  }
11604
+ var formatPgError = (e) => {
11605
+ if (!e || typeof e !== "object") return { raw: e };
11606
+ const { message, code, details, hint } = e;
11607
+ return { message, code, details, hint };
11608
+ };
11604
11609
  var DEFAULT_SUPABASE_URL = "https://kyxgzjnqgvapvlnvqawz.supabase.co";
11605
11610
  var getEnvVar = (key) => {
11606
11611
  try {
@@ -11770,7 +11775,7 @@ var BugBearClient = class {
11770
11775
  )
11771
11776
  `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true }).limit(100);
11772
11777
  if (error) {
11773
- console.error("BugBear: Failed to fetch assignments", error);
11778
+ console.error("BugBear: Failed to fetch assignments", formatPgError(error));
11774
11779
  return [];
11775
11780
  }
11776
11781
  const mapped = (data || []).map((item) => ({
@@ -11998,7 +12003,7 @@ var BugBearClient = class {
11998
12003
  }
11999
12004
  const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
12000
12005
  if (error) {
12001
- console.error("BugBear: Failed to skip assignment", error);
12006
+ console.error("BugBear: Failed to skip assignment", formatPgError(error));
12002
12007
  return { success: false, error: error.message };
12003
12008
  }
12004
12009
  return { success: true };
@@ -12177,7 +12182,7 @@ var BugBearClient = class {
12177
12182
  p_tester_id: testerInfo.id
12178
12183
  });
12179
12184
  if (error) {
12180
- console.error("BugBear: Failed to fetch tester stats", error);
12185
+ console.error("BugBear: Failed to fetch tester stats", formatPgError(error));
12181
12186
  return null;
12182
12187
  }
12183
12188
  return data;
@@ -12328,7 +12333,7 @@ var BugBearClient = class {
12328
12333
  if (updates.platforms !== void 0) updateData.platforms = updates.platforms;
12329
12334
  const { error } = await this.supabase.from("testers").update(updateData).eq("id", testerInfo.id);
12330
12335
  if (error) {
12331
- console.error("BugBear: updateTesterProfile error", error);
12336
+ console.error("BugBear: updateTesterProfile error", formatPgError(error));
12332
12337
  return { success: false, error: error.message };
12333
12338
  }
12334
12339
  return { success: true };
@@ -12350,14 +12355,14 @@ var BugBearClient = class {
12350
12355
  */
12351
12356
  async isQAEnabled() {
12352
12357
  try {
12353
- const { data, error } = await this.supabase.from("projects").select("is_qa_enabled").eq("id", this.config.projectId).single();
12358
+ const { data, error } = await this.supabase.rpc("check_qa_enabled", {
12359
+ p_project_id: this.config.projectId
12360
+ });
12354
12361
  if (error) {
12355
- if (error.code !== "PGRST116") {
12356
- console.warn("BugBear: Could not check QA status", error.message || error.code || "Unknown error");
12357
- }
12362
+ console.warn("BugBear: Could not check QA status", error.message || error.code || "Unknown error");
12358
12363
  return true;
12359
12364
  }
12360
- return data?.is_qa_enabled ?? true;
12365
+ return data ?? true;
12361
12366
  } catch (err) {
12362
12367
  return true;
12363
12368
  }
@@ -12387,7 +12392,7 @@ var BugBearClient = class {
12387
12392
  upsert: false
12388
12393
  });
12389
12394
  if (error) {
12390
- console.error("BugBear: Failed to upload screenshot", error);
12395
+ console.error("BugBear: Failed to upload screenshot", formatPgError(error));
12391
12396
  return null;
12392
12397
  }
12393
12398
  const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
@@ -12418,7 +12423,7 @@ var BugBearClient = class {
12418
12423
  upsert: false
12419
12424
  });
12420
12425
  if (error) {
12421
- console.error("BugBear: Failed to upload image from URI", error);
12426
+ console.error("BugBear: Failed to upload image from URI", formatPgError(error));
12422
12427
  return null;
12423
12428
  }
12424
12429
  const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
@@ -12493,7 +12498,7 @@ var BugBearClient = class {
12493
12498
  }
12494
12499
  const { data, error } = await query;
12495
12500
  if (error) {
12496
- console.error("BugBear: Failed to fetch fix requests", error);
12501
+ console.error("BugBear: Failed to fetch fix requests", formatPgError(error));
12497
12502
  return [];
12498
12503
  }
12499
12504
  return (data || []).map((fr) => ({
@@ -12524,7 +12529,7 @@ var BugBearClient = class {
12524
12529
  p_tester_id: testerInfo.id
12525
12530
  });
12526
12531
  if (error) {
12527
- console.error("BugBear: Failed to fetch threads via RPC", error);
12532
+ console.error("BugBear: Failed to fetch threads via RPC", formatPgError(error));
12528
12533
  return [];
12529
12534
  }
12530
12535
  if (!data || data.length === 0) return [];
@@ -12568,7 +12573,7 @@ var BugBearClient = class {
12568
12573
  attachments
12569
12574
  `).eq("thread_id", threadId).order("created_at", { ascending: true }).limit(200);
12570
12575
  if (error) {
12571
- console.error("BugBear: Failed to fetch messages", error);
12576
+ console.error("BugBear: Failed to fetch messages", formatPgError(error));
12572
12577
  return [];
12573
12578
  }
12574
12579
  return (data || []).map((msg) => ({
@@ -12612,7 +12617,7 @@ var BugBearClient = class {
12612
12617
  }
12613
12618
  const { error } = await this.supabase.from("discussion_messages").insert(insertData);
12614
12619
  if (error) {
12615
- console.error("BugBear: Failed to send message", error);
12620
+ console.error("BugBear: Failed to send message", formatPgError(error));
12616
12621
  return false;
12617
12622
  }
12618
12623
  await this.markThreadAsRead(threadId);
@@ -12728,7 +12733,7 @@ var BugBearClient = class {
12728
12733
  p_platform: options.platform || null
12729
12734
  });
12730
12735
  if (error) {
12731
- console.error("BugBear: Failed to start session", error);
12736
+ console.error("BugBear: Failed to start session", formatPgError(error));
12732
12737
  return { success: false, error: error.message };
12733
12738
  }
12734
12739
  const session = await this.getSession(data);
@@ -12753,7 +12758,7 @@ var BugBearClient = class {
12753
12758
  p_routes_covered: options.routesCovered || null
12754
12759
  });
12755
12760
  if (error) {
12756
- console.error("BugBear: Failed to end session", error);
12761
+ console.error("BugBear: Failed to end session", formatPgError(error));
12757
12762
  return { success: false, error: error.message };
12758
12763
  }
12759
12764
  const session = this.transformSession(data);
@@ -12801,7 +12806,7 @@ var BugBearClient = class {
12801
12806
  if (!testerInfo) return [];
12802
12807
  const { data, error } = await this.supabase.from("qa_sessions").select("*").eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).order("started_at", { ascending: false }).limit(limit);
12803
12808
  if (error) {
12804
- console.error("BugBear: Failed to fetch session history", error);
12809
+ console.error("BugBear: Failed to fetch session history", formatPgError(error));
12805
12810
  return [];
12806
12811
  }
12807
12812
  return (data || []).map((s) => this.transformSession(s));
@@ -12829,7 +12834,7 @@ var BugBearClient = class {
12829
12834
  p_app_context: options.appContext || null
12830
12835
  });
12831
12836
  if (error) {
12832
- console.error("BugBear: Failed to add finding", error);
12837
+ console.error("BugBear: Failed to add finding", formatPgError(error));
12833
12838
  return { success: false, error: error.message };
12834
12839
  }
12835
12840
  const finding = this.transformFinding(data);
@@ -12847,7 +12852,7 @@ var BugBearClient = class {
12847
12852
  try {
12848
12853
  const { data, error } = await this.supabase.from("qa_findings").select("*").eq("session_id", sessionId).order("created_at", { ascending: true }).limit(100);
12849
12854
  if (error) {
12850
- console.error("BugBear: Failed to fetch findings", error);
12855
+ console.error("BugBear: Failed to fetch findings", formatPgError(error));
12851
12856
  return [];
12852
12857
  }
12853
12858
  return (data || []).map((f) => this.transformFinding(f));
@@ -12865,7 +12870,7 @@ var BugBearClient = class {
12865
12870
  p_finding_id: findingId
12866
12871
  });
12867
12872
  if (error) {
12868
- console.error("BugBear: Failed to convert finding", error);
12873
+ console.error("BugBear: Failed to convert finding", formatPgError(error));
12869
12874
  return { success: false, error: error.message };
12870
12875
  }
12871
12876
  return { success: true, bugId: data };
@@ -12886,7 +12891,7 @@ var BugBearClient = class {
12886
12891
  dismissed_at: (/* @__PURE__ */ new Date()).toISOString()
12887
12892
  }).eq("id", findingId);
12888
12893
  if (error) {
12889
- console.error("BugBear: Failed to dismiss finding", error);
12894
+ console.error("BugBear: Failed to dismiss finding", formatPgError(error));
12890
12895
  return { success: false, error: error.message };
12891
12896
  }
12892
12897
  return { success: true };
@@ -13764,7 +13769,10 @@ function TestDetailScreen({ testId, nav }) {
13764
13769
  Keyboard.dismiss();
13765
13770
  setIsSubmitting(true);
13766
13771
  try {
13767
- await client.failAssignment(displayedAssignment.id);
13772
+ const result = await client.failAssignment(displayedAssignment.id);
13773
+ if (!result.success) {
13774
+ console.error("BugBear: Failed to mark assignment as failed", result.error);
13775
+ }
13768
13776
  await refreshAssignments();
13769
13777
  nav.replace({
13770
13778
  name: "REPORT",
@@ -14428,6 +14436,7 @@ function ReportScreen({ nav, prefill }) {
14428
14436
  const [submitting, setSubmitting] = useState6(false);
14429
14437
  const [error, setError] = useState6(null);
14430
14438
  const images = useImageAttachments(uploadImage, 5, "screenshots");
14439
+ const isRetestFailure = prefill?.type === "test_fail";
14431
14440
  const isBugType = reportType === "bug" || reportType === "test_fail";
14432
14441
  const handleSubmit = async () => {
14433
14442
  if (!client || !description.trim()) return;
@@ -14467,7 +14476,50 @@ function ReportScreen({ nav, prefill }) {
14467
14476
  setSubmitting(false);
14468
14477
  }
14469
14478
  };
14470
- return /* @__PURE__ */ React8.createElement(View7, null, /* @__PURE__ */ React8.createElement(Text7, { style: shared.label }, "What are you reporting?"), /* @__PURE__ */ React8.createElement(View7, { style: styles7.typeRow }, [
14479
+ return /* @__PURE__ */ React8.createElement(View7, null, isRetestFailure ? /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(View7, { style: styles7.retestBanner }, /* @__PURE__ */ React8.createElement(Text7, { style: styles7.retestIcon }, "\u{1F504}"), /* @__PURE__ */ React8.createElement(View7, null, /* @__PURE__ */ React8.createElement(Text7, { style: styles7.retestTitle }, "Bug Still Present"), /* @__PURE__ */ React8.createElement(Text7, { style: styles7.retestSubtitle }, "The fix did not resolve this issue"))), /* @__PURE__ */ React8.createElement(View7, { style: styles7.section }, /* @__PURE__ */ React8.createElement(Text7, { style: shared.label }, "Severity"), /* @__PURE__ */ React8.createElement(View7, { style: styles7.severityRow }, [
14480
+ { sev: "critical", color: "#ef4444" },
14481
+ { sev: "high", color: "#f97316" },
14482
+ { sev: "medium", color: "#eab308" },
14483
+ { sev: "low", color: "#6b7280" }
14484
+ ].map(({ sev, color }) => /* @__PURE__ */ React8.createElement(
14485
+ TouchableOpacity7,
14486
+ {
14487
+ key: sev,
14488
+ style: [styles7.sevButton, severity === sev && { backgroundColor: `${color}30`, borderColor: color }],
14489
+ onPress: () => setSeverity(sev)
14490
+ },
14491
+ /* @__PURE__ */ React8.createElement(Text7, { style: [styles7.sevText, severity === sev && { color }] }, sev)
14492
+ )))), /* @__PURE__ */ React8.createElement(View7, { style: styles7.section }, /* @__PURE__ */ React8.createElement(Text7, { style: shared.label }, "What went wrong?"), /* @__PURE__ */ React8.createElement(
14493
+ TextInput3,
14494
+ {
14495
+ style: styles7.descInput,
14496
+ value: description,
14497
+ onChangeText: setDescription,
14498
+ placeholder: "Describe what you observed. What still doesn't work?",
14499
+ placeholderTextColor: colors.textMuted,
14500
+ multiline: true,
14501
+ numberOfLines: 4,
14502
+ textAlignVertical: "top"
14503
+ }
14504
+ )), /* @__PURE__ */ React8.createElement(
14505
+ ImagePickerButtons,
14506
+ {
14507
+ images: images.images,
14508
+ maxImages: 5,
14509
+ onPickGallery: images.pickFromGallery,
14510
+ onPickCamera: images.pickFromCamera,
14511
+ onRemove: images.removeImage,
14512
+ label: "Attachments (optional)"
14513
+ }
14514
+ ), error && /* @__PURE__ */ React8.createElement(View7, { style: styles7.errorBanner }, /* @__PURE__ */ React8.createElement(Text7, { style: styles7.errorText }, error)), /* @__PURE__ */ React8.createElement(
14515
+ TouchableOpacity7,
14516
+ {
14517
+ style: [shared.primaryButton, styles7.retestSubmitButton, (!description.trim() || submitting || images.isUploading) && shared.primaryButtonDisabled, { marginTop: 20 }],
14518
+ onPress: handleSubmit,
14519
+ disabled: !description.trim() || submitting || images.isUploading
14520
+ },
14521
+ /* @__PURE__ */ React8.createElement(Text7, { style: shared.primaryButtonText }, images.isUploading ? "Uploading images..." : submitting ? "Submitting..." : error ? "Retry" : "Submit Failed Retest")
14522
+ )) : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(Text7, { style: shared.label }, "What are you reporting?"), /* @__PURE__ */ React8.createElement(View7, { style: styles7.typeRow }, [
14471
14523
  { type: "bug", label: "Bug", icon: "\u{1F41B}" },
14472
14524
  { type: "feedback", label: "Feedback", icon: "\u{1F4A1}" },
14473
14525
  { type: "suggestion", label: "Idea", icon: "\u2728" }
@@ -14532,7 +14584,7 @@ function ReportScreen({ nav, prefill }) {
14532
14584
  disabled: !description.trim() || submitting || images.isUploading
14533
14585
  },
14534
14586
  /* @__PURE__ */ React8.createElement(Text7, { style: shared.primaryButtonText }, images.isUploading ? "Uploading images..." : submitting ? "Submitting..." : error ? "Retry" : "Submit Report")
14535
- ));
14587
+ )));
14536
14588
  }
14537
14589
  var styles7 = StyleSheet8.create({
14538
14590
  typeRow: { flexDirection: "row", gap: 10, marginBottom: 20 },
@@ -14549,7 +14601,12 @@ var styles7 = StyleSheet8.create({
14549
14601
  screenInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 12, paddingVertical: 8, fontSize: 13, color: colors.textPrimary },
14550
14602
  screenHint: { fontSize: 11, color: colors.textMuted, marginTop: 4 },
14551
14603
  errorBanner: { backgroundColor: "#7f1d1d", borderWidth: 1, borderColor: "#991b1b", borderRadius: 8, padding: 12, marginTop: 16 },
14552
- errorText: { fontSize: 13, color: "#fca5a5", lineHeight: 18 }
14604
+ errorText: { fontSize: 13, color: "#fca5a5", lineHeight: 18 },
14605
+ retestBanner: { flexDirection: "row", alignItems: "center", gap: 10, backgroundColor: "#422006", borderWidth: 1, borderColor: "#854d0e", borderRadius: 10, paddingVertical: 12, paddingHorizontal: 14, marginBottom: 20 },
14606
+ retestIcon: { fontSize: 16 },
14607
+ retestTitle: { fontSize: 15, fontWeight: "600", color: "#fbbf24", lineHeight: 20 },
14608
+ retestSubtitle: { fontSize: 12, color: "#d97706", lineHeight: 16 },
14609
+ retestSubmitButton: { backgroundColor: "#b45309" }
14553
14610
  });
14554
14611
 
14555
14612
  // src/widget/screens/ReportSuccessScreen.tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/react-native",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "BugBear React Native components for mobile apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",