@bbearai/react-native 0.3.5 → 0.3.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/index.js CHANGED
@@ -11543,7 +11543,7 @@ var BugBearClient = class {
11543
11543
  console.error("BugBear: Failed to fetch assignments", error);
11544
11544
  return [];
11545
11545
  }
11546
- return (data || []).map((item) => ({
11546
+ const mapped = (data || []).map((item) => ({
11547
11547
  id: item.id,
11548
11548
  status: item.status,
11549
11549
  startedAt: item.started_at,
@@ -11576,6 +11576,12 @@ var BugBearClient = class {
11576
11576
  } : void 0
11577
11577
  }
11578
11578
  }));
11579
+ mapped.sort((a, b) => {
11580
+ if (a.isVerification && !b.isVerification) return -1;
11581
+ if (!a.isVerification && b.isVerification) return 1;
11582
+ return 0;
11583
+ });
11584
+ return mapped;
11579
11585
  } catch (err) {
11580
11586
  console.error("BugBear: Error fetching assignments", err);
11581
11587
  return [];
@@ -13340,7 +13346,13 @@ var import_react3 = __toESM(require("react"));
13340
13346
  var import_react_native3 = require("react-native");
13341
13347
  function HomeScreen({ nav }) {
13342
13348
  const { assignments, unreadCount, threads, refreshAssignments, refreshThreads, dashboardUrl } = useBugBear();
13343
- const pendingCount = assignments.filter((a) => a.status === "pending" || a.status === "in_progress").length;
13349
+ (0, import_react3.useEffect)(() => {
13350
+ refreshAssignments();
13351
+ refreshThreads();
13352
+ }, []);
13353
+ const pendingAssignments = assignments.filter((a) => a.status === "pending" || a.status === "in_progress");
13354
+ const pendingCount = pendingAssignments.length;
13355
+ const retestCount = pendingAssignments.filter((a) => a.isVerification).length;
13344
13356
  const completedCount = assignments.filter((a) => a.status === "passed" || a.status === "failed").length;
13345
13357
  const totalTests = assignments.length;
13346
13358
  return /* @__PURE__ */ import_react3.default.createElement(import_react_native3.View, null, pendingCount > 0 ? /* @__PURE__ */ import_react3.default.createElement(
@@ -13352,6 +13364,7 @@ function HomeScreen({ nav }) {
13352
13364
  },
13353
13365
  /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.heroCount }, pendingCount),
13354
13366
  /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.heroLabel }, "test", pendingCount !== 1 ? "s" : "", " waiting"),
13367
+ retestCount > 0 && /* @__PURE__ */ import_react3.default.createElement(import_react_native3.View, { style: styles.retestPill }, /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.retestPillText }, "\u{1F504} ", retestCount, " retest", retestCount !== 1 ? "s" : "")),
13355
13368
  /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.heroAction }, "Start Testing \u2192")
