@bbearai/react-native 0.5.0 → 0.5.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
@@ -11393,7 +11393,7 @@ function shouldShowDeprecationWarning() {
11393
11393
  }
11394
11394
  if (shouldShowDeprecationWarning()) console.warn("\u26A0\uFE0F Node.js 18 and below are deprecated and will no longer be supported in future versions of @supabase/supabase-js. Please upgrade to Node.js 20 or later. For more information, visit: https://github.com/orgs/supabase/discussions/37217");
11395
11395
 
11396
- // node_modules/@bbearai/core/dist/index.mjs
11396
+ // ../core/dist/index.mjs
11397
11397
  var MAX_CONSOLE_LOGS = 50;
11398
11398
  var MAX_NETWORK_REQUESTS = 20;
11399
11399
  var MAX_NAVIGATION_HISTORY = 20;
@@ -11653,6 +11653,7 @@ var HOSTED_BUGBEAR_ANON_KEY = getEnvVar("BUGBEAR_ANON_KEY") || getEnvVar("NEXT_P
11653
11653
  var BugBearClient = class {
11654
11654
  constructor(config) {
11655
11655
  this.navigationHistory = [];
11656
+ this.reportSubmitInFlight = false;
11656
11657
  this.config = config;
11657
11658
  this.supabase = createClient(
11658
11659
  config.supabaseUrl || DEFAULT_SUPABASE_URL,
@@ -11713,6 +11714,10 @@ var BugBearClient = class {
11713
11714
  * Submit a report
11714
11715
  */
11715
11716
  async submitReport(report) {
11717
+ if (this.reportSubmitInFlight) {
11718
+ return { success: false, error: "A report is already being submitted" };
11719
+ }
11720
+ this.reportSubmitInFlight = true;
11716
11721
  try {
11717
11722
  const validationError = this.validateReport(report);
11718
11723
  if (validationError) {
@@ -11764,6 +11769,8 @@ var BugBearClient = class {
11764
11769
  } catch (err) {
11765
11770
  const message = err instanceof Error ? err.message : "Unknown error";
11766
11771
  return { success: false, error: message };
11772
+ } finally {
11773
+ this.reportSubmitInFlight = false;
11767
11774
  }
11768
11775
  }
11769
11776
  /**
@@ -11804,6 +11811,14 @@ var BugBearClient = class {
11804
11811
  name,
11805
11812
  description,
11806
11813
  sort_order
11814
+ ),
11815
+ role:project_roles(
11816
+ id,
11817
+ name,
11818
+ slug,
11819
+ color,
11820
+ description,
11821
+ login_hint
11807
11822
  )
11808
11823
  )
11809
11824
  `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true }).limit(100);
@@ -11841,6 +11856,14 @@ var BugBearClient = class {
11841
11856
  name: item.test_case.group.name,
11842
11857
  description: item.test_case.group.description,
11843
11858
  sortOrder: item.test_case.group.sort_order
11859
+ } : void 0,
11860
+ role: item.test_case.role ? {
11861
+ id: item.test_case.role.id,
11862
+ name: item.test_case.role.name,
11863
+ slug: item.test_case.role.slug,
11864
+ color: item.test_case.role.color,
11865
+ description: item.test_case.role.description,
11866
+ loginHint: item.test_case.role.login_hint
11844
11867
  } : void 0
11845
11868
  }
11846
11869
  }));
@@ -12256,8 +12279,8 @@ var BugBearClient = class {
12256
12279
  return "Maximum 10 screenshots allowed";
12257
12280
  }
12258
12281
  for (const url of report.screenshots) {
12259
- if (typeof url !== "string" || url.length > 2e3) {
12260
- return "Invalid screenshot URL";
12282
+ if (typeof url !== "string" || url.length > 2e3 || !/^https?:\/\//i.test(url)) {
12283
+ return "Invalid screenshot URL (must be an HTTP/HTTPS URL)";
12261
12284
  }
12262
12285
  }
12263
12286
  }
@@ -12646,7 +12669,10 @@ var BugBearClient = class {
12646
12669
  content
12647
12670
  };
12648
12671
  if (attachments && attachments.length > 0) {
12649
- insertData.attachments = attachments;
12672
+ const safeAttachments = attachments.filter((a) => /^https?:\/\//i.test(a.url));
12673
+ if (safeAttachments.length > 0) {
12674
+ insertData.attachments = safeAttachments;
12675
+ }
12650
12676
  }
12651
12677
  const { error } = await this.supabase.from("discussion_messages").insert(insertData);
12652
12678
  if (error) {
@@ -14496,11 +14522,14 @@ function ReportScreen({ nav, prefill }) {
14496
14522
  const [affectedScreen, setAffectedScreen] = (0, import_react10.useState)("");
14497
14523
  const [submitting, setSubmitting] = (0, import_react10.useState)(false);
14498
14524
  const [error, setError] = (0, import_react10.useState)(null);
14525
+ const submittingRef = (0, import_react10.useRef)(false);
14499
14526
  const images = useImageAttachments(uploadImage, 5, "screenshots");
14500
14527
  const isRetestFailure = prefill?.type === "test_fail";
14501
14528
  const isBugType = reportType === "bug" || reportType === "test_fail";
14502
14529
  const handleSubmit = async () => {
14503
14530
  if (!client || !description.trim()) return;
14531
+ if (submittingRef.current) return;
14532
+ submittingRef.current = true;
14504
14533
  setSubmitting(true);
14505
14534
  setError(null);
14506
14535
  try {
@@ -14524,17 +14553,18 @@ function ReportScreen({ nav, prefill }) {
14524
14553
  console.error("BugBear: Report submission failed", result.error);
14525
14554
  setError(result.error || "Failed to submit report. Please try again.");
14526
14555
  setSubmitting(false);
14556
+ submittingRef.current = false;
14527
14557
  return;
14528
14558
  }
14529
14559
  if (prefill?.assignmentId) {
14530
14560
  await refreshAssignments();
14531
14561
  }
14532
- setSubmitting(false);
14533
14562
  nav.replace({ name: "REPORT_SUCCESS" });
14534
14563
  } catch (err) {
14535
14564
  console.error("BugBear: Report submission error", err);
14536
14565
  setError(err instanceof Error ? err.message : "An unexpected error occurred. Please try again.");
14537
14566
  setSubmitting(false);
14567
+ submittingRef.current = false;
14538
14568
  }
14539
14569
  };
14540
14570
  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 }, [
package/dist/index.mjs CHANGED
@@ -11360,7 +11360,7 @@ function shouldShowDeprecationWarning() {
11360
11360
  }
11361
11361
  if (shouldShowDeprecationWarning()) console.warn("\u26A0\uFE0F Node.js 18 and below are deprecated and will no longer be supported in future versions of @supabase/supabase-js. Please upgrade to Node.js 20 or later. For more information, visit: https://github.com/orgs/supabase/discussions/37217");
11362
11362
 
11363
- // node_modules/@bbearai/core/dist/index.mjs
11363
+ // ../core/dist/index.mjs
11364
11364
  var MAX_CONSOLE_LOGS = 50;
11365
11365
  var MAX_NETWORK_REQUESTS = 20;
11366
11366
  var MAX_NAVIGATION_HISTORY = 20;
@@ -11620,6 +11620,7 @@ var HOSTED_BUGBEAR_ANON_KEY = getEnvVar("BUGBEAR_ANON_KEY") || getEnvVar("NEXT_P
11620
11620
  var BugBearClient = class {
11621
11621
  constructor(config) {
11622
11622
  this.navigationHistory = [];
11623
+ this.reportSubmitInFlight = false;
11623
11624
  this.config = config;
11624
11625
  this.supabase = createClient(
11625
11626
  config.supabaseUrl || DEFAULT_SUPABASE_URL,
@@ -11680,6 +11681,10 @@ var BugBearClient = class {
11680
11681
  * Submit a report
11681
11682
  */
11682
11683
  async submitReport(report) {
11684
+ if (this.reportSubmitInFlight) {
11685
+ return { success: false, error: "A report is already being submitted" };
11686
+ }
11687
+ this.reportSubmitInFlight = true;
11683
11688
  try {
11684
11689
  const validationError = this.validateReport(report);
11685
11690
  if (validationError) {
@@ -11731,6 +11736,8 @@ var BugBearClient = class {
11731
11736
  } catch (err) {
11732
11737
  const message = err instanceof Error ? err.message : "Unknown error";
11733
11738
  return { success: false, error: message };
11739
+ } finally {
11740
+ this.reportSubmitInFlight = false;
11734
11741
  }
11735
11742
  }
11736
11743
  /**
@@ -11771,6 +11778,14 @@ var BugBearClient = class {
11771
11778
  name,
11772
11779
  description,
11773
11780
  sort_order
11781
+ ),
11782
+ role:project_roles(
11783
+ id,
11784
+ name,
11785
+ slug,
11786
+ color,
11787
+ description,
11788
+ login_hint
11774
11789
  )
11775
11790
  )
11776
11791
  `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true }).limit(100);
@@ -11808,6 +11823,14 @@ var BugBearClient = class {
11808
11823
  name: item.test_case.group.name,
11809
11824
  description: item.test_case.group.description,
11810
11825
  sortOrder: item.test_case.group.sort_order
11826
+ } : void 0,
11827
+ role: item.test_case.role ? {
11828
+ id: item.test_case.role.id,
11829
+ name: item.test_case.role.name,
11830
+ slug: item.test_case.role.slug,
11831
+ color: item.test_case.role.color,
11832
+ description: item.test_case.role.description,
11833
+ loginHint: item.test_case.role.login_hint
11811
11834
  } : void 0
11812
11835
  }
11813
11836
  }));
@@ -12223,8 +12246,8 @@ var BugBearClient = class {
12223
12246
  return "Maximum 10 screenshots allowed";
12224
12247
  }
12225
12248
  for (const url of report.screenshots) {
12226
- if (typeof url !== "string" || url.length > 2e3) {
12227
- return "Invalid screenshot URL";
12249
+ if (typeof url !== "string" || url.length > 2e3 || !/^https?:\/\//i.test(url)) {
12250
+ return "Invalid screenshot URL (must be an HTTP/HTTPS URL)";
12228
12251
  }
12229
12252
  }
12230
12253
  }
@@ -12613,7 +12636,10 @@ var BugBearClient = class {
12613
12636
  content
12614
12637
  };
12615
12638
  if (attachments && attachments.length > 0) {
12616
- insertData.attachments = attachments;
12639
+ const safeAttachments = attachments.filter((a) => /^https?:\/\//i.test(a.url));
12640
+ if (safeAttachments.length > 0) {
12641
+ insertData.attachments = safeAttachments;
12642
+ }
12617
12643
  }
12618
12644
  const { error } = await this.supabase.from("discussion_messages").insert(insertData);
12619
12645
  if (error) {
@@ -13213,7 +13239,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
13213
13239
  }
13214
13240
 
13215
13241
  // src/BugBearButton.tsx
13216
- import React14, { useState as useState10, useRef as useRef2 } from "react";
13242
+ import React14, { useState as useState10, useRef as useRef3 } from "react";
13217
13243
  import {
13218
13244
  View as View13,
13219
13245
  Text as Text13,
@@ -14468,7 +14494,7 @@ var styles6 = StyleSheet7.create({
14468
14494
  });
14469
14495
 
14470
14496
  // src/widget/screens/ReportScreen.tsx
14471
- import React8, { useState as useState6 } from "react";
14497
+ import React8, { useState as useState6, useRef as useRef2 } from "react";
14472
14498
  import { View as View7, Text as Text7, TouchableOpacity as TouchableOpacity7, TextInput as TextInput3, StyleSheet as StyleSheet8 } from "react-native";
14473
14499
  function ReportScreen({ nav, prefill }) {
14474
14500
  const { client, getDeviceInfo, uploadImage, refreshAssignments } = useBugBear();
@@ -14478,11 +14504,14 @@ function ReportScreen({ nav, prefill }) {
14478
14504
  const [affectedScreen, setAffectedScreen] = useState6("");
14479
14505
  const [submitting, setSubmitting] = useState6(false);
14480
14506
  const [error, setError] = useState6(null);
14507
+ const submittingRef = useRef2(false);
14481
14508
  const images = useImageAttachments(uploadImage, 5, "screenshots");
14482
14509
  const isRetestFailure = prefill?.type === "test_fail";
14483
14510
  const isBugType = reportType === "bug" || reportType === "test_fail";
14484
14511
  const handleSubmit = async () => {
14485
14512
  if (!client || !description.trim()) return;
14513
+ if (submittingRef.current) return;
14514
+ submittingRef.current = true;
14486
14515
  setSubmitting(true);
14487
14516
  setError(null);
14488
14517
  try {
@@ -14506,17 +14535,18 @@ function ReportScreen({ nav, prefill }) {
14506
14535
  console.error("BugBear: Report submission failed", result.error);
14507
14536
  setError(result.error || "Failed to submit report. Please try again.");
14508
14537
  setSubmitting(false);
14538
+ submittingRef.current = false;
14509
14539
  return;
14510
14540
  }
14511
14541
  if (prefill?.assignmentId) {
14512
14542
  await refreshAssignments();
14513
14543
  }
14514
- setSubmitting(false);
14515
14544
  nav.replace({ name: "REPORT_SUCCESS" });
14516
14545
  } catch (err) {
14517
14546
  console.error("BugBear: Report submission error", err);
14518
14547
  setError(err instanceof Error ? err.message : "An unexpected error occurred. Please try again.");
14519
14548
  setSubmitting(false);
14549
+ submittingRef.current = false;
14520
14550
  }
14521
14551
  };
14522
14552
  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 }, [
@@ -15046,9 +15076,9 @@ function BugBearButton({
15046
15076
  return { x, y };
15047
15077
  };
15048
15078
  const initialPos = getInitialPosition();
15049
- const pan = useRef2(new Animated.ValueXY(initialPos)).current;
15050
- const isDragging = useRef2(false);
15051
- const panResponder = useRef2(
15079
+ const pan = useRef3(new Animated.ValueXY(initialPos)).current;
15080
+ const isDragging = useRef3(false);
15081
+ const panResponder = useRef3(
15052
15082
  PanResponder.create({
15053
15083
  onStartShouldSetPanResponder: () => draggable,
15054
15084
  onMoveShouldSetPanResponder: (_, gs) => draggable && (Math.abs(gs.dx) > 5 || Math.abs(gs.dy) > 5),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/react-native",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "BugBear React Native components for mobile apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",