@bbearai/react-native 0.5.1 → 0.5.3

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
@@ -12247,6 +12247,72 @@ var BugBearClient = class {
12247
12247
  return null;
12248
12248
  }
12249
12249
  }
12250
+ /**
12251
+ * Get issue counts for the tester (Open, Done, Reopened)
12252
+ * Used by the widget HomeScreen cards
12253
+ */
12254
+ async getIssueCounts() {
12255
+ try {
12256
+ const testerInfo = await this.getTesterInfo();
12257
+ if (!testerInfo) return { open: 0, done: 0, reopened: 0 };
12258
+ const { data, error } = await this.supabase.rpc("get_tester_issue_counts", {
12259
+ p_project_id: this.config.projectId,
12260
+ p_tester_id: testerInfo.id
12261
+ });
12262
+ if (error) {
12263
+ console.error("BugBear: Failed to fetch issue counts", formatPgError(error));
12264
+ return { open: 0, done: 0, reopened: 0 };
12265
+ }
12266
+ return {
12267
+ open: data?.open ?? 0,
12268
+ done: data?.done ?? 0,
12269
+ reopened: data?.reopened ?? 0
12270
+ };
12271
+ } catch (err) {
12272
+ console.error("BugBear: Error fetching issue counts", err);
12273
+ return { open: 0, done: 0, reopened: 0 };
12274
+ }
12275
+ }
12276
+ /**
12277
+ * Get issues for the tester by category.
12278
+ * Returns enriched data: done issues include verification proof,
12279
+ * reopened issues include original bug context.
12280
+ */
12281
+ async getIssues(category) {
12282
+ try {
12283
+ const testerInfo = await this.getTesterInfo();
12284
+ if (!testerInfo) return [];
12285
+ const { data, error } = await this.supabase.rpc("get_tester_issues", {
12286
+ p_project_id: this.config.projectId,
12287
+ p_tester_id: testerInfo.id,
12288
+ p_category: category
12289
+ });
12290
+ if (error) {
12291
+ console.error("BugBear: Failed to fetch issues", formatPgError(error));
12292
+ return [];
12293
+ }
12294
+ return (data || []).map((row) => ({
12295
+ id: row.id,
12296
+ title: row.title || "Untitled",
12297
+ description: row.description,
12298
+ reportType: row.report_type,
12299
+ severity: row.severity || null,
12300
+ status: row.status,
12301
+ screenshotUrls: row.screenshot_urls || [],
12302
+ route: row.app_context?.currentRoute || void 0,
12303
+ reporterName: row.reporter_name || void 0,
12304
+ createdAt: row.created_at,
12305
+ updatedAt: row.updated_at,
12306
+ verifiedByName: row.verified_by_name || void 0,
12307
+ verifiedAt: row.verified_at || void 0,
12308
+ originalBugId: row.original_bug_id || void 0,
12309
+ originalBugTitle: row.original_bug_title || void 0
12310
+ }));
12311
+ } catch (err) {
12312
+ console.error("BugBear: Error fetching issues", err);
12313
+ return [];
12314
+ }
12315
+ }
12250
12316
  /**
12251
12317
  * Basic email format validation (defense in depth)
12252
12318
  */
@@ -13053,6 +13119,10 @@ var BugBearContext = (0, import_react.createContext)({
13053
13119
  updateTesterProfile: async () => ({ success: false }),
13054
13120
  refreshTesterInfo: async () => {
13055
13121
  },
13122
+ // Issue tracking
13123
+ issueCounts: { open: 0, done: 0, reopened: 0 },
13124
+ refreshIssueCounts: async () => {
13125
+ },
13056
13126
  dashboardUrl: void 0,
13057
13127
  onError: void 0
13058
13128
  });
@@ -13068,6 +13138,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
13068
13138
  const [isLoading, setIsLoading] = (0, import_react.useState)(true);
13069
13139
  const [threads, setThreads] = (0, import_react.useState)([]);
13070
13140
  const [unreadCount, setUnreadCount] = (0, import_react.useState)(0);
13141
+ const [issueCounts, setIssueCounts] = (0, import_react.useState)({ open: 0, done: 0, reopened: 0 });
13071
13142
  const [activeSession, setActiveSession] = (0, import_react.useState)(null);
13072
13143
  const [sessionFindings, setSessionFindings] = (0, import_react.useState)([]);
13073
13144
  const hasInitialized = (0, import_react.useRef)(false);
@@ -13174,6 +13245,11 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
13174
13245
  if (!client) return null;
13175
13246
  return client.uploadImageFromUri(uri, void 0, bucket);
13176
13247
  }, [client]);