13356
13369
  ) : unreadCount > 0 ? /* @__PURE__ */ import_react3.default.createElement(
13357
13370
  import_react_native3.TouchableOpacity,
@@ -13455,6 +13468,22 @@ var styles = import_react_native3.StyleSheet.create({
13455
13468
  color: colors.blueText,
13456
13469
  marginTop: 2
13457
13470
  },
13471
+ retestPill: {
13472
+ flexDirection: "row",
13473
+ alignItems: "center",
13474
+ backgroundColor: "#422006",
13475
+ borderWidth: 1,
13476
+ borderColor: "#854d0e",
13477
+ borderRadius: 6,
13478
+ paddingHorizontal: 8,
13479
+ paddingVertical: 3,
13480
+ marginTop: 8
13481
+ },
13482
+ retestPillText: {
13483
+ fontSize: 12,
13484
+ fontWeight: "600",
13485
+ color: "#fbbf24"
13486
+ },
13458
13487
  heroAction: {
13459
13488
  fontSize: 14,
13460
13489
  fontWeight: "600",
@@ -13665,7 +13694,7 @@ function TestDetailScreen({ testId, nav }) {
13665
13694
  const steps = testCase.steps;
13666
13695
  const info = templateInfo[template] || templateInfo.steps;
13667
13696
  const rubricMode = testCase.track?.rubricMode || "pass_fail";
13668
- return /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.container }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.topRow }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.positionInfo }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.positionText }, "Test ", currentIndex + 1, " of ", allTests.length), displayedAssignment.status === "in_progress" && assignmentElapsedTime > 0 && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.timerBadge }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.timerText }, formatElapsedTime(assignmentElapsedTime)))), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.TouchableOpacity, { onPress: () => nav.push({ name: "TEST_LIST" }) }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.viewAllLink }, "View All \u2192"))), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.testTitle }, testCase.title), testCase.key && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.testKey }, testCase.key), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.TouchableOpacity, { onPress: () => setShowSteps(!showSteps), style: styles2.sectionHeader }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.sectionHeaderText }, showSteps ? "\u25BC" : "\u25B6", " ", info.icon, " ", template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`)), showSteps && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.templateContent }, template === "steps" && steps.map((step, idx) => /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { key: idx, style: styles2.step }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.stepNumber }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.stepNumberText }, step.stepNumber)), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.stepBody }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.stepAction }, step.action), step.expectedResult && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.stepExpected }, "\u2192 ", step.expectedResult)))), template === "checklist" && /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, steps.map((step, idx) => /* @__PURE__ */ import_react4.default.createElement(
13697
+ return /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.container }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.topRow }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.positionInfo }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.positionText }, "Test ", currentIndex + 1, " of ", allTests.length), displayedAssignment.status === "in_progress" && assignmentElapsedTime > 0 && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.timerBadge }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.timerText }, formatElapsedTime(assignmentElapsedTime)))), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.TouchableOpacity, { onPress: () => nav.push({ name: "TEST_LIST" }) }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.viewAllLink }, "View All \u2192"))), displayedAssignment.isVerification && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.retestBanner }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.retestIcon }, "\u{1F504}"), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.retestLabel }, "Retest"), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.retestSub }, "\u2014 Verify bug fix")), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.testTitle }, testCase.title), testCase.key && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.testKey }, testCase.key), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.TouchableOpacity, { onPress: () => setShowSteps(!showSteps), style: styles2.sectionHeader }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.sectionHeaderText }, showSteps ? "\u25BC" : "\u25B6", " ", info.icon, " ", template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`)), showSteps && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.templateContent }, template === "steps" && steps.map((step, idx) => /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { key: idx, style: styles2.step }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.stepNumber }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.stepNumberText }, step.stepNumber)), /* @__PURE__ */ import_react4.default.createElement(import_react_native4.View, { style: styles2.stepBody }, /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.stepAction }, step.action), step.expectedResult && /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.stepExpected }, "\u2192 ", step.expectedResult)))), template === "checklist" && /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, steps.map((step, idx) => /* @__PURE__ */ import_react4.default.createElement(
13669
13698
  import_react_native4.TouchableOpacity,
13670
13699
  {
13671
13700
  key: idx,
@@ -13749,6 +13778,10 @@ function TestDetailScreen({ testId, nav }) {
13749
13778
  }
13750
13779
  var styles2 = import_react_native4.StyleSheet.create({
13751
13780
  container: { paddingBottom: 16 },
13781
+ retestBanner: { flexDirection: "row", alignItems: "center", gap: 6, backgroundColor: "#422006", borderWidth: 1, borderColor: "#854d0e", borderRadius: 8, paddingVertical: 6, paddingHorizontal: 10, marginBottom: 10 },
13782
+ retestIcon: { fontSize: 14 },
13783
+ retestLabel: { fontSize: 13, fontWeight: "600", color: "#fbbf24" },
13784
+ retestSub: { fontSize: 12, color: "#d97706" },
13752
13785
  topRow: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 12 },
13753
13786
  positionInfo: { flexDirection: "row", alignItems: "center", gap: 8 },
13754
13787
  positionText: { fontSize: 13, color: colors.textMuted },
@@ -13864,6 +13897,8 @@ function TestListScreen({ nav }) {
13864
13897
  const statusOrder = { in_progress: 0, pending: 1, failed: 2, skipped: 3, passed: 4 };
13865
13898
  for (const folder of groups.values()) {
13866
13899
  folder.assignments.sort((a, b) => {
13900
+ if (a.isVerification && !b.isVerification) return -1;
13901
+ if (!a.isVerification && b.isVerification) return 1;
13867
13902
  const sd = (statusOrder[a.status] ?? 5) - (statusOrder[b.status] ?? 5);
13868
13903
  if (sd !== 0) return sd;
13869
13904
  return (priorityOrder[a.testCase.priority] ?? 4) - (priorityOrder[b.testCase.priority] ?? 4);
@@ -13905,7 +13940,7 @@ function TestListScreen({ nav }) {
13905
13940
  onPress: () => nav.push({ name: "TEST_DETAIL", testId: assignment.id })
13906
13941
  },
13907
13942
  /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testBadge }, badge.icon),
13908
- /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.testInfo }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testTitle, numberOfLines: 1 }, assignment.testCase.title), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testMeta }, assignment.testCase.key, " \xB7 ", assignment.testCase.priority))
13943
+ /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.testInfo }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testTitle, numberOfLines: 1 }, assignment.testCase.title), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.testMetaRow }, assignment.isVerification && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.retestTag }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.retestTagText }, "Retest")), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testMeta }, assignment.testCase.key, " \xB7 ", assignment.testCase.priority)))
13909
13944
  );
