@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.js CHANGED
@@ -11392,6 +11392,239 @@ function shouldShowDeprecationWarning() {
11392
11392
  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");
11393
11393
 
11394
11394
  // ../core/dist/index.mjs
11395
+ var MAX_CONSOLE_LOGS = 50;
11396
+ var MAX_NETWORK_REQUESTS = 20;
11397
+ var MAX_NAVIGATION_HISTORY = 20;
11398
+ var MAX_RESPONSE_BODY_LENGTH = 500;
11399
+ var ContextCaptureManager = class {
11400
+ constructor() {
11401
+ this.consoleLogs = [];
11402
+ this.networkRequests = [];
11403
+ this.navigationHistory = [];
11404
+ this.originalConsole = {};
11405
+ this.isCapturing = false;
11406
+ }
11407
+ /**
11408
+ * Start capturing console logs, network requests, and navigation
11409
+ */
11410
+ startCapture() {
11411
+ if (this.isCapturing) return;
11412
+ this.isCapturing = true;
11413
+ this.captureConsole();
11414
+ this.captureFetch();
11415
+ this.captureNavigation();
11416
+ }
11417
+ /**
11418
+ * Stop capturing and restore original functions
11419
+ */
11420
+ stopCapture() {
11421
+ if (!this.isCapturing) return;
11422
+ this.isCapturing = false;
11423
+ if (this.originalConsole.log) console.log = this.originalConsole.log;
11424
+ if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
11425
+ if (this.originalConsole.error) console.error = this.originalConsole.error;
11426
+ if (this.originalConsole.info) console.info = this.originalConsole.info;
11427
+ if (this.originalFetch && typeof window !== "undefined") {
11428
+ window.fetch = this.originalFetch;
11429
+ }
11430
+ if (typeof window !== "undefined" && typeof history !== "undefined") {
11431
+ if (this.originalPushState) {
11432
+ history.pushState = this.originalPushState;
11433
+ }
11434
+ if (this.originalReplaceState) {
11435
+ history.replaceState = this.originalReplaceState;
11436
+ }
11437
+ if (this.popstateHandler) {
11438
+ window.removeEventListener("popstate", this.popstateHandler);
11439
+ }
11440
+ }
11441
+ }
11442
+ /**
11443
+ * Get captured context for a bug report
11444
+ */
11445
+ getEnhancedContext() {
11446
+ return {
11447
+ consoleLogs: [...this.consoleLogs],
11448
+ networkRequests: [...this.networkRequests],
11449
+ navigationHistory: [...this.navigationHistory],
11450
+ performanceMetrics: this.getPerformanceMetrics(),
11451
+ environment: this.getEnvironmentInfo()
11452
+ };
11453
+ }
11454
+ /**
11455
+ * Get the auto-captured navigation history
11456
+ */
11457
+ getNavigationHistory() {
11458
+ return [...this.navigationHistory];
11459
+ }
11460
+ /**
11461
+ * Get the current route (last entry in navigation history, or window.location)
11462
+ */
11463
+ getCurrentRoute() {
11464
+ if (this.navigationHistory.length > 0) {
11465
+ return this.navigationHistory[this.navigationHistory.length - 1];
11466
+ }
11467
+ if (typeof window !== "undefined") {
11468
+ return window.location.pathname;
11469
+ }
11470
+ return "unknown";
11471
+ }
11472
+ /**
11473
+ * Manually track a navigation event (for React Native or custom routing)
11474
+ */
11475
+ trackNavigation(route) {
11476
+ const last = this.navigationHistory[this.navigationHistory.length - 1];
11477
+ if (route === last) return;
11478
+ this.navigationHistory.push(route);
11479
+ if (this.navigationHistory.length > MAX_NAVIGATION_HISTORY) {
11480
+ this.navigationHistory.shift();
11481
+ }
11482
+ }
11483
+ /**
11484
+ * Clear captured data
11485
+ */
11486
+ clear() {
11487
+ this.consoleLogs = [];
11488
+ this.networkRequests = [];
11489
+ this.navigationHistory = [];
11490
+ }
11491
+ /**
11492
+ * Add a log entry manually (for custom logging)
11493
+ */
11494
+ addLog(level, message, args) {
11495
+ this.consoleLogs.push({
11496
+ level,
11497
+ message,
11498
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11499
+ args
11500
+ });
11501
+ if (this.consoleLogs.length > MAX_CONSOLE_LOGS) {
11502
+ this.consoleLogs = this.consoleLogs.slice(-MAX_CONSOLE_LOGS);
11503
+ }
11504
+ }
11505
+ /**
11506
+ * Add a network request manually
11507
+ */
11508
+ addNetworkRequest(request) {
11509
+ this.networkRequests.push(request);
11510
+ if (this.networkRequests.length > MAX_NETWORK_REQUESTS) {
11511
+ this.networkRequests = this.networkRequests.slice(-MAX_NETWORK_REQUESTS);
11512
+ }
11513
+ }
11514
+ captureConsole() {
11515
+ if (typeof console === "undefined") return;
11516
+ const levels = ["log", "warn", "error", "info"];
11517
+ levels.forEach((level) => {
11518
+ this.originalConsole[level] = console[level];
11519
+ console[level] = (...args) => {
11520
+ this.originalConsole[level]?.apply(console, args);
11521
+ try {
11522
+ const message = args.map((arg) => {
11523
+ if (typeof arg === "string") return arg;
11524
+ try {
11525
+ return JSON.stringify(arg);
11526
+ } catch {
11527
+ return String(arg);
11528
+ }
11529
+ }).join(" ");
11530
+ this.addLog(level, message.slice(0, 500));
11531
+ } catch {
11532
+ }
11533
+ };
11534
+ });
11535
+ }
11536
+ captureFetch() {
11537
+ if (typeof window === "undefined" || typeof fetch === "undefined") return;
11538
+ this.originalFetch = window.fetch;
11539
+ const self2 = this;
11540
+ window.fetch = async function(input, init) {
11541
+ const startTime = Date.now();
11542
+ const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
11543
+ const method = init?.method || "GET";
11544
+ try {
11545
+ const response = await self2.originalFetch.call(window, input, init);
11546
+ const requestEntry = {
11547
+ method,
11548
+ url: url.slice(0, 200),
11549
+ // Limit URL length
11550
+ status: response.status,
11551
+ duration: Date.now() - startTime,
11552
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
11553
+ };
11554
+ if (response.status >= 400) {
11555
+ try {
11556
+ const cloned = response.clone();
11557
+ const body = await cloned.text();
11558
+ if (body) {
11559
+ requestEntry.responseBody = body.slice(0, MAX_RESPONSE_BODY_LENGTH);
11560
+ }
11561
+ } catch {
11562
+ }
11563
+ }
11564
+ self2.addNetworkRequest(requestEntry);
11565
+ return response;
11566
+ } catch (error) {
11567
+ self2.addNetworkRequest({
11568
+ method,
11569
+ url: url.slice(0, 200),
11570
+ duration: Date.now() - startTime,
11571
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11572
+ error: error instanceof Error ? error.message : "Unknown error"
11573
+ });
11574
+ throw error;
11575
+ }
11576
+ };
11577
+ }
11578
+ captureNavigation() {
11579
+ if (typeof window === "undefined" || typeof history === "undefined") return;
11580
+ this.trackNavigation(window.location.pathname);
11581
+ const self2 = this;
11582
+ this.originalPushState = history.pushState;
11583
+ history.pushState = function(...args) {
11584
+ self2.originalPushState.apply(history, args);
11585
+ self2.trackNavigation(window.location.pathname);
11586
+ };
11587
+ this.originalReplaceState = history.replaceState;
11588
+ history.replaceState = function(...args) {
11589
+ self2.originalReplaceState.apply(history, args);
11590
+ self2.trackNavigation(window.location.pathname);
11591
+ };
11592
+ this.popstateHandler = () => {
11593
+ self2.trackNavigation(window.location.pathname);
11594
+ };
11595
+ window.addEventListener("popstate", this.popstateHandler);
11596
+ }
11597
+ getPerformanceMetrics() {
11598
+ if (typeof window === "undefined" || typeof performance === "undefined") return void 0;
11599
+ const metrics = {};
11600
+ try {
11601
+ const navigation = performance.getEntriesByType("navigation")[0];
11602
+ if (navigation) {
11603
+ metrics.pageLoadTime = Math.round(navigation.loadEventEnd - navigation.startTime);
11604
+ }
11605
+ } catch {
11606
+ }
11607
+ try {
11608
+ const memory = performance.memory;
11609
+ if (memory) {
11610
+ metrics.memoryUsage = Math.round(memory.usedJSHeapSize / 1024 / 1024);
11611
+ }
11612
+ } catch {
11613
+ }
11614
+ return Object.keys(metrics).length > 0 ? metrics : void 0;
11615
+ }
11616
+ getEnvironmentInfo() {
11617
+ if (typeof window === "undefined" || typeof navigator === "undefined") return void 0;
11618
+ return {
11619
+ language: navigator.language,
11620
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
11621
+ cookiesEnabled: navigator.cookieEnabled,
11622
+ localStorage: typeof localStorage !== "undefined",
11623
+ online: navigator.onLine
11624
+ };
11625
+ }
11626
+ };
11627
+ var contextCapture = new ContextCaptureManager();
11395
11628
  var DEFAULT_SUPABASE_URL = "https://kyxgzjnqgvapvlnvqawz.supabase.co";
11396
11629
  var getEnvVar = (key) => {
11397
11630
  try {
@@ -11413,22 +11646,40 @@ var BugBearClient = class {
11413
11646
  );
11414
11647
  }
11415
11648
  /**
11416
- * Track navigation for context
11649
+ * Track navigation for context.
11650
+ * Also forwards to contextCapture for auto-tracked navigation.
11417
11651
  */
11418
11652
  trackNavigation(route) {
11419
11653
  this.navigationHistory.push(route);
11420
11654
  if (this.navigationHistory.length > 10) {
11421
11655
  this.navigationHistory.shift();
11422
11656
  }
11657
+ contextCapture.trackNavigation(route);
11423
11658
  }
11424
11659
  /**
11425
- * Get current navigation history
11660
+ * Get current navigation history.
11661
+ * Priority: config callback > manual tracking > auto-captured (pushState/popstate)
11426
11662
  */
11427
11663
  getNavigationHistory() {
11428
11664
  if (this.config.getNavigationHistory) {
11429
11665
  return this.config.getNavigationHistory();
11430
11666
  }
11431
- return [...this.navigationHistory];
11667
+ if (this.navigationHistory.length > 0) {
11668
+ return [...this.navigationHistory];
11669
+ }
11670
+ return contextCapture.getNavigationHistory();
11671
+ }
11672
+ /**
11673
+ * Get current app context.
11674
+ * Uses config.getAppContext() callback if provided, otherwise builds from available data.
11675
+ */
11676
+ getAppContext() {
11677
+ if (this.config.getAppContext) {
11678
+ return this.config.getAppContext();
11679
+ }
11680
+ return {
11681
+ currentRoute: contextCapture.getCurrentRoute()
11682
+ };
11432
11683
  }
11433
11684
  /**
11434
11685
  * Get current user info from host app or BugBear's own auth
@@ -11468,6 +11719,8 @@ var BugBearClient = class {
11468
11719
  project_id: this.config.projectId,
11469
11720
  reporter_id: userInfo.id,
11470
11721
  // User ID from host app (required)
11722
+ reporter_name: testerInfo?.name || userInfo.name || null,
11723
+ reporter_email: userInfo.email || null,
11471
11724
  tester_id: testerInfo?.id || null,
11472
11725
  // Tester record ID (optional)
11473
11726
  report_type: report.type,
@@ -11481,6 +11734,7 @@ var BugBearClient = class {
11481
11734
  app_context: report.appContext,
11482
11735
  device_info: report.deviceInfo || this.getDeviceInfo(),
11483
11736
  navigation_history: this.getNavigationHistory(),
11737
+ enhanced_context: report.enhancedContext || contextCapture.getEnhancedContext(),
11484
11738
  assignment_id: report.assignmentId,
11485
11739
  test_case_id: report.testCaseId
11486
11740
  };
@@ -11728,19 +11982,40 @@ var BugBearClient = class {
11728
11982
  return { success: false, error: message };
11729
11983
  }
11730
11984
  }
11985
+ /**
11986
+ * Pass a test assignment — convenience wrapper around updateAssignmentStatus
11987
+ */
11988
+ async passAssignment(assignmentId) {
11989
+ return this.updateAssignmentStatus(assignmentId, "passed");
11990
+ }
11991
+ /**
11992
+ * Fail a test assignment — convenience wrapper around updateAssignmentStatus
11993
+ */
11994
+ async failAssignment(assignmentId) {
11995
+ return this.updateAssignmentStatus(assignmentId, "failed");
11996
+ }
11731
11997
  /**
11732
11998
  * Skip a test assignment with a required reason
11733
11999
  * Marks the assignment as 'skipped' and records why it was skipped
11734
12000
  */
11735
12001
  async skipAssignment(assignmentId, reason, notes) {
12002
+ let actualReason;
12003
+ let actualNotes;
12004
+ if (typeof reason === "object") {
12005
+ actualReason = reason.reason;
12006
+ actualNotes = reason.notes;
12007
+ } else {
12008
+ actualReason = reason;
12009
+ actualNotes = notes;
12010
+ }
11736
12011
  try {
11737
12012
  const updateData = {
11738
12013
  status: "skipped",
11739
- skip_reason: reason,
12014
+ skip_reason: actualReason,
11740
12015
  completed_at: (/* @__PURE__ */ new Date()).toISOString()
11741
12016
  };
11742
- if (notes) {
11743
- updateData.notes = notes;
12017
+ if (actualNotes) {
12018
+ updateData.notes = actualNotes;
11744
12019
  }
11745
12020
  const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11746
12021
  if (error) {
@@ -12714,163 +12989,6 @@ var BugBearClient = class {
12714
12989
  function createBugBear(config) {
12715
12990
  return new BugBearClient(config);
12716
12991
  }
12717
- var MAX_CONSOLE_LOGS = 50;
12718
- var MAX_NETWORK_REQUESTS = 20;
12719
- var ContextCaptureManager = class {
12720
- constructor() {
12721
- this.consoleLogs = [];
12722
- this.networkRequests = [];
12723
- this.originalConsole = {};
12724
- this.isCapturing = false;
12725
- }
12726
- /**
12727
- * Start capturing console logs and network requests
12728
- */
12729
- startCapture() {
12730
- if (this.isCapturing) return;
12731
- this.isCapturing = true;
12732
- this.captureConsole();
12733
- this.captureFetch();
12734
- }
12735
- /**
12736
- * Stop capturing and restore original functions
12737
- */
12738
- stopCapture() {
12739
- if (!this.isCapturing) return;
12740
- this.isCapturing = false;
12741
- if (this.originalConsole.log) console.log = this.originalConsole.log;
12742
- if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
12743
- if (this.originalConsole.error) console.error = this.originalConsole.error;
12744
- if (this.originalConsole.info) console.info = this.originalConsole.info;
12745
- if (this.originalFetch && typeof window !== "undefined") {
12746
- window.fetch = this.originalFetch;
12747
- }
12748
- }
12749
- /**
12750
- * Get captured context for a bug report
12751
- */
12752
- getEnhancedContext() {
12753
- return {
12754
- consoleLogs: [...this.consoleLogs],
12755
- networkRequests: [...this.networkRequests],
12756
- performanceMetrics: this.getPerformanceMetrics(),
12757
- environment: this.getEnvironmentInfo()
12758
- };
12759
- }
12760
- /**
12761
- * Clear captured data
12762
- */
12763
- clear() {
12764
- this.consoleLogs = [];
12765
- this.networkRequests = [];
12766
- }
12767
- /**
12768
- * Add a log entry manually (for custom logging)
12769
- */
12770
- addLog(level, message, args) {
12771
- this.consoleLogs.push({
12772
- level,
12773
- message,
12774
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12775
- args
12776
- });
12777
- if (this.consoleLogs.length > MAX_CONSOLE_LOGS) {
12778
- this.consoleLogs = this.consoleLogs.slice(-MAX_CONSOLE_LOGS);
12779
- }
12780
- }
12781
- /**
12782
- * Add a network request manually
12783
- */
12784
- addNetworkRequest(request) {
12785
- this.networkRequests.push(request);
12786
- if (this.networkRequests.length > MAX_NETWORK_REQUESTS) {
12787
- this.networkRequests = this.networkRequests.slice(-MAX_NETWORK_REQUESTS);
12788
- }
12789
- }
12790
- captureConsole() {
12791
- if (typeof console === "undefined") return;
12792
- const levels = ["log", "warn", "error", "info"];
12793
- levels.forEach((level) => {
12794
- this.originalConsole[level] = console[level];
12795
- console[level] = (...args) => {
12796
- this.originalConsole[level]?.apply(console, args);
12797
- try {
12798
- const message = args.map((arg) => {
12799
- if (typeof arg === "string") return arg;
12800
- try {
12801
- return JSON.stringify(arg);
12802
- } catch {
12803
- return String(arg);
12804
- }
12805
- }).join(" ");
12806
- this.addLog(level, message.slice(0, 500));
12807
- } catch {
12808
- }
12809
- };
12810
- });
12811
- }
12812
- captureFetch() {
12813
- if (typeof window === "undefined" || typeof fetch === "undefined") return;
12814
- this.originalFetch = window.fetch;
12815
- const self2 = this;
12816
- window.fetch = async function(input, init) {
12817
- const startTime = Date.now();
12818
- const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
12819
- const method = init?.method || "GET";
12820
- try {
12821
- const response = await self2.originalFetch.call(window, input, init);
12822
- self2.addNetworkRequest({
12823
- method,
12824
- url: url.slice(0, 200),
12825
- // Limit URL length
12826
- status: response.status,
12827
- duration: Date.now() - startTime,
12828
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
12829
- });
12830
- return response;
12831
- } catch (error) {
12832
- self2.addNetworkRequest({
12833
- method,
12834
- url: url.slice(0, 200),
12835
- duration: Date.now() - startTime,
12836
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12837
- error: error instanceof Error ? error.message : "Unknown error"
12838
- });
12839
- throw error;
12840
- }
12841
- };
12842
- }
12843
- getPerformanceMetrics() {
12844
- if (typeof window === "undefined" || typeof performance === "undefined") return void 0;
12845
- const metrics = {};
12846
- try {
12847
- const navigation = performance.getEntriesByType("navigation")[0];
12848
- if (navigation) {
12849
- metrics.pageLoadTime = Math.round(navigation.loadEventEnd - navigation.startTime);
12850
- }
12851
- } catch {
12852
- }
12853
- try {
12854
- const memory = performance.memory;
12855
- if (memory) {
12856
- metrics.memoryUsage = Math.round(memory.usedJSHeapSize / 1024 / 1024);
12857
- }
12858
- } catch {
12859
- }
12860
- return Object.keys(metrics).length > 0 ? metrics : void 0;
12861
- }
12862
- getEnvironmentInfo() {
12863
- if (typeof window === "undefined" || typeof navigator === "undefined") return void 0;
12864
- return {
12865
- language: navigator.language,
12866
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
12867
- cookiesEnabled: navigator.cookieEnabled,
12868
- localStorage: typeof localStorage !== "undefined",
12869
- online: navigator.onLine
12870
- };
12871
- }
12872
- };
12873
- var contextCapture = new ContextCaptureManager();
12874
12992
 
12875
12993
  // src/BugBearProvider.tsx
12876
12994
  var import_react_native = require("react-native");
@@ -13071,6 +13189,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
13071
13189
  (0, import_react.useEffect)(() => {
13072
13190
  if (enabled && !hasInitialized.current) {
13073
13191
  hasInitialized.current = true;
13192
+ contextCapture.startCapture();
13074
13193
  const newClient = createBugBear(config);
13075
13194
  setClient(newClient);
13076
13195
  initializeBugBear(newClient);
@@ -13380,7 +13499,7 @@ function HomeScreen({ nav }) {
13380
13499
  import_react_native3.TouchableOpacity,
13381
13500
  {
13382
13501
  style: styles.actionCard,
13383
- onPress: () => nav.push({ name: "TEST_DETAIL" }),
13502
+ onPress: () => nav.push({ name: "TEST_LIST" }),
13384
13503
  activeOpacity: 0.7
13385
13504
  },
13386
13505
  /* @__PURE__ */ import_react3.default.createElement(import_react_native3.Text, { style: styles.actionIcon }, "\u2705"),
@@ -13648,12 +13767,14 @@ function TestDetailScreen({ testId, nav }) {
13648
13767
  const currentIndex = displayedAssignment ? assignments.indexOf(displayedAssignment) : -1;
13649
13768
  const handlePass = (0, import_react4.useCallback)(async () => {
13650
13769
  if (!client || !displayedAssignment) return;
13770
+ import_react_native4.Keyboard.dismiss();
13651
13771
  await client.passAssignment(displayedAssignment.id);
13652
13772
  await refreshAssignments();
13653
13773
  nav.replace({ name: "TEST_FEEDBACK", status: "passed", assignmentId: displayedAssignment.id });
13654
13774
  }, [client, displayedAssignment, refreshAssignments, nav]);
13655
13775
  const handleFail = (0, import_react4.useCallback)(async () => {
13656
13776
  if (!client || !displayedAssignment) return;
13777
+ import_react_native4.Keyboard.dismiss();
13657
13778
  await client.failAssignment(displayedAssignment.id);
13658
13779
  await refreshAssignments();
13659
13780
  nav.replace({
@@ -13667,6 +13788,7 @@ function TestDetailScreen({ testId, nav }) {
13667
13788
  }, [client, displayedAssignment, refreshAssignments, nav]);
13668
13789
  const handleSkip = (0, import_react4.useCallback)(async () => {
13669
13790
  if (!client || !displayedAssignment || !selectedSkipReason) return;
13791
+ import_react_native4.Keyboard.dismiss();
13670
13792
  setSkipping(true);
13671
13793
  await client.skipAssignment(displayedAssignment.id, {
13672
13794
  reason: selectedSkipReason,
@@ -13735,7 +13857,9 @@ function TestDetailScreen({ testId, nav }) {
13735
13857
  {
13736
13858
  style: styles2.navigateButton,
13737
13859
  onPress: () => {
13860
+ import_react_native4.Keyboard.dismiss();
13738
13861
  onNavigate(testCase.targetRoute);
13862
+ nav.closeWidget?.();
13739
13863
  }
13740
13864
  },
13741
13865
  /* @__PURE__ */ import_react4.default.createElement(import_react_native4.Text, { style: styles2.navigateText }, "\u{1F9ED} Go to test location")
@@ -14296,12 +14420,18 @@ function ReportScreen({ nav, prefill }) {
14296
14420
  const [reportType, setReportType] = (0, import_react10.useState)(prefill?.type || "bug");
14297
14421
  const [severity, setSeverity] = (0, import_react10.useState)("medium");
14298
14422
  const [description, setDescription] = (0, import_react10.useState)("");
14423
+ const [affectedScreen, setAffectedScreen] = (0, import_react10.useState)("");
14299
14424
  const [submitting, setSubmitting] = (0, import_react10.useState)(false);
14300
14425
  const images = useImageAttachments(uploadImage, 5, "screenshots");
14301
14426
  const isBugType = reportType === "bug" || reportType === "test_fail";
14302
14427
  const handleSubmit = async () => {
14303
14428
  if (!client || !description.trim()) return;
14304
14429
  setSubmitting(true);
14430
+ const baseContext = client.getAppContext();
14431
+ const appContext = {
14432
+ ...baseContext,
14433
+ currentRoute: affectedScreen.trim() || baseContext.currentRoute
14434
+ };
14305
14435
  const screenshotUrls = images.getScreenshotUrls();
14306
14436
  await client.submitReport({
14307
14437
  type: reportType,
@@ -14309,7 +14439,7 @@ function ReportScreen({ nav, prefill }) {
14309
14439
  severity: isBugType ? severity : void 0,
14310
14440
  assignmentId: prefill?.assignmentId,
14311
14441
  testCaseId: prefill?.testCaseId,
14312
- appContext: { currentRoute: "unknown" },
14442
+ appContext,
14313
14443
  deviceInfo: getDeviceInfo(),
14314
14444
  screenshots: screenshotUrls.length > 0 ? screenshotUrls : void 0
14315
14445
  });
@@ -14357,7 +14487,16 @@ function ReportScreen({ nav, prefill }) {
14357
14487
  numberOfLines: 4,
14358
14488
  textAlignVertical: "top"
14359
14489
  }
14360
- )), /* @__PURE__ */ import_react10.default.createElement(
14490
+ )), isBugType && /* @__PURE__ */ import_react10.default.createElement(import_react_native9.View, { style: styles7.section }, /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: shared.label }, "Which screen?"), /* @__PURE__ */ import_react10.default.createElement(
14491
+ import_react_native9.TextInput,
14492
+ {
14493
+ style: styles7.screenInput,
14494
+ value: affectedScreen,
14495
+ onChangeText: setAffectedScreen,
14496
+ placeholder: "e.g. Reservations, Settings...",
14497
+ placeholderTextColor: colors.textMuted
14498
+ }
14499
+ ), /* @__PURE__ */ import_react10.default.createElement(import_react_native9.Text, { style: styles7.screenHint }, "Which screen or area was the bug on? (optional)")), /* @__PURE__ */ import_react10.default.createElement(
14361
14500
  ImagePickerButtons,
14362
14501
  {
14363
14502
  images: images.images,
@@ -14388,7 +14527,9 @@ var styles7 = import_react_native9.StyleSheet.create({
14388
14527
  severityRow: { flexDirection: "row", gap: 8 },
14389
14528
  sevButton: { flex: 1, paddingVertical: 8, borderRadius: 8, alignItems: "center", borderWidth: 1, borderColor: colors.border, backgroundColor: colors.card },
14390
14529
  sevText: { fontSize: 12, fontWeight: "500", color: colors.textSecondary, textTransform: "capitalize" },
14391
- descInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, fontSize: 14, color: colors.textPrimary, minHeight: 100 }
14530
+ descInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, fontSize: 14, color: colors.textPrimary, minHeight: 100 },
14531
+ screenInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 8, paddingHorizontal: 12, paddingVertical: 8, fontSize: 13, color: colors.textPrimary },
14532
+ screenHint: { fontSize: 11, color: colors.textMuted, marginTop: 4 }
14392
14533
  });
14393
14534
 
14394
14535
  // src/widget/screens/ReportSuccessScreen.tsx
@@ -14859,10 +15000,29 @@ function BugBearButton({
14859
15000
  }
14860
15001
  };
14861
15002
  const handleClose = () => {
15003
+ import_react_native15.Keyboard.dismiss();
14862
15004
  setModalVisible(false);
14863
- reset();
14864
15005
  };
14865
- const nav = { push, pop, replace, reset, canGoBack };
15006
+ const nav = {
15007
+ push: (screen) => {
15008
+ import_react_native15.Keyboard.dismiss();
15009
+ push(screen);
15010
+ },
15011
+ pop: () => {
15012
+ import_react_native15.Keyboard.dismiss();
15013
+ pop();
15014
+ },
15015
+ replace: (screen) => {
15016
+ import_react_native15.Keyboard.dismiss();
15017
+ replace(screen);
15018
+ },
15019
+ reset: () => {
15020
+ import_react_native15.Keyboard.dismiss();
15021
+ reset();
15022
+ },
15023
+ canGoBack,
15024
+ closeWidget: handleClose
15025
+ };
14866
15026
  const renderScreen = () => {
14867
15027
  switch (currentScreen.name) {
14868
15028
  case "HOME":
@@ -14919,7 +15079,7 @@ function BugBearButton({
14919
15079
  behavior: import_react_native15.Platform.OS === "ios" ? "padding" : "height",
14920
15080
  style: styles13.modalOverlay
14921
15081
  },
14922
- /* @__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.TouchableOpacity, { onPress: 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.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(
15082
+ /* @__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(
14923
15083
  import_react_native15.ScrollView,
14924
15084
  {
14925
15085
  style: styles13.content,
@@ -15020,15 +15180,27 @@ var styles13 = import_react_native15.StyleSheet.create({
15020
15180
  flex: 1,
15021
15181
  textAlign: "center"
15022
15182
  },
15183
+ headerNavRow: {
15184
+ flexDirection: "row",
15185
+ alignItems: "center",
15186
+ gap: 8
15187
+ },
15023
15188
  backButton: {
15024
15189
  paddingVertical: 2,
15025
- paddingRight: 12
15190
+ paddingRight: 4
15026
15191
  },
15027
15192
  backText: {
15028
15193
  fontSize: 15,
15029
15194
  color: colors.blue,
15030
15195
  fontWeight: "500"
15031
15196
  },
15197
+ homeButton: {
15198
+ paddingVertical: 2,
15199
+ paddingHorizontal: 6
15200
+ },
15201
+ homeText: {
15202
+ fontSize: 16
15203
+ },
15032
15204
  closeButton: {
15033
15205
  width: 32,
15034
15206
  height: 32,