13248
+ const refreshIssueCounts = (0, import_react.useCallback)(async () => {
13249
+ if (!client) return;
13250
+ const counts = await client.getIssueCounts();
13251
+ setIssueCounts(counts);
13252
+ }, [client]);
13177
13253
  const initializeBugBear = (0, import_react.useCallback)(async (bugBearClient) => {
13178
13254
  setIsLoading(true);
13179
13255
  try {
@@ -13186,16 +13262,18 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
13186
13262
  setTesterInfo(info);
13187
13263
  setIsTester(!!info);
13188
13264
  if (info && qaEnabled) {
13189
- const [newAssignments, newThreads, session] = await Promise.all([
13265
+ const [newAssignments, newThreads, session, counts] = await Promise.all([
13190
13266
  bugBearClient.getAssignedTests(),
13191
13267
  bugBearClient.getThreadsForTester(),
13192
- bugBearClient.getActiveSession()
13268
+ bugBearClient.getActiveSession(),
13269
+ bugBearClient.getIssueCounts()
13193
13270
  ]);
13194
13271
  setAssignments(newAssignments);
13195
13272
  setThreads(newThreads);
13196
13273
  const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
13197
13274
  setUnreadCount(totalUnread);
13198
13275
  setActiveSession(session);
13276
+ setIssueCounts(counts);
13199
13277
  if (session) {
13200
13278
  const findings = await bugBearClient.getSessionFindings(session.id);
13201
13279
  setSessionFindings(findings);
@@ -13263,6 +13341,9 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
13263
13341
  refreshTesterStatus,
13264
13342
  updateTesterProfile,
13265
13343
  refreshTesterInfo,
13344
+ // Issue tracking
13345
+ issueCounts,
13346
+ refreshIssueCounts,
13266
13347
  dashboardUrl: config.dashboardUrl,
13267
13348
  onError: config.onError
13268
13349
  }
@@ -13272,8 +13353,8 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
13272
13353
  }
13273
13354
 
13274
13355
  // src/BugBearButton.tsx
13275
- var import_react16 = __toESM(require("react"));
13276
- var import_react_native15 = require("react-native");
13356
+ var import_react18 = __toESM(require("react"));
13357
+ var import_react_native17 = require("react-native");
13277
13358
 
13278
13359
  // src/widget/logo.ts
13279
13360
  var BUGBEAR_LOGO_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAJhlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAABIAAAAAQAAAEgAAAABAASQBAACAAAAFAAAAISgAQADAAAAAQABAACgAgAEAAAAAQAAAGCgAwAEAAAAAQAAAGAAAAAAMjAyNjowMToyNCAxNjoyMTozOABbbVCuAAAACXBIWXMAAAsTAAALEwEAmpwYAAACo2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpJcHRjNHhtcEV4dD0iaHR0cDovL2lwdGMub3JnL3N0ZC9JcHRjNHhtcEV4dC8yMDA4LTAyLTI5LyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPElwdGM0eG1wRXh0OkRpZ2l0YWxTb3VyY2VUeXBlPmh0dHA6Ly9jdi5pcHRjLm9yZy9uZXdzY29kZXMvZGlnaXRhbHNvdXJjZXR5cGUvdHJhaW5lZEFsZ29yaXRobWljTWVkaWE8L0lwdGM0eG1wRXh0OkRpZ2l0YWxTb3VyY2VUeXBlPgogICAgICAgICA8SXB0YzR4bXBFeHQ6RGlnSW1hZ2VHVUlEPmZjNzJlN2Q2LTYyYTEtNDE1ZS04MjY5LWM2NjA4MjY0OWRiMDwvSXB0YzR4bXBFeHQ6RGlnSW1hZ2VHVUlEPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyNi0wMS0yNFQxNjoyMTozODwveG1wOkNyZWF0ZURhdGU+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+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";
@@ -13494,10 +13575,11 @@ var templateInfo = {
13494
13575
  var import_react3 = __toESM(require("react"));
13495
13576
  var import_react_native3 = require("react-native");
13496
13577
  function HomeScreen({ nav }) {
13497
- const { assignments, unreadCount, threads, refreshAssignments, refreshThreads, dashboardUrl } = useBugBear();
13578
+ const { assignments, unreadCount, threads, refreshAssignments, refreshThreads, issueCounts, refreshIssueCounts, dashboardUrl } = useBugBear();
13498
13579
  (0, import_react3.useEffect)(() => {
13499
13580
  refreshAssignments();
13500
13581
  refreshThreads();
13582
+ refreshIssueCounts();
13501
13583
  }, []);
13502
13584
  const pendingAssignments = assignments.filter((a) => a.status === "pending" || a.status === "in_progress");
13503
13585
  const pendingCount = pendingAssignments.length;
@@ -13563,6 +13645,33 @@ function HomeScreen({ nav }) {
13563
13645
  /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.actionIcon }, "\u{1F4AC}"),
13564
13646
  /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.actionLabel }, "Messages"),
13565
13647
  unreadCount > 0 && /* @__PURE__ */ import_react3.default.createElement(import_react_native3.View, { style: [styles.actionBadge, styles.actionBadgeMsg] }, /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.actionBadgeText }, unreadCount))
13648
+ )), /* @__PURE__ */ import_react3.default.createElement(import_react_native3.View, { style: styles.issueGrid }, /* @__PURE__ */ import_react3.default.createElement(
13649
+ import_react_native3.TouchableOpacity,
13650
+ {
13651
+ style: [styles.issueCard, styles.issueCardOpen],
13652
+ onPress: () => nav.push({ name: "ISSUE_LIST", category: "open" }),
13653
+ activeOpacity: 0.7
13654
+ },
13655
+ /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.issueCountOpen }, issueCounts.open),
13656
+ /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.issueLabel }, "Open")
13657
+ ), /* @__PURE__ */ import_react3.default.createElement(
13658
+ import_react_native3.TouchableOpacity,
13659
+ {
13660
+ style: [styles.issueCard, styles.issueCardDone],
13661
+ onPress: () => nav.push({ name: "ISSUE_LIST", category: "done" }),
13662
+ activeOpacity: 0.7
13663
+ },
13664
+ /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.issueCountDone }, issueCounts.done),
13665
+ /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.issueLabel }, "Done")
13666
+ ), /* @__PURE__ */ import_react3.default.createElement(
13667
+ import_react_native3.TouchableOpacity,
13668
+ {
13669
+ style: [styles.issueCard, styles.issueCardReopened],
13670
+ onPress: () => nav.push({ name: "ISSUE_LIST", category: "reopened" }),
13671
+ activeOpacity: 0.7
13672
+ },
13673
+ /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.issueCountReopened }, issueCounts.reopened),
13674
+ /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.issueLabel }, "Reopened")
13566
13675
  )), totalTests > 0 && /* @__PURE__ */ import_react3.default.createElement(import_react_native3.View, { style: styles.progressSection }, /* @__PURE__ */ import_react3.default.createElement(import_react_native3.View, { style: styles.progressBar }, /* @__PURE__ */ import_react3.default.createElement(import_react_native3.View, { style: [styles.progressFill, { width: `${Math.round(completedCount / totalTests * 100)}%` }] })), /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.progressText }, completedCount, "/", totalTests, " tests completed")), dashboardUrl && /* @__PURE__ */ import_react3.default.createElement(
13567
13676
  import_react_native3.TouchableOpacity,
13568
13677
  {
@@ -13580,6 +13689,7 @@ function HomeScreen({ nav }) {
13580
13689
  onPress: () => {
13581
13690
  refreshAssignments();
13582
13691
  refreshThreads();
13692
+ refreshIssueCounts();
13583
13693
  }
13584
13694
  },
13585
13695
  /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.refreshText }, "\u21BB Refresh")