13910
13945
  }));
13911
13946
  }), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.TouchableOpacity, { style: styles3.refreshBtn, onPress: refreshAssignments }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.refreshText }, "\u21BB Refresh")));
@@ -13928,6 +13963,9 @@ var styles3 = import_react_native5.StyleSheet.create({
13928
13963
  testBadge: { fontSize: 16, marginRight: 10, width: 20 },
13929
13964
  testInfo: { flex: 1 },
13930
13965
  testTitle: { fontSize: 14, color: colors.textPrimary, marginBottom: 2 },
13966
+ testMetaRow: { flexDirection: "row", alignItems: "center", gap: 6 },
13967
+ retestTag: { backgroundColor: "#422006", borderWidth: 1, borderColor: "#854d0e", borderRadius: 4, paddingHorizontal: 5, paddingVertical: 1 },
13968
+ retestTagText: { fontSize: 10, fontWeight: "600", color: "#fbbf24" },
13931
13969
  testMeta: { fontSize: 11, color: colors.textDim },
13932
13970
  refreshBtn: { alignItems: "center", paddingVertical: 12 },
13933
13971
  refreshText: { fontSize: 13, color: colors.blue }
package/dist/index.mjs CHANGED
@@ -11512,7 +11512,7 @@ var BugBearClient = class {
11512
11512
  console.error("BugBear: Failed to fetch assignments", error);
11513
11513
  return [];
11514
11514
  }
11515
- return (data || []).map((item) => ({
11515
+ const mapped = (data || []).map((item) => ({
11516
11516
  id: item.id,
11517
11517
  status: item.status,
11518
11518
  startedAt: item.started_at,
@@ -11545,6 +11545,12 @@ var BugBearClient = class {
11545
11545
  } : void 0
11546
11546
  }
11547
11547
  }));
11548
+ mapped.sort((a, b) => {
11549
+ if (a.isVerification && !b.isVerification) return -1;
11550
+ if (!a.isVerification && b.isVerification) return 1;
11551
+ return 0;
11552
+ });
11553
+ return mapped;
11548
11554
  } catch (err) {
11549
11555
  console.error("BugBear: Error fetching assignments", err);
11550
11556
  return [];
@@ -13319,11 +13325,17 @@ var templateInfo = {
13319
13325
  };
13320
13326
 
13321
13327
  // src/widget/screens/HomeScreen.tsx
13322
- import React2 from "react";
13328
+ import React2, { useEffect as useEffect2 } from "react";
13323
13329
  import { View, Text, TouchableOpacity, StyleSheet as StyleSheet2, Linking } from "react-native";
13324
13330
  function HomeScreen({ nav }) {
13325
13331
  const { assignments, unreadCount, threads, refreshAssignments, refreshThreads, dashboardUrl } = useBugBear();
13326
- const pendingCount = assignments.filter((a) => a.status === "pending" || a.status === "in_progress").length;
13332
+ useEffect2(() => {
13333
+ refreshAssignments();
13334
+ refreshThreads();
13335
+ }, []);
13336
+ const pendingAssignments = assignments.filter((a) => a.status === "pending" || a.status === "in_progress");
13337
+ const pendingCount = pendingAssignments.length;
13338
+ const retestCount = pendingAssignments.filter((a) => a.isVerification).length;
13327
13339
  const completedCount = assignments.filter((a) => a.status === "passed" || a.status === "failed").length;
13328
13340
  const totalTests = assignments.length;
13329
13341
  return /* @__PURE__ */ React2.createElement(View, null, pendingCount > 0 ? /* @__PURE__ */ React2.createElement(
@@ -13335,6 +13347,7 @@ function HomeScreen({ nav }) {
13335
13347
  },
13336
13348
  /* @__PURE__ */ React2.createElement(Text, { style: styles.heroCount }, pendingCount),
13337
13349
  /* @__PURE__ */ React2.createElement(Text, { style: styles.heroLabel }, "test", pendingCount !== 1 ? "s" : "", " waiting"),
13350
+ retestCount > 0 && /* @__PURE__ */ React2.createElement(View, { style: styles.retestPill }, /* @__PURE__ */ React2.createElement(Text, { style: styles.retestPillText }, "\u{1F504} ", retestCount, " retest", retestCount !== 1 ? "s" : "")),
13338
13351
  /* @__PURE__ */ React2.createElement(Text, { style: styles.heroAction }, "Start Testing \u2192")
13339
13352
  ) : unreadCount > 0 ? /* @__PURE__ */ React2.createElement(
13340
13353
  TouchableOpacity,
@@ -13438,6 +13451,22 @@ var styles = StyleSheet2.create({
13438
13451
  color: colors.blueText,
13439
13452
  marginTop: 2
13440
13453
  },
13454
+ retestPill: {
13455
+ flexDirection: "row",
13456
+ alignItems: "center",
13457
+ backgroundColor: "#422006",
13458
+ borderWidth: 1,
13459
+ borderColor: "#854d0e",
13460
+ borderRadius: 6,
13461
+ paddingHorizontal: 8,
13462
+ paddingVertical: 3,
13463
+ marginTop: 8
13464
+ },
13465
+ retestPillText: {
13466
+ fontSize: 12,
13467
+ fontWeight: "600",
13468
+ color: "#fbbf24"
13469
+ },
13441
13470
  heroAction: {
13442
13471
  fontSize: 14,
13443
13472
  fontWeight: "600",
@@ -13566,7 +13595,7 @@ var styles = StyleSheet2.create({
13566
13595
  });
13567
13596
 
13568
13597
  // src/widget/screens/TestDetailScreen.tsx
13569
- import React3, { useState as useState2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
13598
+ import React3, { useState as useState2, useEffect as useEffect3, useCallback as useCallback2 } from "react";
13570
13599
  import { View as View2, Text as Text2, TouchableOpacity as TouchableOpacity2, StyleSheet as StyleSheet3, Modal, TextInput } from "react-native";
13571
13600
  function TestDetailScreen({ testId, nav }) {
13572
13601
  const { client, assignments, currentAssignment, refreshAssignments, getDeviceInfo, onNavigate } = useBugBear();
@@ -13579,12 +13608,12 @@ function TestDetailScreen({ testId, nav }) {
13579
13608
  const [selectedSkipReason, setSelectedSkipReason] = useState2(null);
13580
13609
  const [skipNotes, setSkipNotes] = useState2("");
13581
13610
  const [skipping, setSkipping] = useState2(false);
13582
- useEffect2(() => {
13611
+ useEffect3(() => {
13583
13612
  setCriteriaResults({});
13584
13613
  setShowSteps(true);
13585
13614
  setShowDetails(false);
13586
13615
  }, [displayedAssignment?.id]);
13587
- useEffect2(() => {
13616
+ useEffect3(() => {
13588
13617
  const active = displayedAssignment?.status === "in_progress" ? displayedAssignment : null;
13589
13618
  if (!active?.startedAt) {
13590
13619
  setAssignmentElapsedTime(0);
@@ -13648,7 +13677,7 @@ function TestDetailScreen({ testId, nav }) {
13648
13677
  const steps = testCase.steps;
13649
13678
  const info = templateInfo[template] || templateInfo.steps;
13650
13679
  const rubricMode = testCase.track?.rubricMode || "pass_fail";
13651
- return /* @__PURE__ */ React3.createElement(View2, { style: styles2.container }, /* @__PURE__ */ React3.createElement(View2, { style: styles2.topRow }, /* @__PURE__ */ React3.createElement(View2, { style: styles2.positionInfo }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.positionText }, "Test ", currentIndex + 1, " of ", allTests.length), displayedAssignment.status === "in_progress" && assignmentElapsedTime > 0 && /* @__PURE__ */ React3.createElement(View2, { style: styles2.timerBadge }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.timerText }, formatElapsedTime(assignmentElapsedTime)))), /* @__PURE__ */ React3.createElement(TouchableOpacity2, { onPress: () => nav.push({ name: "TEST_LIST" }) }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.viewAllLink }, "View All \u2192"))), /* @__PURE__ */ React3.createElement(Text2, { style: styles2.testTitle }, testCase.title), testCase.key && /* @__PURE__ */ React3.createElement(Text2, { style: styles2.testKey }, testCase.key), /* @__PURE__ */ React3.createElement(TouchableOpacity2, { onPress: () => setShowSteps(!showSteps), style: styles2.sectionHeader }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.sectionHeaderText }, showSteps ? "\u25BC" : "\u25B6", " ", info.icon, " ", template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`)), showSteps && /* @__PURE__ */ React3.createElement(View2, { style: styles2.templateContent }, template === "steps" && steps.map((step, idx) => /* @__PURE__ */ React3.createElement(View2, { key: idx, style: styles2.step }, /* @__PURE__ */ React3.createElement(View2, { style: styles2.stepNumber }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.stepNumberText }, step.stepNumber)), /* @__PURE__ */ React3.createElement(View2, { style: styles2.stepBody }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.stepAction }, step.action), step.expectedResult && /* @__PURE__ */ React3.createElement(Text2, { style: styles2.stepExpected }, "\u2192 ", step.expectedResult)))), template === "checklist" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, steps.map((step, idx) => /* @__PURE__ */ React3.createElement(
13680
+ return /* @__PURE__ */ React3.createElement(View2, { style: styles2.container }, /* @__PURE__ */ React3.createElement(View2, { style: styles2.topRow }, /* @__PURE__ */ React3.createElement(View2, { style: styles2.positionInfo }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.positionText }, "Test ", currentIndex + 1, " of ", allTests.length), displayedAssignment.status === "in_progress" && assignmentElapsedTime > 0 && /* @__PURE__ */ React3.createElement(View2, { style: styles2.timerBadge }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.timerText }, formatElapsedTime(assignmentElapsedTime)))), /* @__PURE__ */ React3.createElement(TouchableOpacity2, { onPress: () => nav.push({ name: "TEST_LIST" }) }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.viewAllLink }, "View All \u2192"))), displayedAssignment.isVerification && /* @__PURE__ */ React3.createElement(View2, { style: styles2.retestBanner }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.retestIcon }, "\u{1F504}"), /* @__PURE__ */ React3.createElement(Text2, { style: styles2.retestLabel }, "Retest"), /* @__PURE__ */ React3.createElement(Text2, { style: styles2.retestSub }, "\u2014 Verify bug fix")), /* @__PURE__ */ React3.createElement(Text2, { style: styles2.testTitle }, testCase.title), testCase.key && /* @__PURE__ */ React3.createElement(Text2, { style: styles2.testKey }, testCase.key), /* @__PURE__ */ React3.createElement(TouchableOpacity2, { onPress: () => setShowSteps(!showSteps), style: styles2.sectionHeader }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.sectionHeaderText }, showSteps ? "\u25BC" : "\u25B6", " ", info.icon, " ", template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`)), showSteps && /* @__PURE__ */ React3.createElement(View2, { style: styles2.templateContent }, template === "steps" && steps.map((step, idx) => /* @__PURE__ */ React3.createElement(View2, { key: idx, style: styles2.step }, /* @__PURE__ */ React3.createElement(View2, { style: styles2.stepNumber }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.stepNumberText }, step.stepNumber)), /* @__PURE__ */ React3.createElement(View2, { style: styles2.stepBody }, /* @__PURE__ */ React3.createElement(Text2, { style: styles2.stepAction }, step.action), step.expectedResult && /* @__PURE__ */ React3.createElement(Text2, { style: styles2.stepExpected }, "\u2192 ", step.expectedResult)))), template === "checklist" && /* @__PURE__ */ React3.createElement(React3.Fragment, null, steps.map((step, idx) => /* @__PURE__ */ React3.createElement(
13652
13681
  TouchableOpacity2,
13653
13682
  {
13654
13683
  key: idx,
@@ -13732,6 +13761,10 @@ function TestDetailScreen({ testId, nav }) {
13732
13761
  }
13733
13762
  var styles2 = StyleSheet3.create({
13734
13763
  container: { paddingBottom: 16 },
13764
+ retestBanner: { flexDirection: "row", alignItems: "center", gap: 6, backgroundColor: "#422006", borderWidth: 1, borderColor: "#854d0e", borderRadius: 8, paddingVertical: 6, paddingHorizontal: 10, marginBottom: 10 },
13765
+ retestIcon: { fontSize: 14 },
13766
+ retestLabel: { fontSize: 13, fontWeight: "600", color: "#fbbf24" },
13767
+ retestSub: { fontSize: 12, color: "#d97706" },
13735
13768
  topRow: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 12 },
13736
13769
  positionInfo: { flexDirection: "row", alignItems: "center", gap: 8 },
13737
13770
  positionText: { fontSize: 13, color: colors.textMuted },
@@ -13847,6 +13880,8 @@ function TestListScreen({ nav }) {
13847
13880
  const statusOrder = { in_progress: 0, pending: 1, failed: 2, skipped: 3, passed: 4 };
13848
13881
  for (const folder of groups.values()) {
13849
13882
  folder.assignments.sort((a, b) => {
13883
+ if (a.isVerification && !b.isVerification) return -1;
13884
+ if (!a.isVerification && b.isVerification) return 1;
13850
13885
  const sd = (statusOrder[a.status] ?? 5) - (statusOrder[b.status] ?? 5);
13851
13886
  if (sd !== 0) return sd;
13852
13887
  return (priorityOrder[a.testCase.priority] ?? 4) - (priorityOrder[b.testCase.priority] ?? 4);
@@ -13888,7 +13923,7 @@ function TestListScreen({ nav }) {
13888
13923
  onPress: () => nav.push({ name: "TEST_DETAIL", testId: assignment.id })
13889
13924
  },
13890
13925
  /* @__PURE__ */ React4.createElement(Text3, { style: styles3.testBadge }, badge.icon),
13891
- /* @__PURE__ */ React4.createElement(View3, { style: styles3.testInfo }, /* @__PURE__ */ React4.createElement(Text3, { style: styles3.testTitle, numberOfLines: 1 }, assignment.testCase.title), /* @__PURE__ */ React4.createElement(Text3, { style: styles3.testMeta }, assignment.testCase.key, " \xB7 ", assignment.testCase.priority))
13926
+ /* @__PURE__ */ React4.createElement(View3, { style: styles3.testInfo }, /* @__PURE__ */ React4.createElement(Text3, { style: styles3.testTitle, numberOfLines: 1 }, assignment.testCase.title), /* @__PURE__ */ React4.createElement(View3, { style: styles3.testMetaRow }, assignment.isVerification && /* @__PURE__ */ React4.createElement(View3, { style: styles3.retestTag }, /* @__PURE__ */ React4.createElement(Text3, { style: styles3.retestTagText }, "Retest")), /* @__PURE__ */ React4.createElement(Text3, { style: styles3.testMeta }, assignment.testCase.key, " \xB7 ", assignment.testCase.priority)))
13892
13927
  );
13893
13928
  }));
13894
13929
  }), /* @__PURE__ */ React4.createElement(TouchableOpacity3, { style: styles3.refreshBtn, onPress: refreshAssignments }, /* @__PURE__ */ React4.createElement(Text3, { style: styles3.refreshText }, "\u21BB Refresh")));
@@ -13911,6 +13946,9 @@ var styles3 = StyleSheet4.create({
13911
13946
  testBadge: { fontSize: 16, marginRight: 10, width: 20 },
13912
13947
  testInfo: { flex: 1 },
13913
13948
  testTitle: { fontSize: 14, color: colors.textPrimary, marginBottom: 2 },
13949
+ testMetaRow: { flexDirection: "row", alignItems: "center", gap: 6 },
13950
+ retestTag: { backgroundColor: "#422006", borderWidth: 1, borderColor: "#854d0e", borderRadius: 4, paddingHorizontal: 5, paddingVertical: 1 },
13951
+ retestTagText: { fontSize: 10, fontWeight: "600", color: "#fbbf24" },
13914
13952
  testMeta: { fontSize: 11, color: colors.textDim },
13915
13953
  refreshBtn: { alignItems: "center", paddingVertical: 12 },
13916
13954
  refreshText: { fontSize: 13, color: colors.blue }
@@ -14337,10 +14375,10 @@ var styles7 = StyleSheet8.create({
14337
14375
  });
14338
14376
 
14339
14377
  // src/widget/screens/ReportSuccessScreen.tsx
14340
- import React9, { useEffect as useEffect3 } from "react";
14378
+ import React9, { useEffect as useEffect4 } from "react";
14341
14379
  import { View as View8, Text as Text8, StyleSheet as StyleSheet9 } from "react-native";
14342
14380
  function ReportSuccessScreen({ nav }) {
14343
- useEffect3(() => {
14381
+ useEffect4(() => {
14344
14382
  const timer = setTimeout(() => nav.reset(), 2e3);
14345
14383
  return () => clearTimeout(timer);
14346
14384
  }, [nav]);
@@ -14399,7 +14437,7 @@ var styles9 = StyleSheet10.create({
14399
14437
  });
14400
14438
 
14401
14439
  // src/widget/screens/ThreadDetailScreen.tsx
14402
- import React11, { useState as useState7, useEffect as useEffect4 } from "react";
14440
+ import React11, { useState as useState7, useEffect as useEffect5 } from "react";
14403
14441
  import { View as View10, Text as Text10, TouchableOpacity as TouchableOpacity9, TextInput as TextInput4, StyleSheet as StyleSheet11, Image as Image2 } from "react-native";
14404
14442
  function ThreadDetailScreen({ thread, nav }) {
14405
14443
  const { getThreadMessages, sendMessage, markAsRead, uploadImage } = useBugBear();
@@ -14409,7 +14447,7 @@ function ThreadDetailScreen({ thread, nav }) {
14409
14447
  const [sending, setSending] = useState7(false);
14410
14448
  const [sendError, setSendError] = useState7(false);
14411
14449
  const replyImages = useImageAttachments(uploadImage, 3, "discussion-attachments");
14412
- useEffect4(() => {
14450
+ useEffect5(() => {
14413
14451
  (async () => {
14414
14452
  setLoading(true);
14415
14453
  const msgs = await getThreadMessages(thread.id);
@@ -14578,7 +14616,7 @@ var styles11 = StyleSheet12.create({
14578
14616
  });
14579
14617
 
14580
14618
  // src/widget/screens/ProfileScreen.tsx
14581
- import React13, { useState as useState9, useEffect as useEffect5 } from "react";
14619
+ import React13, { useState as useState9, useEffect as useEffect6 } from "react";
14582
14620
  import { View as View12, Text as Text12, TouchableOpacity as TouchableOpacity11, TextInput as TextInput6, StyleSheet as StyleSheet13 } from "react-native";
14583
14621
  function ProfileScreen({ nav }) {
14584
14622
  const { testerInfo, assignments, updateTesterProfile, refreshTesterInfo } = useBugBear();
@@ -14591,7 +14629,7 @@ function ProfileScreen({ nav }) {
14591
14629
  const [saved, setSaved] = useState9(false);
14592
14630
  const [showDetails, setShowDetails] = useState9(false);
14593
14631
  const completedCount = assignments.filter((a) => a.status === "passed" || a.status === "failed").length;
14594
- useEffect5(() => {
14632
+ useEffect6(() => {
14595
14633
  if (testerInfo) {
14596
14634
  setName(testerInfo.name);
14597
14635
  setAdditionalEmails(testerInfo.additionalEmails || []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/react-native",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "BugBear React Native components for mobile apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",