@bbearai/react-native 0.6.1 → 0.6.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/dist/index.js CHANGED
@@ -12007,8 +12007,8 @@ var BugBearClient = class {
12007
12007
  return { success: false, error: rateLimit.error };
12008
12008
  }
12009
12009
  if (!userInfo) {
12010
- console.error("BugBear: No user info available, cannot submit report");
12011
- return { success: false, error: "User not authenticated" };
12010
+ console.error("BugBear: No user info available, cannot submit report. Ensure your BugBear config provides a getCurrentUser() callback that returns { id, email }.");
12011
+ return { success: false, error: "Unable to identify user. Check that your app passes a getCurrentUser callback to BugBear config." };
12012
12012
  }
12013
12013
  const testerInfo = await this.getTesterInfo();
12014
12014
  fullReport = {
@@ -12114,10 +12114,9 @@ var BugBearClient = class {
12114
12114
  platforms
12115
12115
  )
12116
12116
  `;
12117
- const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1e3).toISOString();
12118
12117
  const [pendingResult, completedResult] = await Promise.all([
12119
12118
  this.supabase.from("test_assignments").select(selectFields).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true }).range(from, to),
12120
- this.supabase.from("test_assignments").select(selectFields).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["passed", "failed", "skipped", "blocked"]).gte("completed_at", twentyFourHoursAgo).order("completed_at", { ascending: false }).limit(50)
12119
+ this.supabase.from("test_assignments").select(selectFields).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["passed", "failed", "skipped", "blocked"]).order("completed_at", { ascending: false }).limit(100)
12121
12120
  ]);
12122
12121
  if (pendingResult.error) {
12123
12122
  console.error("BugBear: Failed to fetch assignments", formatPgError(pendingResult.error));
@@ -14630,7 +14629,7 @@ function TestDetailScreen({ testId, nav }) {
14630
14629
  }
14631
14630
  },
14632
14631
  /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.navigateText }, "\u{1F9ED} Go to test location")
14633
- ), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.TouchableOpacity, { onPress: () => setShowDetails(!showDetails), style: styles2.detailsToggle }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.detailsToggleText }, showDetails ? "\u25BC" : "\u25B6", " Details")), showDetails && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles2.detailsSection }, testCase.key && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.detailMeta }, testCase.key, " \xB7 ", testCase.priority, " \xB7 ", info.name), testCase.description && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.detailDesc }, testCase.description), testCase.group && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles2.folderProgress }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.folderName }, "\u{1F4C1} ", testCase.group.name))), displayedAssignment.status === "passed" || displayedAssignment.status === "failed" || displayedAssignment.status === "skipped" || displayedAssignment.status === "blocked" ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: [
14632
+ ), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.TouchableOpacity, { onPress: () => setShowDetails(!showDetails), style: styles2.detailsToggle }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.detailsToggleText }, showDetails ? "\u25BC" : "\u25B6", " Details")), showDetails && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles2.detailsSection }, testCase.key && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.detailMeta }, testCase.key, " \xB7 ", testCase.priority, " \xB7 ", info.name), testCase.track && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.detailMeta }, testCase.track.icon, " ", testCase.track.name), testCase.description && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.detailDesc }, testCase.description), testCase.group && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles2.folderProgress }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles2.folderName }, "\u{1F4C1} ", testCase.group.name))), displayedAssignment.status === "passed" || displayedAssignment.status === "failed" || displayedAssignment.status === "skipped" || displayedAssignment.status === "blocked" ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: [
14634
14633
  styles2.completedBanner,
14635
14634
  displayedAssignment.status === "passed" && styles2.completedBannerPass,
14636
14635
  displayedAssignment.status === "failed" && styles2.completedBannerFail
@@ -14830,13 +14829,6 @@ function TestListScreen({ nav }) {
14830
14829
  }
14831
14830
  return Array.from(trackMap.values());
14832
14831
  }, [assignments]);
14833
- const availablePlatforms = (0, import_react6.useMemo)(() => {
14834
- const set = /* @__PURE__ */ new Set();
14835
- for (const a of assignments) {
14836
- if (a.testCase.platforms) a.testCase.platforms.forEach((p) => set.add(p));
14837
- }
14838
- return Array.from(set).sort();
14839
- }, [assignments]);
14840
14832
  const selectedRole = availableRoles.find((r) => r.id === roleFilter);
14841
14833
  const groupedAssignments = (0, import_react6.useMemo)(() => {
14842
14834
  const groups = /* @__PURE__ */ new Map();
@@ -14934,28 +14926,30 @@ function TestListScreen({ nav }) {
14934
14926
  placeholderTextColor: colors.textMuted,
14935
14927
  style: styles3.searchInput
14936
14928
  }
14937
- )), availablePlatforms.length >= 2 && /* @__PURE__ */ import_react6.default.createElement(import_react_native6.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles3.platformBar }, /* @__PURE__ */ import_react6.default.createElement(
14929
+ )), /* @__PURE__ */ import_react6.default.createElement(import_react_native6.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles3.platformBar }, /* @__PURE__ */ import_react6.default.createElement(
14938
14930
  import_react_native6.TouchableOpacity,
14939
14931
  {
14940
14932
  style: [styles3.platformBtn, !platformFilter && styles3.platformBtnActive],
14941
14933
  onPress: () => setPlatformFilter(null)
14942
14934
  },
14943
- /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: [styles3.platformBtnText, !platformFilter && styles3.platformBtnTextActive] }, "All Platforms")
14944
- ), availablePlatforms.map((p) => {
14945
- const isActive = platformFilter === p;
14946
- const label = p === "ios" ? "iOS" : p === "android" ? "Android" : p === "web" ? "Web" : p;
14947
- const icon = p === "ios" ? "\u{1F4F1}" : p === "android" ? "\u{1F916}" : p === "web" ? "\u{1F310}" : "\u{1F4CB}";
14935
+ /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: [styles3.platformBtnText, !platformFilter && styles3.platformBtnTextActive] }, "All")
14936
+ ), [
14937
+ { key: "web", label: "Web", icon: "\u{1F310}" },
14938
+ { key: "ios", label: "iOS", icon: "\u{1F4F1}" },
14939
+ { key: "android", label: "Android", icon: "\u{1F916}" }
14940
+ ].map((p) => {
14941
+ const isActive = platformFilter === p.key;
14948
14942
  return /* @__PURE__ */ import_react6.default.createElement(
14949
14943
  import_react_native6.TouchableOpacity,
14950
14944
  {
14951
- key: p,
14945
+ key: p.key,
14952
14946
  style: [
14953
14947
  styles3.platformBtn,
14954
14948
  isActive && { backgroundColor: colors.blue + "20", borderColor: colors.blue + "60", borderWidth: 1 }
14955
14949
  ],
14956
- onPress: () => setPlatformFilter(isActive ? null : p)
14950
+ onPress: () => setPlatformFilter(isActive ? null : p.key)
14957
14951
  },
14958
- /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: [styles3.platformBtnText, isActive && { color: colors.blue, fontWeight: "600" }] }, icon, " ", label)
14952
+ /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: [styles3.platformBtnText, isActive && { color: colors.blue, fontWeight: "600" }] }, p.icon, " ", p.label)
14959
14953
  );
14960
14954
  })), /* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: styles3.trackSortRow }, availableTracks.length >= 2 && /* @__PURE__ */ import_react6.default.createElement(import_react_native6.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: { flex: 1 } }, /* @__PURE__ */ import_react6.default.createElement(
14961
14955
  import_react_native6.TouchableOpacity,
@@ -15251,7 +15245,9 @@ var styles4 = import_react_native7.StyleSheet.create({
15251
15245
 
15252
15246
  // src/widget/ImagePickerButtons.tsx
15253
15247
  function ImagePickerButtons({ images, maxImages, onPickGallery, onPickCamera, onRemove, label }) {
15254
- if (!IMAGE_PICKER_AVAILABLE) return null;
15248
+ if (!IMAGE_PICKER_AVAILABLE) {
15249
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: styles5.section }, label && /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: styles5.label }, label), /* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: styles5.unavailableRow }, /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: styles5.unavailableText }, "Install react-native-image-picker to enable photo attachments")));
15250
+ }
15255
15251
  return /* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: styles5.section }, label && /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: styles5.label }, label), /* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: styles5.buttonRow }, /* @__PURE__ */ import_react9.default.createElement(
15256
15252
  import_react_native8.TouchableOpacity,
15257
15253
  {
@@ -15306,6 +15302,18 @@ var styles5 = import_react_native8.StyleSheet.create({
15306
15302
  fontSize: 12,
15307
15303
  color: colors.textDim,
15308
15304
  marginLeft: 4
15305
+ },
15306
+ unavailableRow: {
15307
+ backgroundColor: colors.card,
15308
+ borderWidth: 1,
15309
+ borderColor: colors.border,
15310
+ borderRadius: 8,
15311
+ padding: 12
15312
+ },
15313
+ unavailableText: {
15314
+ fontSize: 12,
15315
+ color: colors.textDim,
15316
+ fontStyle: "italic"
15309
15317
  }
15310
15318
  });
15311
15319
 
package/dist/index.mjs CHANGED
@@ -11974,8 +11974,8 @@ var BugBearClient = class {
11974
11974
  return { success: false, error: rateLimit.error };
11975
11975
  }
11976
11976
  if (!userInfo) {
11977
- console.error("BugBear: No user info available, cannot submit report");
11978
- return { success: false, error: "User not authenticated" };
11977
+ console.error("BugBear: No user info available, cannot submit report. Ensure your BugBear config provides a getCurrentUser() callback that returns { id, email }.");
11978
+ return { success: false, error: "Unable to identify user. Check that your app passes a getCurrentUser callback to BugBear config." };
11979
11979
  }
11980
11980
  const testerInfo = await this.getTesterInfo();
11981
11981
  fullReport = {
@@ -12081,10 +12081,9 @@ var BugBearClient = class {
12081
12081
  platforms
12082
12082
  )
12083
12083
  `;
12084
- const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1e3).toISOString();
12085
12084
  const [pendingResult, completedResult] = await Promise.all([
12086
12085
  this.supabase.from("test_assignments").select(selectFields).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true }).range(from, to),