@@ -13750,6 +13860,54 @@ var styles = import_react_native3.StyleSheet.create({
13750
13860
  color: colors.textMuted,
13751
13861
  marginLeft: 8
13752
13862
  },
13863
+ issueGrid: {
13864
+ flexDirection: "row",
13865
+ gap: 10,
13866
+ marginBottom: 20
13867
+ },
13868
+ issueCard: {
13869
+ flex: 1,
13870
+ backgroundColor: colors.card,
13871
+ borderWidth: 1,
13872
+ borderColor: colors.border,
13873
+ borderRadius: 10,
13874
+ paddingVertical: 12,
13875
+ paddingHorizontal: 8,
13876
+ alignItems: "center"
13877
+ },
13878
+ issueCardOpen: {
13879
+ borderTopWidth: 3,
13880
+ borderTopColor: "#f97316"
13881
+ },
13882
+ issueCardDone: {
13883
+ borderTopWidth: 3,
13884
+ borderTopColor: "#22c55e"
13885
+ },
13886
+ issueCardReopened: {
13887
+ borderTopWidth: 3,
13888
+ borderTopColor: "#ef4444"
13889
+ },
13890
+ issueCountOpen: {
13891
+ fontSize: 22,
13892
+ fontWeight: "700",
13893
+ color: "#f97316"
13894
+ },
13895
+ issueCountDone: {
13896
+ fontSize: 22,
13897
+ fontWeight: "700",
13898
+ color: "#22c55e"
13899
+ },
13900
+ issueCountReopened: {
13901
+ fontSize: 22,
13902
+ fontWeight: "700",
13903
+ color: "#ef4444"
13904
+ },
13905
+ issueLabel: {
13906
+ fontSize: 11,
13907
+ fontWeight: "600",
13908
+ color: colors.textSecondary,
13909
+ marginTop: 2
13910
+ },
13753
13911
  refreshButton: {
13754
13912
  alignItems: "center",
13755
13913
  paddingVertical: 8
@@ -14105,10 +14263,16 @@ function TestListScreen({ nav }) {
14105
14263
  const filterAssignment = (a) => {
14106
14264
  if (roleFilter && a.testCase.role?.id !== roleFilter) return false;
14107
14265
  if (filter === "pending") return a.status === "pending" || a.status === "in_progress";
14108
- if (filter === "completed") return a.status === "passed" || a.status === "failed";
14266
+ if (filter === "done") return a.status === "passed";
14267
+ if (filter === "reopened") return a.status === "failed";
14109
14268
  return true;
14110
14269
  };
14111
- return /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, null, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.filterBar }, ["all", "pending", "completed"].map((f) => /* @__PURE__ */ import_react5.default.createElement(import_react_native5.TouchableOpacity, { key: f, style: [styles3.filterBtn, filter === f && styles3.filterBtnActive], onPress: () => setFilter(f) }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: [styles3.filterBtnText, filter === f && styles3.filterBtnTextActive] }, f === "all" ? `All (${assignments.length})` : f === "pending" ? `To Do (${assignments.filter((a) => a.status === "pending" || a.status === "in_progress").length})` : `Done (${assignments.filter((a) => a.status === "passed" || a.status === "failed").length})`)))), availableRoles.length >= 2 && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.roleSection }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles3.roleBar }, /* @__PURE__ */ import_react5.default.createElement(
14270
+ return /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, null, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.filterBar }, [
14271
+ { key: "all", label: "All", count: assignments.length },
14272
+ { key: "pending", label: "To Do", count: assignments.filter((a) => a.status === "pending" || a.status === "in_progress").length },
14273
+ { key: "done", label: "Done", count: assignments.filter((a) => a.status === "passed").length },
14274
+ { key: "reopened", label: "Re Opened", count: assignments.filter((a) => a.status === "failed").length }
14275
+ ].map((f) => /* @__PURE__ */ import_react5.default.createElement(import_react_native5.TouchableOpacity, { key: f.key, style: [styles3.filterBtn, filter === f.key && styles3.filterBtnActive], onPress: () => setFilter(f.key) }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: [styles3.filterBtnText, filter === f.key && styles3.filterBtnTextActive] }, f.label, " (", f.count, ")")))), availableRoles.length >= 2 && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.roleSection }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles3.roleBar }, /* @__PURE__ */ import_react5.default.createElement(
14112
14276
  import_react_native5.TouchableOpacity,
14113
14277
  {
14114
14278
  style: [styles3.roleBtn, !roleFilter && styles3.roleBtnActive],
@@ -14146,7 +14310,19 @@ function TestListScreen({ nav }) {
14146
14310
  onPress: () => nav.push({ name: "TEST_DETAIL", testId: assignment.id })
14147
14311
  },
14148
14312
  /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testBadge }, badge.icon),
