@bbearai/react-native 0.3.7 → 0.3.9

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.
Files changed (4) hide show
  1. package/README.md +139 -92
  2. package/dist/index.js +343 -171
  3. package/dist/index.mjs +346 -173
  4. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -11361,6 +11361,239 @@ function shouldShowDeprecationWarning() {
11361
11361
  if (shouldShowDeprecationWarning()) console.warn("\u26A0\uFE0F Node.js 18 and below are deprecated and will no longer be supported in future versions of @supabase/supabase-js. Please upgrade to Node.js 20 or later. For more information, visit: https://github.com/orgs/supabase/discussions/37217");
11362
11362
 
11363
11363
  // ../core/dist/index.mjs
11364
+ var MAX_CONSOLE_LOGS = 50;
11365
+ var MAX_NETWORK_REQUESTS = 20;
11366
+ var MAX_NAVIGATION_HISTORY = 20;
11367
+ var MAX_RESPONSE_BODY_LENGTH = 500;
11368
+ var ContextCaptureManager = class {
11369
+ constructor() {
11370
+ this.consoleLogs = [];
11371
+ this.networkRequests = [];
11372
+ this.navigationHistory = [];
11373
+ this.originalConsole = {};
11374
+ this.isCapturing = false;
11375
+ }
11376
+ /**
11377
+ * Start capturing console logs, network requests, and navigation
11378
+ */
11379
+ startCapture() {
11380
+ if (this.isCapturing) return;
11381
+ this.isCapturing = true;
11382
+ this.captureConsole();
11383
+ this.captureFetch();
11384
+ this.captureNavigation();
11385
+ }
11386
+ /**
11387
+ * Stop capturing and restore original functions
11388
+ */
11389
+ stopCapture() {
11390
+ if (!this.isCapturing) return;
11391
+ this.isCapturing = false;
11392
+ if (this.originalConsole.log) console.log = this.originalConsole.log;
11393
+ if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
11394
+ if (this.originalConsole.error) console.error = this.originalConsole.error;
11395
+ if (this.originalConsole.info) console.info = this.originalConsole.info;
11396
+ if (this.originalFetch && typeof window !== "undefined") {
11397
+ window.fetch = this.originalFetch;
11398
+ }
11399
+ if (typeof window !== "undefined" && typeof history !== "undefined") {
11400
+ if (this.originalPushState) {
11401
+ history.pushState = this.originalPushState;
11402
+ }
11403
+ if (this.originalReplaceState) {
11404
+ history.replaceState = this.originalReplaceState;
11405
+ }
11406
+ if (this.popstateHandler) {
11407
+ window.removeEventListener("popstate", this.popstateHandler);
11408
+ }
11409
+ }
11410
+ }
11411
+ /**
11412
+ * Get captured context for a bug report
11413
+ */
11414
+ getEnhancedContext() {
11415
+ return {
11416
+ consoleLogs: [...this.consoleLogs],
11417
+ networkRequests: [...this.networkRequests],
11418
+ navigationHistory: [...this.navigationHistory],
11419
+ performanceMetrics: this.getPerformanceMetrics(),
11420
+ environment: this.getEnvironmentInfo()
11421
+ };
11422
+ }
11423
+ /**
11424
+ * Get the auto-captured navigation history
11425
+ */
11426
+ getNavigationHistory() {
11427
+ return [...this.navigationHistory];
11428
+ }
11429
+ /**
11430
+ * Get the current route (last entry in navigation history, or window.location)
11431
+ */
11432
+ getCurrentRoute() {
11433
+ if (this.navigationHistory.length > 0) {
11434
+ return this.navigationHistory[this.navigationHistory.length - 1];
11435
+ }
11436
+ if (typeof window !== "undefined") {
11437
+ return window.location.pathname;
11438
+ }
11439
+ return "unknown";
11440
+ }
11441
+ /**
11442
+ * Manually track a navigation event (for React Native or custom routing)
11443
+ */
11444
+ trackNavigation(route) {
11445
+ const last = this.navigationHistory[this.navigationHistory.length - 1];
11446
+ if (route === last) return;
11447
+ this.navigationHistory.push(route);
11448
+ if (this.navigationHistory.length > MAX_NAVIGATION_HISTORY) {
11449
+ this.navigationHistory.shift();
11450
+ }
11451
+ }
11452
+ /**
11453
+ * Clear captured data
11454
+ */
11455
+ clear() {
11456
+ this.consoleLogs = [];
11457
+ this.networkRequests = [];
11458
+ this.navigationHistory = [];
11459
+ }
11460
+ /**
11461
+ * Add a log entry manually (for custom logging)
11462
+ */
11463
+ addLog(level, message, args) {
11464
+ this.consoleLogs.push({
11465
+ level,
11466
+ message,
11467
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11468
+ args
11469
+ });
11470
+ if (this.consoleLogs.length > MAX_CONSOLE_LOGS) {
11471
+ this.consoleLogs = this.consoleLogs.slice(-MAX_CONSOLE_LOGS);
11472
+ }
11473
+ }
11474
+ /**
11475
+ * Add a network request manually
11476
+ */
11477
+ addNetworkRequest(request) {
11478
+ this.networkRequests.push(request);
11479
+ if (this.networkRequests.length > MAX_NETWORK_REQUESTS) {
11480
+ this.networkRequests = this.networkRequests.slice(-MAX_NETWORK_REQUESTS);
11481
+ }
11482
+ }
11483
+ captureConsole() {
11484
+ if (typeof console === "undefined") return;
11485
+ const levels = ["log", "warn", "error", "info"];
11486
+ levels.forEach((level) => {
11487
+ this.originalConsole[level] = console[level];
11488
+ console[level] = (...args) => {
11489
+ this.originalConsole[level]?.apply(console, args);
11490
+ try {
11491
+ const message = args.map((arg) => {
11492
+ if (typeof arg === "string") return arg;
11493
+ try {
11494
+ return JSON.stringify(arg);
11495
+ } catch {
11496
+ return String(arg);
11497
+ }
11498
+ }).join(" ");
11499
+ this.addLog(level, message.slice(0, 500));
11500
+ } catch {
11501
+ }
11502
+ };
11503
+ });
11504
+ }
11505
+ captureFetch() {
11506
+ if (typeof window === "undefined" || typeof fetch === "undefined") return;
11507
+ this.originalFetch = window.fetch;
11508
+ const self2 = this;
11509
+ window.fetch = async function(input, init) {
11510
+ const startTime = Date.now();
11511
+ const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
11512
+ const method = init?.method || "GET";
11513
+ try {
11514
+ const response = await self2.originalFetch.call(window, input, init);
11515
+ const requestEntry = {
11516
+ method,
11517
+ url: url.slice(0, 200),
11518
+ // Limit URL length
11519
+ status: response.status,
11520
+ duration: Date.now() - startTime,
11521
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
11522
+ };
11523
+ if (response.status >= 400) {
11524
+ try {
11525
+ const cloned = response.clone();
11526
+ const body = await cloned.text();
11527
+ if (body) {
11528
+ requestEntry.responseBody = body.slice(0, MAX_RESPONSE_BODY_LENGTH);
11529
+ }
11530
+ } catch {
11531
+ }
11532
+ }
11533
+ self2.addNetworkRequest(requestEntry);
11534
+ return response;
11535
+ } catch (error) {
11536
+ self2.addNetworkRequest({
11537
+ method,
11538
+ url: url.slice(0, 200),
11539
+ duration: Date.now() - startTime,
11540
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11541
+ error: error instanceof Error ? error.message : "Unknown error"
11542
+ });
11543
+ throw error;
11544
+ }
11545
+ };
11546
+ }
11547
+ captureNavigation() {
11548
+ if (typeof window === "undefined" || typeof history === "undefined") return;
11549
+ this.trackNavigation(window.location.pathname);
11550
+ const self2 = this;
11551
+ this.originalPushState = history.pushState;
11552
+ history.pushState = function(...args) {
11553
+ self2.originalPushState.apply(history, args);
11554
+ self2.trackNavigation(window.location.pathname);
11555
+ };
11556
+ this.originalReplaceState = history.replaceState;
11557
+ history.replaceState = function(...args) {
11558
+ self2.originalReplaceState.apply(history, args);
11559
+ self2.trackNavigation(window.location.pathname);
11560
+ };
11561
+ this.popstateHandler = () => {
11562
+ self2.trackNavigation(window.location.pathname);
11563
+ };
11564
+ window.addEventListener("popstate", this.popstateHandler);
11565
+ }
11566
+ getPerformanceMetrics() {
11567
+ if (typeof window === "undefined" || typeof performance === "undefined") return void 0;
11568
+ const metrics = {};
11569
+ try {
11570
+ const navigation = performance.getEntriesByType("navigation")[0];
11571
+ if (navigation) {
11572
+ metrics.pageLoadTime = Math.round(navigation.loadEventEnd - navigation.startTime);
11573
+ }
11574
+ } catch {
11575
+ }
11576
+ try {
11577
+ const memory = performance.memory;
11578
+ if (memory) {
11579
+ metrics.memoryUsage = Math.round(memory.usedJSHeapSize / 1024 / 1024);
11580
+ }
11581
+ } catch {
11582
+ }
11583
+ return Object.keys(metrics).length > 0 ? metrics : void 0;
11584
+ }
11585
+ getEnvironmentInfo() {
11586
+ if (typeof window === "undefined" || typeof navigator === "undefined") return void 0;
11587
+ return {
11588
+ language: navigator.language,
11589
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
11590
+ cookiesEnabled: navigator.cookieEnabled,
11591
+ localStorage: typeof localStorage !== "undefined",
11592
+ online: navigator.onLine
11593
+ };
11594
+ }
11595
+ };
11596
+ var contextCapture = new ContextCaptureManager();
11364
11597
  var DEFAULT_SUPABASE_URL = "https://kyxgzjnqgvapvlnvqawz.supabase.co";
11365
11598
  var getEnvVar = (key) => {
11366
11599
  try {
@@ -11382,22 +11615,40 @@ var BugBearClient = class {
11382
11615
  );
11383
11616
  }
11384
11617
  /**
11385
- * Track navigation for context
11618
+ * Track navigation for context.
11619
+ * Also forwards to contextCapture for auto-tracked navigation.
11386
11620
  */
11387
11621
  trackNavigation(route) {
11388
11622
  this.navigationHistory.push(route);
11389
11623
  if (this.navigationHistory.length > 10) {
11390
11624
  this.navigationHistory.shift();
11391
11625
  }
11626
+ contextCapture.trackNavigation(route);
11392
11627
  }
11393
11628
  /**
11394
- * Get current navigation history
11629
+ * Get current navigation history.
11630
+ * Priority: config callback > manual tracking > auto-captured (pushState/popstate)
11395
11631
  */
11396
11632
  getNavigationHistory() {
11397
11633
  if (this.config.getNavigationHistory) {
11398
11634
  return this.config.getNavigationHistory();
11399
11635
  }
11400
- return [...this.navigationHistory];
11636
+ if (this.navigationHistory.length > 0) {
11637
+ return [...this.navigationHistory];
11638
+ }
11639
+ return contextCapture.getNavigationHistory();
11640
+ }
11641
+ /**
11642
+ * Get current app context.
11643
+ * Uses config.getAppContext() callback if provided, otherwise builds from available data.
11644
+ */
11645
+ getAppContext() {
11646
+ if (this.config.getAppContext) {
11647
+ return this.config.getAppContext();
11648
+ }
11649
+ return {
11650
+ currentRoute: contextCapture.getCurrentRoute()
11651
+ };
11401
11652
  }
11402
11653
  /**
11403
11654
  * Get current user info from host app or BugBear's own auth
@@ -11437,6 +11688,8 @@ var BugBearClient = class {
11437
11688
  project_id: this.config.projectId,
11438
11689
  reporter_id: userInfo.id,
11439
11690
  // User ID from host app (required)
11691
+ reporter_name: testerInfo?.name || userInfo.name || null,
11692
+ reporter_email: userInfo.email || null,
11440
11693
  tester_id: testerInfo?.id || null,
11441
11694
  // Tester record ID (optional)
11442
11695
  report_type: report.type,
@@ -11450,6 +11703,7 @@ var BugBearClient = class {
11450
11703
  app_context: report.appContext,
11451
11704
  device_info: report.deviceInfo || this.getDeviceInfo(),
11452
11705
  navigation_history: this.getNavigationHistory(),
11706
+ enhanced_context: report.enhancedContext || contextCapture.getEnhancedContext(),
11453
11707
  assignment_id: report.assignmentId,
11454
11708
  test_case_id: report.testCaseId
11455
11709
  };
@@ -11697,19 +11951,40 @@ var BugBearClient = class {
11697
11951
  return { success: false, error: message };
11698
11952
  }
11699
11953
  }
11954
+ /**
11955
+ * Pass a test assignment — convenience wrapper around updateAssignmentStatus
11956
+ */
11957
+ async passAssignment(assignmentId) {
11958
+ return this.updateAssignmentStatus(assignmentId, "passed");
11959
+ }
11960
+ /**
11961
+ * Fail a test assignment — convenience wrapper around updateAssignmentStatus
11962
+ */
11963
+ async failAssignment(assignmentId) {
11964
+ return this.updateAssignmentStatus(assignmentId, "failed");
11965
+ }
11700
11966
  /**
11701
11967
  * Skip a test assignment with a required reason
11702
11968
  * Marks the assignment as 'skipped' and records why it was skipped
11703
11969
  */
11704
11970
  async skipAssignment(assignmentId, reason, notes) {
11971
+ let actualReason;
11972
+ let actualNotes;
11973
+ if (typeof reason === "object") {
11974
+ actualReason = reason.reason;
11975
+ actualNotes = reason.notes;
11976
+ } else {
11977
+ actualReason = reason;
11978
+ actualNotes = notes;
11979
+ }
11705
11980
  try {
11706
11981
  const updateData = {
11707
11982
  status: "skipped",
11708
- skip_reason: reason,
11983
+ skip_reason: actualReason,
11709
11984
  completed_at: (/* @__PURE__ */ new Date()).toISOString()
11710
11985
  };
11711
- if (notes) {
11712
- updateData.notes = notes;
11986
+ if (actualNotes) {
11987
+ updateData.notes = actualNotes;
11713
11988
  }
11714
11989
  const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11715
11990
  if (error) {
@@ -12683,163 +12958,6 @@ var BugBearClient = class {
12683
12958
  function createBugBear(config) {
12684
12959
  return new BugBearClient(config);
12685
12960
  }
12686
- var MAX_CONSOLE_LOGS = 50;
12687
- var MAX_NETWORK_REQUESTS = 20;
12688
- var ContextCaptureManager = class {
12689
- constructor() {
12690
- this.consoleLogs = [];
12691
- this.networkRequests = [];
12692
- this.originalConsole = {};
12693
- this.isCapturing = false;
12694
- }
12695
- /**
12696
- * Start capturing console logs and network requests
12697
- */
12698
- startCapture() {
12699
- if (this.isCapturing) return;
12700
- this.isCapturing = true;
12701
- this.captureConsole();
12702
- this.captureFetch();
12703
- }
12704
- /**
12705
- * Stop capturing and restore original functions
12706
- */
12707
- stopCapture() {
12708
- if (!this.isCapturing) return;
12709
- this.isCapturing = false;
12710
- if (this.originalConsole.log) console.log = this.originalConsole.log;
12711
- if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
12712
- if (this.originalConsole.error) console.error = this.originalConsole.error;
12713
- if (this.originalConsole.info) console.info = this.originalConsole.info;
12714
- if (this.originalFetch && typeof window !== "undefined") {
12715
- window.fetch = this.originalFetch;
12716
- }
12717
- }
12718
- /**
12719
- * Get captured context for a bug report
12720
- */
12721
- getEnhancedContext() {
12722
- return {
12723
- consoleLogs: [...this.consoleLogs],
12724
- networkRequests: [...this.networkRequests],
12725
- performanceMetrics: this.getPerformanceMetrics(),
12726
- environment: this.getEnvironmentInfo()
12727
- };
12728
- }
12729
- /**
12730
- * Clear captured data
12731
- */
12732
- clear() {
12733
- this.consoleLogs = [];
12734
- this.networkRequests = [];
12735
- }
12736
- /**
12737
- * Add a log entry manually (for custom logging)
12738
- */
12739
- addLog(level, message, args) {
12740
- this.consoleLogs.push({
12741
- level,
12742
- message,
12743
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12744
- args
12745
- });
12746
- if (this.consoleLogs.length > MAX_CONSOLE_LOGS) {
12747
- this.consoleLogs = this.consoleLogs.slice(-MAX_CONSOLE_LOGS);
12748
- }
12749
- }
12750
- /**
12751
- * Add a network request manually
12752
- */
12753
- addNetworkRequest(request) {
12754
- this.networkRequests.push(request);
12755
- if (this.networkRequests.length > MAX_NETWORK_REQUESTS) {
12756
- this.networkRequests = this.networkRequests.slice(-MAX_NETWORK_REQUESTS);
12757
- }
12758
- }
12759
- captureConsole() {
12760
- if (typeof console === "undefined") return;
12761
- const levels = ["log", "warn", "error", "info"];
12762
- levels.forEach((level) => {
12763
- this.originalConsole[level] = console[level];
12764
- console[level] = (...args) => {
12765
- this.originalConsole[level]?.apply(console, args);
12766
- try {
12767
- const message = args.map((arg) => {
12768
- if (typeof arg === "string") return arg;
12769
- try {
12770
- return JSON.stringify(arg);
12771
- } catch {
12772
- return String(arg);
12773
- }
12774
- }).join(" ");
12775
- this.addLog(level, message.slice(0, 500));
12776
- } catch {
12777
- }
12778
- };
12779
- });
12780
- }
12781
- captureFetch() {
12782
- if (typeof window === "undefined" || typeof fetch === "undefined") return;
12783
- this.originalFetch = window.fetch;
12784
- const self2 = this;
12785
- window.fetch = async function(input, init) {
12786
- const startTime = Date.now();
12787
- const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
12788
- const method = init?.method || "GET";
12789
- try {
12790
- const response = await self2.originalFetch.call(window, input, init);
12791
- self2.addNetworkRequest({
12792
- method,
12793
- url: url.slice(0, 200),
12794
- // Limit URL length
12795
- status: response.status,
12796
- duration: Date.now() - startTime,
12797
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
12798
- });
12799
- return response;
12800
- } catch (error) {
12801
- self2.addNetworkRequest({
12802
- method,
12803
- url: url.slice(0, 200),
12804
- duration: Date.now() - startTime,
12805
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12806
- error: error instanceof Error ? error.message : "Unknown error"
12807
- });
12808
- throw error;
12809
- }
12810
- };
12811
- }
12812
- getPerformanceMetrics() {
12813
- if (typeof window === "undefined" || typeof performance === "undefined") return void 0;
12814
- const metrics = {};
12815
- try {
12816
- const navigation = performance.getEntriesByType("navigation")[0];
12817
- if (navigation) {
12818
- metrics.pageLoadTime = Math.round(navigation.loadEventEnd - navigation.startTime);
12819
- }
12820
- } catch {
12821
- }
12822
- try {
12823
- const memory = performance.memory;
12824
- if (memory) {
12825
- metrics.memoryUsage = Math.round(memory.usedJSHeapSize / 1024 / 1024);
12826
- }
12827
- } catch {
12828
- }
12829
- return Object.keys(metrics).length > 0 ? metrics : void 0;
12830
- }
12831
- getEnvironmentInfo() {
12832
- if (typeof window === "undefined" || typeof navigator === "undefined") return void 0;
12833
- return {
12834
- language: navigator.language,
12835
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
12836
- cookiesEnabled: navigator.cookieEnabled,
12837
- localStorage: typeof localStorage !== "undefined",
12838
- online: navigator.onLine
12839
- };
12840
- }
12841
- };
12842
- var contextCapture = new ContextCaptureManager();
12843
12961
 
12844
12962
  // src/BugBearProvider.tsx
12845
12963
  import { Platform, Dimensions } from "react-native";
@@ -13040,6 +13158,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
13040
13158
  useEffect(() => {
13041
13159
  if (enabled && !hasInitialized.current) {
13042
13160
  hasInitialized.current = true;
13161
+ contextCapture.startCapture();
13043
13162
  const newClient = createBugBear(config);
13044
13163
  setClient(newClient);
13045
13164
  initializeBugBear(newClient);
@@ -13106,7 +13225,8 @@ import {
13106
13225
  Platform as Platform4,
13107
13226
  PanResponder,
13108
13227
  Animated,
13109
- ActivityIndicator as ActivityIndicator2
13228
+ ActivityIndicator as ActivityIndicator2,
13229
+ Keyboard as Keyboard2
13110
13230
  } from "react-native";
13111
13231
 
13112
13232
  // src/widget/logo.ts
@@ -13363,7 +13483,7 @@ function HomeScreen({ nav }) {
13363
13483
  TouchableOpacity,
13364
13484
  {
13365
13485
  style: styles.actionCard,
13366
- onPress: () => nav.push({ name: "TEST_DETAIL" }),
13486
+ onPress: () => nav.push({ name: "TEST_LIST" }),
13367
13487
  activeOpacity: 0.7
13368
13488
  },
13369
13489
  /* @__PURE__ */ React2.createElement(Text, { style: styles.actionIcon }, "\u2705"),
@@ -13596,7 +13716,7 @@ var styles = StyleSheet2.create({
13596
13716
 
13597
13717
  // src/widget/screens/TestDetailScreen.tsx
13598
13718
  import React3, { useState as useState2, useEffect as useEffect3, useCallback as useCallback2 } from "react";
13599
- import { View as View2, Text as Text2, TouchableOpacity as TouchableOpacity2, StyleSheet as StyleSheet3, Modal, TextInput } from "react-native";
13719
+ import { View as View2, Text as Text2, TouchableOpacity as TouchableOpacity2, StyleSheet as StyleSheet3, Modal, TextInput, Keyboard } from "react-native";
13600
13720
  function TestDetailScreen({ testId, nav }) {
13601
13721
  const { client, assignments, currentAssignment, refreshAssignments, getDeviceInfo, onNavigate } = useBugBear();
13602
13722
  const displayedAssignment = testId ? assignments.find((a) => a.id === testId) || currentAssignment : currentAssignment;
@@ -13631,12 +13751,14 @@ function TestDetailScreen({ testId, nav }) {
13631
13751
  const currentIndex = displayedAssignment ? assignments.indexOf(displayedAssignment) : -1;
13632
13752
  const handlePass = useCallback2(async () => {
13633
13753
  if (!client || !displayedAssignment) return;
13754
+ Keyboard.dismiss();
13634
13755
  await client.passAssignment(displayedAssignment.id);
13635
13756
  await refreshAssignments();
13636
13757
  nav.replace({ name: "TEST_FEEDBACK", status: "passed", assignmentId: displayedAssignment.id });
13637
13758
  }, [client, displayedAssignment, refreshAssignments, nav]);
13638
13759
  const handleFail = useCallback2(async () => {
13639
13760
  if (!client || !displayedAssignment) return;
13761
+ Keyboard.dismiss();
13640
13762
  await client.failAssignment(displayedAssignment.id);
13641
13763
  await refreshAssignments();
13642
13764
  nav.replace({
@@ -13650,6 +13772,7 @@ function TestDetailScreen({ testId, nav }) {
13650
13772
  }, [client, displayedAssignment, refreshAssignments, nav]);
13651
13773
  const handleSkip = useCallback2(async () => {
13652
13774
  if (!client || !displayedAssignment || !selectedSkipReason) return;
13775
+ Keyboard.dismiss();
13653
13776
  setSkipping(true);
13654
13777
  await client.skipAssignment(displayedAssignment.id, {
13655
13778
  reason: selectedSkipReason,
@@ -13718,7 +13841,9 @@ function TestDetailScreen({ testId, nav }) {
13718
13841
  {
13719
13842
  style: styles2.navigateButton,
13720
13843
  onPress: () => {
13844
+ Keyboard.dismiss();
13721
13845
  onNavigate(testCase.targetRoute);
13846
+ nav.closeWidget?.();
13722
13847
  }
13723
13848
  },
13724
13849
  /* @__PURE__ */ React3.createElement(Text2, { style: styles2.navigateText }, "\u{1F9ED} Go to test location")
@@ -14279,12 +14404,18 @@ function ReportScreen({ nav, prefill }) {
14279
14404
  const [reportType, setReportType] = useState6(prefill?.type || "bug");
14280
14405
  const [severity, setSeverity] = useState6("medium");
14281
14406
  const [description, setDescription] = useState6("");
14407
+ const [affectedScreen, setAffectedScreen] = useState6("");
14282
14408
  const [submitting, setSubmitting] = useState6(false);
14283
14409
  const images = useImageAttachments(uploadImage, 5, "screenshots");
14284
14410
  const isBugType = reportType === "bug" || reportType === "test_fail";
14285
14411
  const handleSubmit = async () => {
14286
14412
  if (!client || !description.trim()) return;
14287
14413
  setSubmitting(true);
14414
+ const baseContext = client.getAppContext();
14415
+ const appContext = {
14416
+ ...baseContext,
14417
+ currentRoute: affectedScreen.trim() || baseContext.currentRoute
14418
+ };
14288
14419
  const screenshotUrls = images.getScreenshotUrls();
14289
14420
  await client.submitReport({
14290
14421
  type: reportType,
@@ -14292,7 +14423,7 @@ function ReportScreen({ nav, prefill }) {
14292
14423
  severity: isBugType ? severity : void 0,
14293
14424
  assignmentId: prefill?.assignmentId,
14294
14425
  testCaseId: prefill?.testCaseId,
14295
- appContext: { currentRoute: "unknown" },
14426
+ appContext,
14296
14427
  deviceInfo: getDeviceInfo(),
14297
14428
  screenshots: screenshotUrls.length > 0 ? screenshotUrls : void 0
14298
14429
  });
@@ -14340,7 +14471,16 @@ function ReportScreen({ nav, prefill }) {
14340
14471
  numberOfLines: 4,
14341
14472
  textAlignVertical: "top"
14342
14473
  }
14343
- )), /* @__PURE__ */ React8.createElement(
14474
+ )), isBugType && /* @__PURE__ */ React8.createElement(View7, { style: styles7.section }, /* @__PURE__ */ React8.createElement(Text7, { style: shared.label }, "Which screen?"), /* @__PURE__ */ React8.createElement(
14475
+ TextInput3,
14476
+ {
14477
+ style: styles7.screenInput,
14478
+ value: affectedScreen,
14479
+ onChangeText: setAffectedScreen,
14480
+ placeholder: "e.g. Reservations, Settings...",
14481
+ placeholderTextColor: colors.textMuted
14482
+ }
14483
+ ), /* @__PURE__ */ React8.createElement(Text7, { style: styles7.screenHint }, "Which screen or area was the bug on? (optional)")), /* @__PURE__ */ React8.createElement(
14344
14484
  ImagePickerButtons,
14345
14485
  {
14346
14486
  images: images.images,
@@ -14371,7 +14511,9 @@ var styles7 = StyleSheet8.create({
14371
14511
  severityRow: { flexDirection: "row", gap: 8 },
14372
14512
  sevButton: { flex: 1, paddingVertical: 8, borderRadius: 8, alignItems: "center", borderWidth: 1, borderColor: colors.border, backgroundColor: colors.card },
14373
14513
  sevText: { fontSize: 12, fontWeight: "500", color: colors.textSecondary, textTransform: "capitalize" },
14374
- descInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, fontSize: 14, color: colors.textPrimary, minHeight: 100 }
14514
+ descInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, fontSize: 14, color: colors.textPrimary, minHeight: 100 },
14515
+ screenInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 12, paddingVertical: 8, fontSize: 13, color: colors.textPrimary },
14516
+ screenHint: { fontSize: 11, color: colors.textMuted, marginTop: 4 }
14375
14517
  });
14376
14518
 
14377
14519
  // src/widget/screens/ReportSuccessScreen.tsx
@@ -14842,10 +14984,29 @@ function BugBearButton({
14842
14984
  }
14843
14985
  };
14844
14986
  const handleClose = () => {
14987
+ Keyboard2.dismiss();
14845
14988
  setModalVisible(false);
14846
- reset();
14847
14989
  };
14848
- const nav = { push, pop, replace, reset, canGoBack };
14990
+ const nav = {
14991
+ push: (screen) => {
14992
+ Keyboard2.dismiss();
14993
+ push(screen);
14994
+ },
14995
+ pop: () => {
14996
+ Keyboard2.dismiss();
14997
+ pop();
14998
+ },
14999
+ replace: (screen) => {
15000
+ Keyboard2.dismiss();
15001
+ replace(screen);
15002
+ },
15003
+ reset: () => {
15004
+ Keyboard2.dismiss();
15005
+ reset();
15006
+ },
15007
+ canGoBack,
15008
+ closeWidget: handleClose
15009
+ };
14849
15010
  const renderScreen = () => {
14850
15011
  switch (currentScreen.name) {
14851
15012
  case "HOME":
@@ -14902,7 +15063,7 @@ function BugBearButton({
14902
15063
  behavior: Platform4.OS === "ios" ? "padding" : "height",
14903
15064
  style: styles13.modalOverlay
14904
15065
  },
14905
- /* @__PURE__ */ React14.createElement(View13, { style: styles13.modalContainer }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.header }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerLeft }, canGoBack ? /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: pop, style: styles13.backButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.backText }, "\u2190 Back")) : /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerTitleRow }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerTitle }, "BugBear"), testerInfo && /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => push({ name: "PROFILE" }) }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerName }, testerInfo.name, " \u270E")))), getHeaderTitle() ? /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerScreenTitle, numberOfLines: 1 }, getHeaderTitle()) : null, /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: handleClose, style: styles13.closeButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.closeText }, "\u2715"))), /* @__PURE__ */ React14.createElement(
15066
+ /* @__PURE__ */ React14.createElement(View13, { style: styles13.modalContainer }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.header }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerLeft }, canGoBack ? /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerNavRow }, /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => nav.pop(), style: styles13.backButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.backText }, "\u2190 Back")), /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => nav.reset(), style: styles13.homeButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.homeText }, "\u{1F3E0}"))) : /* @__PURE__ */ React14.createElement(View13, { style: styles13.headerTitleRow }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerTitle }, "BugBear"), testerInfo && /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => push({ name: "PROFILE" }) }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerName }, testerInfo.name, " \u270E")))), getHeaderTitle() ? /* @__PURE__ */ React14.createElement(Text13, { style: styles13.headerScreenTitle, numberOfLines: 1 }, getHeaderTitle()) : null, /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: handleClose, style: styles13.closeButton }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.closeText }, "\u2715"))), /* @__PURE__ */ React14.createElement(
14906
15067
  ScrollView2,
14907
15068
  {
14908
15069
  style: styles13.content,
@@ -15003,15 +15164,27 @@ var styles13 = StyleSheet14.create({
15003
15164
  flex: 1,
15004
15165
  textAlign: "center"
15005
15166
  },
15167
+ headerNavRow: {
15168
+ flexDirection: "row",
15169
+ alignItems: "center",
15170
+ gap: 8
15171
+ },
15006
15172
  backButton: {
15007
15173
  paddingVertical: 2,
15008
- paddingRight: 12
15174
+ paddingRight: 4
15009
15175
  },
15010
15176
  backText: {
15011
15177
  fontSize: 15,
15012
15178
  color: colors.blue,
15013
15179
  fontWeight: "500"
15014
15180
  },
15181
+ homeButton: {
15182
+ paddingVertical: 2,
15183
+ paddingHorizontal: 6
15184
+ },
15185
+ homeText: {
15186
+ fontSize: 16
15187
+ },
15015
15188
  closeButton: {
15016
15189
  width: 32,
15017
15190
  height: 32,