12087
- this.supabase.from("test_assignments").select(selectFields).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["passed", "failed", "skipped", "blocked"]).gte("completed_at", twentyFourHoursAgo).order("completed_at", { ascending: false }).limit(50)
12086
+ this.supabase.from("test_assignments").select(selectFields).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["passed", "failed", "skipped", "blocked"]).order("completed_at", { ascending: false }).limit(100)
12088
12087
  ]);
12089
12088
  if (pendingResult.error) {
12090
12089
  console.error("BugBear: Failed to fetch assignments", formatPgError(pendingResult.error));
@@ -14612,7 +14611,7 @@ function TestDetailScreen({ testId, nav }) {
14612
14611
  }
14613
14612
  },
14614
14613
  /* @__PURE__ */ React4.createElement(Text2, { style: styles2.navigateText }, "\u{1F9ED} Go to test location")
14615
- ), /* @__PURE__ */ React4.createElement(TouchableOpacity2, { onPress: () => setShowDetails(!showDetails), style: styles2.detailsToggle }, /* @__PURE__ */ React4.createElement(Text2, { style: styles2.detailsToggleText }, showDetails ? "\u25BC" : "\u25B6", " Details")), showDetails && /* @__PURE__ */ React4.createElement(View3, { style: styles2.detailsSection }, testCase.key && /* @__PURE__ */ React4.createElement(Text2, { style: styles2.detailMeta }, testCase.key, " \xB7 ", testCase.priority, " \xB7 ", info.name), testCase.description && /* @__PURE__ */ React4.createElement(Text2, { style: styles2.detailDesc }, testCase.description), testCase.group && /* @__PURE__ */ React4.createElement(View3, { style: styles2.folderProgress }, /* @__PURE__ */ React4.createElement(Text2, { style: styles2.folderName }, "\u{1F4C1} ", testCase.group.name))), displayedAssignment.status === "passed" || displayedAssignment.status === "failed" || displayedAssignment.status === "skipped" || displayedAssignment.status === "blocked" ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(View3, { style: [
14614
+ ), /* @__PURE__ */ React4.createElement(TouchableOpacity2, { onPress: () => setShowDetails(!showDetails), style: styles2.detailsToggle }, /* @__PURE__ */ React4.createElement(Text2, { style: styles2.detailsToggleText }, showDetails ? "\u25BC" : "\u25B6", " Details")), showDetails && /* @__PURE__ */ React4.createElement(View3, { style: styles2.detailsSection }, testCase.key && /* @__PURE__ */ React4.createElement(Text2, { style: styles2.detailMeta }, testCase.key, " \xB7 ", testCase.priority, " \xB7 ", info.name), testCase.track && /* @__PURE__ */ React4.createElement(Text2, { style: styles2.detailMeta }, testCase.track.icon, " ", testCase.track.name), testCase.description && /* @__PURE__ */ React4.createElement(Text2, { style: styles2.detailDesc }, testCase.description), testCase.group && /* @__PURE__ */ React4.createElement(View3, { style: styles2.folderProgress }, /* @__PURE__ */ React4.createElement(Text2, { style: styles2.folderName }, "\u{1F4C1} ", testCase.group.name))), displayedAssignment.status === "passed" || displayedAssignment.status === "failed" || displayedAssignment.status === "skipped" || displayedAssignment.status === "blocked" ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(View3, { style: [
14616
14615
  styles2.completedBanner,
14617
14616
  displayedAssignment.status === "passed" && styles2.completedBannerPass,
14618
14617
  displayedAssignment.status === "failed" && styles2.completedBannerFail
@@ -14812,13 +14811,6 @@ function TestListScreen({ nav }) {
14812
14811
  }
14813
14812
  return Array.from(trackMap.values());
14814
14813
  }, [assignments]);
14815
- const availablePlatforms = useMemo2(() => {
14816
- const set = /* @__PURE__ */ new Set();
14817
- for (const a of assignments) {
14818
- if (a.testCase.platforms) a.testCase.platforms.forEach((p) => set.add(p));
14819
- }
14820
- return Array.from(set).sort();
14821
- }, [assignments]);
14822
14814
  const selectedRole = availableRoles.find((r) => r.id === roleFilter);
14823
14815
  const groupedAssignments = useMemo2(() => {
14824
14816
  const groups = /* @__PURE__ */ new Map();
@@ -14916,28 +14908,30 @@ function TestListScreen({ nav }) {
14916
14908
  placeholderTextColor: colors.textMuted,
14917
14909
  style: styles3.searchInput
14918
14910
  }
14919
- )), availablePlatforms.length >= 2 && /* @__PURE__ */ React5.createElement(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles3.platformBar }, /* @__PURE__ */ React5.createElement(
14911
+ )), /* @__PURE__ */ React5.createElement(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles3.platformBar }, /* @__PURE__ */ React5.createElement(
14920
14912
  TouchableOpacity3,
14921
14913
  {
14922
14914
  style: [styles3.platformBtn, !platformFilter && styles3.platformBtnActive],
14923
14915
  onPress: () => setPlatformFilter(null)
14924
14916
  },
14925
- /* @__PURE__ */ React5.createElement(Text3, { style: [styles3.platformBtnText, !platformFilter && styles3.platformBtnTextActive] }, "All Platforms")
14926
- ), availablePlatforms.map((p) => {
14927
- const isActive = platformFilter === p;
14928
- const label = p === "ios" ? "iOS" : p === "android" ? "Android" : p === "web" ? "Web" : p;
14929
- const icon = p === "ios" ? "\u{1F4F1}" : p === "android" ? "\u{1F916}" : p === "web" ? "\u{1F310}" : "\u{1F4CB}";
14917
+ /* @__PURE__ */ React5.createElement(Text3, { style: [styles3.platformBtnText, !platformFilter && styles3.platformBtnTextActive] }, "All")
14918
+ ), [
14919
+ { key: "web", label: "Web", icon: "\u{1F310}" },
14920
+ { key: "ios", label: "iOS", icon: "\u{1F4F1}" },
14921
+ { key: "android", label: "Android", icon: "\u{1F916}" }
14922
+ ].map((p) => {
14923
+ const isActive = platformFilter === p.key;
14930
14924
  return /* @__PURE__ */ React5.createElement(
14931
14925
  TouchableOpacity3,
14932
14926
  {
14933
- key: p,
14927
+ key: p.key,
14934
14928
  style: [
14935
14929
  styles3.platformBtn,
14936
14930
  isActive && { backgroundColor: colors.blue + "20", borderColor: colors.blue + "60", borderWidth: 1 }
14937
14931
  ],
14938
- onPress: () => setPlatformFilter(isActive ? null : p)
14932
+ onPress: () => setPlatformFilter(isActive ? null : p.key)
14939
14933
  },
14940
- /* @__PURE__ */ React5.createElement(Text3, { style: [styles3.platformBtnText, isActive && { color: colors.blue, fontWeight: "600" }] }, icon, " ", label)
14934
+ /* @__PURE__ */ React5.createElement(Text3, { style: [styles3.platformBtnText, isActive && { color: colors.blue, fontWeight: "600" }] }, p.icon, " ", p.label)
14941
14935
  );
14942
14936
  })), /* @__PURE__ */ React5.createElement(View4, { style: styles3.trackSortRow }, availableTracks.length >= 2 && /* @__PURE__ */ React5.createElement(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: { flex: 1 } }, /* @__PURE__ */ React5.createElement(
14943
14937
  TouchableOpacity3,
@@ -15233,7 +15227,9 @@ var styles4 = StyleSheet6.create({
15233
15227
 
15234
15228
  // src/widget/ImagePickerButtons.tsx
15235
15229
  function ImagePickerButtons({ images, maxImages, onPickGallery, onPickCamera, onRemove, label }) {
15236
- if (!IMAGE_PICKER_AVAILABLE) return null;
15230
+ if (!IMAGE_PICKER_AVAILABLE) {
15231
+ return /* @__PURE__ */ React7.createElement(View6, { style: styles5.section }, label && /* @__PURE__ */ React7.createElement(Text5, { style: styles5.label }, label), /* @__PURE__ */ React7.createElement(View6, { style: styles5.unavailableRow }, /* @__PURE__ */ React7.createElement(Text5, { style: styles5.unavailableText }, "Install react-native-image-picker to enable photo attachments")));
15232
+ }
15237
15233
  return /* @__PURE__ */ React7.createElement(View6, { style: styles5.section }, label && /* @__PURE__ */ React7.createElement(Text5, { style: styles5.label }, label), /* @__PURE__ */ React7.createElement(View6, { style: styles5.buttonRow }, /* @__PURE__ */ React7.createElement(
15238
15234
  TouchableOpacity5,
15239
15235
  {
@@ -15288,6 +15284,18 @@ var styles5 = StyleSheet7.create({
15288
15284
  fontSize: 12,
15289
15285
  color: colors.textDim,
15290
15286
  marginLeft: 4
15287
+ },
15288
+ unavailableRow: {
15289
+ backgroundColor: colors.card,
15290
+ borderWidth: 1,
15291
+ borderColor: colors.border,
15292
+ borderRadius: 8,
15293
+ padding: 12
15294
+ },
15295
+ unavailableText: {
15296
+ fontSize: 12,
15297
+ color: colors.textDim,
15298
+ fontStyle: "italic"
15291
15299
  }
15292
15300
  });
15293
15301
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/react-native",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "BugBear React Native components for mobile apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",