14149
- /* @__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.testKey, " \xB7 ", assignment.testCase.priority), assignment.testCase.role && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.roleBadgeRow }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testMeta }, " \xB7 "), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: [styles3.roleBadgeDot, { backgroundColor: assignment.testCase.role.color }] }), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: [styles3.testMeta, { color: assignment.testCase.role.color, fontWeight: "500" }] }, assignment.testCase.role.name))))
14313
+ /* @__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.testKey, " \xB7 ", assignment.testCase.priority), assignment.testCase.role && /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.roleBadgeRow }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testMeta }, " \xB7 "), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: [styles3.roleBadgeDot, { backgroundColor: assignment.testCase.role.color }] }), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: [styles3.testMeta, { color: assignment.testCase.role.color, fontWeight: "500" }] }, assignment.testCase.role.name)))),
14314
+ /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: [
14315
+ styles3.statusPill,
14316
+ {
14317
+ backgroundColor: assignment.status === "passed" ? "#14532d" : assignment.status === "failed" ? "#450a0a" : assignment.status === "in_progress" ? "#172554" : "#27272a",
14318
+ borderColor: assignment.status === "passed" ? "#166534" : assignment.status === "failed" ? "#7f1d1d" : assignment.status === "in_progress" ? "#1e3a5f" : "#3f3f46"
14319
+ }
14320
+ ] }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: [
14321
+ styles3.statusPillText,
14322
+ {
14323
+ color: assignment.status === "passed" ? "#4ade80" : assignment.status === "failed" ? "#f87171" : assignment.status === "in_progress" ? "#60a5fa" : "#d4d4d8"
14324
+ }
14325
+ ] }, badge.label))
14150
14326
  );
14151
14327
  }));
14152
14328
  }), /* @__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")));
@@ -14184,6 +14360,8 @@ var styles3 = import_react_native5.StyleSheet.create({
14184
14360
  retestTag: { backgroundColor: "#422006", borderWidth: 1, borderColor: "#854d0e", borderRadius: 4, paddingHorizontal: 5, paddingVertical: 1 },
14185
14361
  retestTagText: { fontSize: 10, fontWeight: "600", color: "#fbbf24" },
14186
14362
  testMeta: { fontSize: 11, color: colors.textDim },
14363
+ statusPill: { paddingHorizontal: 8, paddingVertical: 3, borderRadius: 6, borderWidth: 1, marginLeft: 8 },
14364
+ statusPillText: { fontSize: 10, fontWeight: "600" },
14187
14365
  refreshBtn: { alignItems: "center", paddingVertical: 12 },
14188
14366
  refreshText: { fontSize: 13, color: colors.blue }
14189
14367
  });
@@ -15068,9 +15246,311 @@ var styles12 = import_react_native14.StyleSheet.create({
15068
15246
  platformTextActive: { color: colors.blueLight }
15069
15247
  });
15070
15248
 
15249
+ // src/widget/screens/IssueListScreen.tsx
15250
+ var import_react16 = __toESM(require("react"));
15251
+ var import_react_native15 = require("react-native");
15252
+ var CATEGORY_CONFIG = {
15253
+ open: { label: "Open Issues", accent: "#f97316", emptyIcon: "\u2705", emptyText: "No open issues" },
15254
+ done: { label: "Done", accent: "#22c55e", emptyIcon: "\u{1F389}", emptyText: "No completed issues yet" },
15255
+ reopened: { label: "Reopened", accent: "#ef4444", emptyIcon: "\u{1F44D}", emptyText: "No reopened issues" }
15256
+ };
15257
+ var SEVERITY_COLORS = {
15258
+ critical: "#ef4444",
15259
+ high: "#f97316",
15260
+ medium: "#eab308",
15261
+ low: "#71717a"
15262
+ };
15263
+ function IssueListScreen({ nav, category }) {
15264
+ const { client } = useBugBear();
15265
+ const [issues, setIssues] = (0, import_react16.useState)([]);
15266
+ const [loading, setLoading] = (0, import_react16.useState)(true);
15267
+ const config = CATEGORY_CONFIG[category];
15268
+ (0, import_react16.useEffect)(() => {
15269
+ let cancelled = false;
15270
+ setLoading(true);
15271
+ (async () => {
15272
+ if (!client) return;
15273
+ const data = await client.getIssues(category);
15274
+ if (!cancelled) {
15275
+ setIssues(data);
15276
+ setLoading(false);
15277
+ }
15278
+ })();
15279
+ return () => {
15280
+ cancelled = true;
15281
+ };
15282
+ }, [client, category]);
15283
+ if (loading) {
15284
+ return /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.emptyContainer }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.ActivityIndicator, { size: "small", color: colors.textMuted }), /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.emptyText }, "Loading..."));
15285
+ }
15286
+ if (issues.length === 0) {
15287
+ return /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.emptyContainer }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.emptyIcon }, config.emptyIcon), /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.emptyText }, config.emptyText));
15288
+ }
15289
+ return /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, null, issues.map((issue) => /* @__PURE__ */ import_react16.default.createElement(
15290
+ import_react_native15.TouchableOpacity,
15291
+ {
15292
+ key: issue.id,
15293
+ style: styles13.issueCard,
15294
+ onPress: () => nav.push({ name: "ISSUE_DETAIL", issue }),
15295
+ activeOpacity: 0.7
15296
+ },
15297
+ /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.topRow }, issue.severity && /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: [styles13.severityDot, { backgroundColor: SEVERITY_COLORS[issue.severity] || colors.textDim }] }), /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.issueTitle, numberOfLines: 1 }, issue.title)),
15298
+ /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.bottomRow }, issue.route && /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.routeText, numberOfLines: 1 }, issue.route), /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.timeText }, formatRelativeTime(issue.updatedAt))),
15299
+ category === "done" && issue.verifiedByName && /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.verifiedBadge }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.verifiedBadgeText }, "\u2714", " Verified by ", issue.verifiedByName)),
15300
+ category === "reopened" && issue.originalBugTitle && /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.reopenedBadge }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.reopenedBadgeText, numberOfLines: 1 }, "\u{1F504}", " Retest of: ", issue.originalBugTitle))
15301
+ )));
15302
+ }
15303
+ var styles13 = import_react_native15.StyleSheet.create({
15304
+ emptyContainer: {
15305
+ alignItems: "center",
15306
+ paddingVertical: 40
15307
+ },
15308
+ emptyIcon: {
15309
+ fontSize: 36,
15310
+ marginBottom: 8
15311
+ },
15312
+ emptyText: {
15313
+ color: colors.textMuted,
15314
+ fontSize: 14,
15315
+ marginTop: 4
15316
+ },
15317
+ issueCard: {
15318
+ backgroundColor: colors.card,
15319
+ borderWidth: 1,
15320
+ borderColor: colors.border,
15321
+ borderRadius: 10,
15322
+ padding: 14,
15323
+ marginBottom: 8
15324
+ },
15325
+ topRow: {
15326
+ flexDirection: "row",
15327
+ alignItems: "flex-start",
15328
+ gap: 8
15329
+ },
15330
+ severityDot: {
15331
+ width: 8,
15332
+ height: 8,
15333
+ borderRadius: 4,
15334
+ marginTop: 5
15335
+ },
15336
+ issueTitle: {
15337
+ fontSize: 13,
15338
+ fontWeight: "600",
15339
+ color: colors.textPrimary,
15340
+ flex: 1
15341
+ },
15342
+ bottomRow: {
15343
+ flexDirection: "row",
15344
+ justifyContent: "space-between",
15345
+ marginTop: 6
15346
+ },
15347
+ routeText: {
15348
+ fontSize: 11,
15349
+ color: colors.textDim,
15350
+ maxWidth: "60%"
15351
+ },
15352
+ timeText: {
15353
+ fontSize: 11,
15354
+ color: colors.textDim,
15355
+ marginLeft: "auto"
15356
+ },
15357
+ verifiedBadge: {
15358
+ flexDirection: "row",
15359
+ alignItems: "center",
15360
+ backgroundColor: "#14532d",
15361
+ borderWidth: 1,
15362
+ borderColor: "#166534",
15363
+ borderRadius: 6,
15364
+ paddingHorizontal: 8,
15365
+ paddingVertical: 2,
15366
+ marginTop: 6,
15367
+ alignSelf: "flex-start"
15368
+ },
15369
+ verifiedBadgeText: {
15370
+ fontSize: 10,
15371
+ fontWeight: "600",
15372
+ color: "#4ade80"
15373
+ },
15374
+ reopenedBadge: {
15375
+ flexDirection: "row",
15376
+ alignItems: "center",
15377
+ backgroundColor: "#422006",
15378
+ borderWidth: 1,
15379
+ borderColor: "#854d0e",
15380
+ borderRadius: 6,
15381
+ paddingHorizontal: 8,
15382
+ paddingVertical: 2,
15383
+ marginTop: 6,
15384
+ alignSelf: "flex-start"
15385
+ },
15386
+ reopenedBadgeText: {
15387
+ fontSize: 10,
15388
+ fontWeight: "600",
15389
+ color: "#fbbf24"
15390
+ }
15391
+ });
15392
+
15393
+ // src/widget/screens/IssueDetailScreen.tsx
15394
+ var import_react17 = __toESM(require("react"));
15395
+ var import_react_native16 = require("react-native");
15396
+ var STATUS_LABELS = {
15397
+ new: { label: "New", bg: "#1e3a5f", color: "#60a5fa" },
15398
+ triaging: { label: "Triaging", bg: "#1e3a5f", color: "#60a5fa" },
15399
+ confirmed: { label: "Confirmed", bg: "#422006", color: "#fbbf24" },
15400
+ in_progress: { label: "In Progress", bg: "#1e3a5f", color: "#60a5fa" },
15401
+ fixed: { label: "Fixed", bg: "#14532d", color: "#4ade80" },
15402
+ ready_to_test: { label: "Ready to Test", bg: "#422006", color: "#fbbf24" },
15403
+ verified: { label: "Verified", bg: "#14532d", color: "#4ade80" },
15404
+ resolved: { label: "Resolved", bg: "#14532d", color: "#4ade80" },
15405
+ reviewed: { label: "Reviewed", bg: "#14532d", color: "#4ade80" },
15406
+ closed: { label: "Closed", bg: "#27272a", color: "#71717a" },
15407
+ wont_fix: { label: "Won't Fix", bg: "#27272a", color: "#71717a" },
15408
+ duplicate: { label: "Duplicate", bg: "#27272a", color: "#71717a" }
15409
+ };
15410
+ var SEVERITY_CONFIG = {
15411
+ critical: { label: "Critical", color: "#ef4444", bg: "#7f1d1d" },
15412
+ high: { label: "High", color: "#f97316", bg: "#431407" },
15413
+ medium: { label: "Medium", color: "#eab308", bg: "#422006" },
15414
+ low: { label: "Low", color: "#71717a", bg: "#27272a" }
15415
+ };
15416
+ function IssueDetailScreen({ nav, issue }) {
15417
+ const statusConfig = STATUS_LABELS[issue.status] || { label: issue.status, bg: "#27272a", color: "#a1a1aa" };
15418
+ const severityConfig = issue.severity ? SEVERITY_CONFIG[issue.severity] : null;
15419
+ return /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, null, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.badgeRow }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: [styles14.badge, { backgroundColor: statusConfig.bg }] }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: [styles14.badgeText, { color: statusConfig.color }] }, statusConfig.label)), severityConfig && /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: [styles14.badge, { backgroundColor: severityConfig.bg }] }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: [styles14.badgeText, { color: severityConfig.color }] }, severityConfig.label))), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.title }, issue.title), issue.route && /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.route }, issue.route), issue.description && /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.descriptionCard }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.descriptionText }, issue.description)), issue.verifiedByName && /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.verifiedCard }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.verifiedHeader }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.verifiedIcon }, "\u2705"), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.verifiedTitle }, "Retesting Proof")), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.verifiedBody }, "Verified by ", issue.verifiedByName, issue.verifiedAt && ` on ${new Date(issue.verifiedAt).toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" })}`)), issue.originalBugTitle && /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.originalBugCard }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.originalBugHeader }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.originalBugIcon }, "\u{1F504}"), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.originalBugTitle }, "Original Bug")), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.originalBugBody }, "Retest of: ", issue.originalBugTitle)), issue.screenshotUrls && issue.screenshotUrls.length > 0 && /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.screenshotSection }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.screenshotLabel }, "Screenshots (", issue.screenshotUrls.length, ")"), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.screenshotRow }, issue.screenshotUrls.map((url, i) => /* @__PURE__ */ import_react17.default.createElement(import_react_native16.TouchableOpacity, { key: i, onPress: () => import_react_native16.Linking.openURL(url), activeOpacity: 0.7 }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Image, { source: { uri: url }, style: styles14.screenshotThumb }))))), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.metaSection }, issue.reporterName && /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.metaText }, "Reported by ", issue.reporterName), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.metaTextSmall }, "Created ", formatRelativeTime(issue.createdAt), " ", "\xB7", " Updated ", formatRelativeTime(issue.updatedAt))));
15420
+ }
15421
+ var styles14 = import_react_native16.StyleSheet.create({
15422
+ badgeRow: {
15423
+ flexDirection: "row",
15424
+ gap: 8,
15425
+ flexWrap: "wrap",
15426
+ marginBottom: 12
15427
+ },
15428
+ badge: {
15429
+ paddingHorizontal: 10,
15430
+ paddingVertical: 3,
15431
+ borderRadius: 6
15432
+ },
15433
+ badgeText: {
15434
+ fontSize: 11,
15435
+ fontWeight: "600"
15436
+ },
15437
+ title: {
15438
+ fontSize: 16,
15439
+ fontWeight: "700",
15440
+ color: colors.textPrimary,
15441
+ marginBottom: 8,
15442
+ lineHeight: 21
15443
+ },
15444
+ route: {
15445
+ fontSize: 12,
15446
+ color: colors.textDim,
15447
+ marginBottom: 12
15448
+ },
15449
+ descriptionCard: {
15450
+ backgroundColor: colors.card,
15451
+ borderWidth: 1,
15452
+ borderColor: colors.border,
15453
+ borderRadius: 8,
15454
+ padding: 12,
15455
+ marginBottom: 12
15456
+ },
15457
+ descriptionText: {
15458
+ fontSize: 13,
15459
+ color: colors.textSecondary,
15460
+ lineHeight: 19
15461
+ },
15462
+ verifiedCard: {
15463
+ backgroundColor: "#14532d",
15464
+ borderWidth: 1,
15465
+ borderColor: "#166534",
15466
+ borderRadius: 8,
15467
+ padding: 12,
15468
+ marginBottom: 12
15469
+ },
15470
+ verifiedHeader: {
15471
+ flexDirection: "row",
15472
+ alignItems: "center",
15473
+ gap: 8,
15474
+ marginBottom: 4
15475
+ },
15476
+ verifiedIcon: {
15477
+ fontSize: 16
15478
+ },
15479
+ verifiedTitle: {
15480
+ fontSize: 13,
15481
+ fontWeight: "600",
15482
+ color: "#4ade80"
15483
+ },
15484
+ verifiedBody: {
15485
+ fontSize: 12,
15486
+ color: "#86efac"
15487
+ },
15488
+ originalBugCard: {
15489
+ backgroundColor: "#422006",
15490
+ borderWidth: 1,
15491
+ borderColor: "#854d0e",
15492
+ borderRadius: 8,
15493
+ padding: 12,
15494
+ marginBottom: 12
15495
+ },
15496
+ originalBugHeader: {
15497
+ flexDirection: "row",
15498
+ alignItems: "center",
15499
+ gap: 8,
15500
+ marginBottom: 4
15501
+ },
15502
+ originalBugIcon: {
15503
+ fontSize: 16
15504
+ },
15505
+ originalBugTitle: {
15506
+ fontSize: 13,
15507
+ fontWeight: "600",
15508
+ color: "#fbbf24"
15509
+ },
15510
+ originalBugBody: {
15511
+ fontSize: 12,
15512
+ color: "#fde68a"
15513
+ },
15514
+ screenshotSection: {
15515
+ marginBottom: 12
15516
+ },
15517
+ screenshotLabel: {
15518
+ fontSize: 12,
15519
+ fontWeight: "600",
15520
+ color: colors.textMuted,
15521
+ marginBottom: 8
15522
+ },
15523
+ screenshotRow: {
15524
+ flexDirection: "row",
15525
+ gap: 8
15526
+ },
15527
+ screenshotThumb: {
15528
+ width: 80,
15529
+ height: 60,
15530
+ borderRadius: 6,
15531
+ borderWidth: 1,
15532
+ borderColor: colors.border
15533
+ },
15534
+ metaSection: {
15535
+ borderTopWidth: 1,
15536
+ borderTopColor: colors.border,
15537
+ paddingTop: 12,
15538
+ marginTop: 4
15539
+ },
15540
+ metaText: {
15541
+ fontSize: 12,
15542
+ color: colors.textDim,
15543
+ marginBottom: 4
15544
+ },
15545
+ metaTextSmall: {
15546
+ fontSize: 11,
15547
+ color: colors.textDim
15548
+ }
15549
+ });
15550
+
15071
15551
  // src/BugBearButton.tsx
15072
- var screenWidth = import_react_native15.Dimensions.get("window").width;
15073
- var screenHeight = import_react_native15.Dimensions.get("window").height;
15552
+ var screenWidth = import_react_native17.Dimensions.get("window").width;
15553
+ var screenHeight = import_react_native17.Dimensions.get("window").height;
15074
15554
  function BugBearButton({
15075
15555
  position = "bottom-right",
15076
15556
  buttonStyle,
@@ -15082,7 +15562,7 @@ function BugBearButton({
15082
15562
  }) {
15083
15563
  const { shouldShowWidget, testerInfo, isLoading, unreadCount, assignments } = useBugBear();
15084
15564
  const { currentScreen, canGoBack, push, pop, replace, reset } = useNavigation();
15085
- const [modalVisible, setModalVisible] = (0, import_react16.useState)(false);
15565
+ const [modalVisible, setModalVisible] = (0, import_react18.useState)(false);
15086
15566
  const getInitialPosition = () => {
15087
15567
  const buttonSize = 56;
15088
15568
  const margin = 16;
@@ -15094,10 +15574,10 @@ function BugBearButton({
15094
15574
  return { x, y };
15095
15575
  };
15096
15576
  const initialPos = getInitialPosition();
15097
- const pan = (0, import_react16.useRef)(new import_react_native15.Animated.ValueXY(initialPos)).current;
15098
- const isDragging = (0, import_react16.useRef)(false);
15099
- const panResponder = (0, import_react16.useRef)(
15100
- import_react_native15.PanResponder.create({
15577
+ const pan = (0, import_react18.useRef)(new import_react_native17.Animated.ValueXY(initialPos)).current;
15578
+ const isDragging = (0, import_react18.useRef)(false);
15579
+ const panResponder = (0, import_react18.useRef)(
15580
+ import_react_native17.PanResponder.create({
15101
15581
  onStartShouldSetPanResponder: () => draggable,
15102
15582
  onMoveShouldSetPanResponder: (_, gs) => draggable && (Math.abs(gs.dx) > 5 || Math.abs(gs.dy) > 5),
15103
15583
  onPanResponderGrant: () => {
@@ -15112,7 +15592,7 @@ function BugBearButton({
15112
15592
  if (Math.abs(gs.dx) > 5 || Math.abs(gs.dy) > 5) {
15113
15593
  isDragging.current = true;
15114
15594
  }
15115
- import_react_native15.Animated.event(
15595
+ import_react_native17.Animated.event(
15116
15596
  [null, { dx: pan.x, dy: pan.y }],
15117
15597
  { useNativeDriver: false }
15118
15598
  )(_, gs);
@@ -15125,7 +15605,7 @@ function BugBearButton({
15125
15605
  const margin = 16;
15126
15606
  const snapX = currentX < screenWidth / 2 ? margin : screenWidth - buttonSize - margin;
15127
15607
  const snapY = Math.max(minY, Math.min(currentY, screenHeight - maxYOffset));
15128
- import_react_native15.Animated.spring(pan, {
15608
+ import_react_native17.Animated.spring(pan, {
15129
15609
  toValue: { x: snapX, y: snapY },
15130
15610
  useNativeDriver: false,
15131
15611
  friction: 7,
@@ -15161,6 +15641,10 @@ function BugBearButton({
15161
15641
  return currentScreen.thread.subject || "Thread";
15162
15642
  case "COMPOSE_MESSAGE":
15163
15643
  return "New Message";
15644
+ case "ISSUE_LIST":
15645
+ return currentScreen.category === "open" ? "Open Issues" : currentScreen.category === "done" ? "Done" : "Reopened";
15646
+ case "ISSUE_DETAIL":
15647
+ return "Issue Detail";
15164
15648
  case "PROFILE":
15165
15649
  return "Profile";
15166
15650
  default:
@@ -15168,24 +15652,24 @@ function BugBearButton({
15168
15652
  }
15169
15653
  };
15170
15654
  const handleClose = () => {
15171
- import_react_native15.Keyboard.dismiss();
15655
+ import_react_native17.Keyboard.dismiss();
15172
15656
  setModalVisible(false);
15173
15657
  };
15174
15658
  const nav = {
15175
15659
  push: (screen) => {
15176
- import_react_native15.Keyboard.dismiss();
15660
+ import_react_native17.Keyboard.dismiss();
15177
15661
  push(screen);
15178
15662
  },
15179
15663
  pop: () => {
15180
- import_react_native15.Keyboard.dismiss();
15664
+ import_react_native17.Keyboard.dismiss();
15181
15665
  pop();
15182
15666
  },
15183
15667
  replace: (screen) => {
15184
- import_react_native15.Keyboard.dismiss();
15668
+ import_react_native17.Keyboard.dismiss();
15185
15669
  replace(screen);
15186
15670
  },
15187
15671
  reset: () => {
15188
- import_react_native15.Keyboard.dismiss();
15672
+ import_react_native17.Keyboard.dismiss();
15189
15673
  reset();
15190
15674
  },
15191
15675
  canGoBack,
@@ -15194,73 +15678,77 @@ function BugBearButton({
15194
15678
  const renderScreen = () => {
15195
15679
  switch (currentScreen.name) {
15196
15680
  case "HOME":
15197
- return /* @__PURE__ */ import_react16.default.createElement(HomeScreen, { nav });
15681
+ return /* @__PURE__ */ import_react18.default.createElement(HomeScreen, { nav });
15198
15682
  case "TEST_DETAIL":
15199
- return /* @__PURE__ */ import_react16.default.createElement(TestDetailScreen, { testId: currentScreen.testId, nav });
15683
+ return /* @__PURE__ */ import_react18.default.createElement(TestDetailScreen, { testId: currentScreen.testId, nav });
15200
15684
  case "TEST_LIST":
15201
- return /* @__PURE__ */ import_react16.default.createElement(TestListScreen, { nav });
15685
+ return /* @__PURE__ */ import_react18.default.createElement(TestListScreen, { nav });
15202
15686
  case "TEST_FEEDBACK":
15203
- return /* @__PURE__ */ import_react16.default.createElement(TestFeedbackScreen, { status: currentScreen.status, assignmentId: currentScreen.assignmentId, nav });
15687
+ return /* @__PURE__ */ import_react18.default.createElement(TestFeedbackScreen, { status: currentScreen.status, assignmentId: currentScreen.assignmentId, nav });
15204
15688
  case "REPORT":
15205
- return /* @__PURE__ */ import_react16.default.createElement(ReportScreen, { nav, prefill: currentScreen.prefill });
15689
+ return /* @__PURE__ */ import_react18.default.createElement(ReportScreen, { nav, prefill: currentScreen.prefill });
15206
15690
  case "REPORT_SUCCESS":
15207
- return /* @__PURE__ */ import_react16.default.createElement(ReportSuccessScreen, { nav });
15691
+ return /* @__PURE__ */ import_react18.default.createElement(ReportSuccessScreen, { nav });
15208
15692
  case "MESSAGE_LIST":
15209
- return /* @__PURE__ */ import_react16.default.createElement(MessageListScreen, { nav });
15693
+ return /* @__PURE__ */ import_react18.default.createElement(MessageListScreen, { nav });
15210
15694
  case "THREAD_DETAIL":
15211
- return /* @__PURE__ */ import_react16.default.createElement(ThreadDetailScreen, { thread: currentScreen.thread, nav });
15695
+ return /* @__PURE__ */ import_react18.default.createElement(ThreadDetailScreen, { thread: currentScreen.thread, nav });
15212
15696
  case "COMPOSE_MESSAGE":
15213
- return /* @__PURE__ */ import_react16.default.createElement(ComposeMessageScreen, { nav });
15697
+ return /* @__PURE__ */ import_react18.default.createElement(ComposeMessageScreen, { nav });
15698
+ case "ISSUE_LIST":
15699
+ return /* @__PURE__ */ import_react18.default.createElement(IssueListScreen, { nav, category: currentScreen.category });
15700
+ case "ISSUE_DETAIL":
15701
+ return /* @__PURE__ */ import_react18.default.createElement(IssueDetailScreen, { nav, issue: currentScreen.issue });
15214
15702
  case "PROFILE":
15215
- return /* @__PURE__ */ import_react16.default.createElement(ProfileScreen, { nav });
15703
+ return /* @__PURE__ */ import_react18.default.createElement(ProfileScreen, { nav });
15216
15704
  default:
15217
- return /* @__PURE__ */ import_react16.default.createElement(HomeScreen, { nav });
15705
+ return /* @__PURE__ */ import_react18.default.createElement(HomeScreen, { nav });
15218
15706
  }
15219
15707
  };
15220
- return /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(
15221
- import_react_native15.Animated.View,
15708
+ return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(
15709
+ import_react_native17.Animated.View,
15222
15710
  {
15223
- style: [styles13.fabContainer, { transform: pan.getTranslateTransform() }, buttonStyle],
15711
+ style: [styles15.fabContainer, { transform: pan.getTranslateTransform() }, buttonStyle],
15224
15712
  ...panResponder.panHandlers
15225
15713
  },
15226
- /* @__PURE__ */ import_react16.default.createElement(
15227
- import_react_native15.TouchableOpacity,
15714
+ /* @__PURE__ */ import_react18.default.createElement(
15715
+ import_react_native17.TouchableOpacity,
15228
15716
  {
15229
- style: styles13.fab,
15717
+ style: styles15.fab,
15230
15718
  onPress: () => setModalVisible(true),
15231
15719
  activeOpacity: draggable ? 1 : 0.7
15232
15720
  },
15233
- /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Image, { source: { uri: BUGBEAR_LOGO_BASE64 }, style: styles13.fabIcon }),
15234
- badgeCount > 0 && /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.badge }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.badgeText }, badgeCount > 9 ? "9+" : badgeCount))
15721
+ /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Image, { source: { uri: BUGBEAR_LOGO_BASE64 }, style: styles15.fabIcon }),
15722
+ badgeCount > 0 && /* @__PURE__ */ import_react18.default.createElement(import_react_native17.View, { style: styles15.badge }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Text, { style: styles15.badgeText }, badgeCount > 9 ? "9+" : badgeCount))
15235
15723
  )
15236
- ), /* @__PURE__ */ import_react16.default.createElement(
15237
- import_react_native15.Modal,
15724
+ ), /* @__PURE__ */ import_react18.default.createElement(
15725
+ import_react_native17.Modal,
15238
15726
  {
15239
15727
  visible: modalVisible,
15240
15728
  animationType: "slide",
15241
15729
  transparent: true,
15242
15730
  onRequestClose: handleClose
15243
15731
  },
15244
- /* @__PURE__ */ import_react16.default.createElement(
15245
- import_react_native15.KeyboardAvoidingView,
15732
+ /* @__PURE__ */ import_react18.default.createElement(
15733
+ import_react_native17.KeyboardAvoidingView,
15246
15734
  {
15247
- behavior: import_react_native15.Platform.OS === "ios" ? "padding" : "height",
15248
- style: styles13.modalOverlay
15735
+ behavior: import_react_native17.Platform.OS === "ios" ? "padding" : "height",
15736
+ style: styles15.modalOverlay
15249
15737
  },
15250
- /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.modalContainer }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.header }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.headerLeft }, canGoBack ? /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.headerNavRow }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.TouchableOpacity, { onPress: () => nav.pop(), style: styles13.backButton }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.backText }, "\u2190 Back")), /* @__PURE__ */ import_react16.default.createElement(import_react_native15.TouchableOpacity, { onPress: () => nav.reset(), style: styles13.homeButton }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.homeText }, "\u{1F3E0}"))) : /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.headerTitleRow }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.headerTitle }, "BugBear"), testerInfo && /* @__PURE__ */ import_react16.default.createElement(import_react_native15.TouchableOpacity, { onPress: () => push({ name: "PROFILE" }) }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.headerName }, testerInfo.name, " \u270E")))), getHeaderTitle() ? /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.headerScreenTitle, numberOfLines: 1 }, getHeaderTitle()) : null, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.TouchableOpacity, { onPress: handleClose, style: styles13.closeButton }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.closeText }, "\u2715"))), /* @__PURE__ */ import_react16.default.createElement(
15251
- import_react_native15.ScrollView,
15738
+ /* @__PURE__ */ import_react18.default.createElement(import_react_native17.View, { style: styles15.modalContainer }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.View, { style: styles15.header }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.View, { style: styles15.headerLeft }, canGoBack ? /* @__PURE__ */ import_react18.default.createElement(import_react_native17.View, { style: styles15.headerNavRow }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.TouchableOpacity, { onPress: () => nav.pop(), style: styles15.backButton }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Text, { style: styles15.backText }, "\u2190 Back")), /* @__PURE__ */ import_react18.default.createElement(import_react_native17.TouchableOpacity, { onPress: () => nav.reset(), style: styles15.homeButton }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Text, { style: styles15.homeText }, "\u{1F3E0}"))) : /* @__PURE__ */ import_react18.default.createElement(import_react_native17.View, { style: styles15.headerTitleRow }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Text, { style: styles15.headerTitle }, "BugBear"), testerInfo && /* @__PURE__ */ import_react18.default.createElement(import_react_native17.TouchableOpacity, { onPress: () => push({ name: "PROFILE" }) }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Text, { style: styles15.headerName }, testerInfo.name, " \u270E")))), getHeaderTitle() ? /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Text, { style: styles15.headerScreenTitle, numberOfLines: 1 }, getHeaderTitle()) : null, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.TouchableOpacity, { onPress: handleClose, style: styles15.closeButton }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Text, { style: styles15.closeText }, "\u2715"))), /* @__PURE__ */ import_react18.default.createElement(
15739
+ import_react_native17.ScrollView,
15252
15740
  {
15253
- style: styles13.content,
15254
- contentContainerStyle: styles13.contentContainer,
15741
+ style: styles15.content,
15742
+ contentContainerStyle: styles15.contentContainer,
15255
15743
  keyboardShouldPersistTaps: "handled",
15256
15744
  showsVerticalScrollIndicator: false
15257
15745
  },
15258
- isLoading ? /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.loadingContainer }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.ActivityIndicator, { size: "large", color: colors.blue }), /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.loadingText }, "Loading...")) : renderScreen()
15746
+ isLoading ? /* @__PURE__ */ import_react18.default.createElement(import_react_native17.View, { style: styles15.loadingContainer }, /* @__PURE__ */ import_react18.default.createElement(import_react_native17.ActivityIndicator, { size: "large", color: colors.blue }), /* @__PURE__ */ import_react18.default.createElement(import_react_native17.Text, { style: styles15.loadingText }, "Loading...")) : renderScreen()
15259
15747
  ))
15260
15748
  )
15261
15749
  ));
15262
15750
  }
15263
- var styles13 = import_react_native15.StyleSheet.create({
15751
+ var styles15 = import_react_native17.StyleSheet.create({
15264
15752
  // FAB
15265
15753
  fabContainer: {
15266
15754
  position: "absolute",
@@ -15402,9 +15890,9 @@ var styles13 = import_react_native15.StyleSheet.create({
15402
15890
  });
15403
15891
 
15404
15892
  // src/BugBearErrorBoundary.tsx
15405
- var import_react17 = __toESM(require("react"));
15406
- var import_react_native16 = require("react-native");
15407
- var BugBearErrorBoundary = class extends import_react17.Component {
15893
+ var import_react19 = __toESM(require("react"));
15894
+ var import_react_native18 = require("react-native");
15895
+ var BugBearErrorBoundary = class extends import_react19.Component {
15408
15896
  constructor(props) {
15409
15897
  super(props);
15410
15898
  this.reset = () => {
@@ -15448,7 +15936,7 @@ var BugBearErrorBoundary = class extends import_react17.Component {
15448
15936
  if (fallback) {
15449
15937
  return fallback;
15450
15938
  }
15451
- return /* @__PURE__ */ import_react17.default.createElement(import_react_native16.View, { style: styles14.container }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.title }, "Something went wrong"), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.message }, error.message), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.TouchableOpacity, { style: styles14.button, onPress: this.reset }, /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.buttonText }, "Try Again")), /* @__PURE__ */ import_react17.default.createElement(import_react_native16.Text, { style: styles14.caption }, "The error has been captured by BugBear"));
15939
+ return /* @__PURE__ */ import_react19.default.createElement(import_react_native18.View, { style: styles16.container }, /* @__PURE__ */ import_react19.default.createElement(import_react_native18.Text, { style: styles16.title }, "Something went wrong"), /* @__PURE__ */ import_react19.default.createElement(import_react_native18.Text, { style: styles16.message }, error.message), /* @__PURE__ */ import_react19.default.createElement(import_react_native18.TouchableOpacity, { style: styles16.button, onPress: this.reset }, /* @__PURE__ */ import_react19.default.createElement(import_react_native18.Text, { style: styles16.buttonText }, "Try Again")), /* @__PURE__ */ import_react19.default.createElement(import_react_native18.Text, { style: styles16.caption }, "The error has been captured by BugBear"));
15452
15940
  }
15453
15941
  return children;
15454
15942
  }
@@ -15459,7 +15947,7 @@ function useErrorContext() {
15459
15947
  getEnhancedContext: () => contextCapture.getEnhancedContext()
15460
15948
  };
15461
15949
  }
15462
- var styles14 = import_react_native16.StyleSheet.create({
15950
+ var styles16 = import_react_native18.StyleSheet.create({
15463
15951
  container: {
15464
15952
  padding: 20,
15465
15953
  margin: 20,