@bbearai/react-native 0.8.0 → 0.8.1

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
@@ -13425,12 +13425,56 @@ var BugBearClient = class {
13425
13425
  return true;
13426
13426
  }
13427
13427
  }
13428
+ /**
13429
+ * Fetch server-side widget config set by the project admin.
13430
+ * Returns settings like color scheme override. Returns empty config on error.
13431
+ */
13432
+ async getWidgetConfig() {
13433
+ try {
13434
+ await this.ensureReady();
13435
+ const { data, error } = await this.supabase.rpc("get_widget_config", {
13436
+ p_project_id: this.config.projectId
13437
+ });
13438
+ if (error) {
13439
+ console.warn("BugBear: Could not fetch widget config", error.message || error.code || "Unknown error");
13440
+ return {};
13441
+ }
13442
+ return data ?? {};
13443
+ } catch (err) {
13444
+ const message = err instanceof Error ? err.message : "Unknown error fetching widget config";
13445
+ console.error("BugBear: Error fetching widget config", err);
13446
+ this.config.onError?.(err instanceof Error ? err : new Error(message), { projectId: this.config.projectId });
13447
+ return {};
13448
+ }
13449
+ }
13450
+ /**
13451
+ * Check if feedback mode is enabled for this project.
13452
+ * This is a master switch that admins can toggle in the dashboard.
13453
+ */
13454
+ async isFeedbackEnabled() {
13455
+ try {
13456
+ await this.ensureReady();
13457
+ const { data, error } = await this.supabase.rpc("check_feedback_enabled", {
13458
+ p_project_id: this.config.projectId
13459
+ });
13460
+ if (error) {
13461
+ console.warn("BugBear: Could not check feedback status", error.message || error.code || "Unknown error");
13462
+ return false;
13463
+ }
13464
+ return data ?? false;
13465
+ } catch (err) {
13466
+ const message = err instanceof Error ? err.message : "Unknown error checking feedback status";
13467
+ console.error("BugBear: Error checking feedback status", err);
13468
+ this.config.onError?.(err instanceof Error ? err : new Error(message), { projectId: this.config.projectId });
13469
+ return false;
13470
+ }
13471
+ }
13428
13472
  /**
13429
13473
  * Check if the widget should be visible.
13430
13474
  * Behavior depends on the configured mode:
13431
13475
  * - 'qa': QA enabled AND user is a registered tester
13432
- * - 'feedback': Any authenticated user
13433
- * - 'auto': Either QA tester OR authenticated non-tester
13476
+ * - 'feedback': Feedback enabled AND user is authenticated
13477
+ * - 'auto': QA tester (if QA enabled) OR authenticated user (if feedback enabled)
13434
13478
  */
13435
13479
  async shouldShowWidget() {
13436
13480
  const mode = this.config.mode || "qa";
@@ -13442,33 +13486,39 @@ var BugBearClient = class {
13442
13486
  return qaEnabled2 && tester;
13443
13487
  }
13444
13488
  if (mode === "feedback") {
13445
- const userInfo2 = await this.getCurrentUserInfo();
13446
- return userInfo2 !== null;
13489
+ const [feedbackEnabled2, userInfo2] = await Promise.all([
13490
+ this.isFeedbackEnabled(),
13491
+ this.getCurrentUserInfo()
13492
+ ]);
13493
+ return feedbackEnabled2 && userInfo2 !== null;
13447
13494
  }
13448
- const [qaEnabled, testerInfo, userInfo] = await Promise.all([
13495
+ const [qaEnabled, feedbackEnabled, testerInfo, userInfo] = await Promise.all([
13449
13496
  this.isQAEnabled(),
13497
+ this.isFeedbackEnabled(),
13450
13498
  this.getTesterInfo(),
13451
13499
  this.getCurrentUserInfo()
13452
13500
  ]);
13453
13501
  if (qaEnabled && testerInfo && testerInfo.role !== "feedback") return true;
13454
- if (userInfo) return true;
13502
+ if (feedbackEnabled && userInfo) return true;
13455
13503
  return false;
13456
13504
  }
13457
13505
  /**
13458
13506
  * Resolve the effective widget mode for the current user.
13459
13507
  * - 'qa' or 'feedback' config → returned as-is
13460
- * - 'auto' → checks if user is a QA tester (role='tester') → 'qa', otherwise 'feedback'
13508
+ * - 'auto' → QA tester with QA enabled 'qa', feedback enabled → 'feedback', else 'qa'
13461
13509
  */
13462
13510
  async getEffectiveMode() {
13463
13511
  const mode = this.config.mode || "qa";
13464
13512
  if (mode === "qa") return "qa";
13465
13513
  if (mode === "feedback") return "feedback";
13466
- const [qaEnabled, testerInfo] = await Promise.all([
13514
+ const [qaEnabled, feedbackEnabled, testerInfo] = await Promise.all([
13467
13515
  this.isQAEnabled(),
13516
+ this.isFeedbackEnabled(),
13468
13517
  this.getTesterInfo()
13469
13518
  ]);
13470
13519
  if (qaEnabled && testerInfo && testerInfo.role !== "feedback") return "qa";
13471
- return "feedback";
13520
+ if (feedbackEnabled) return "feedback";
13521
+ return "qa";
13472
13522
  }
13473
13523
  /**
13474
13524
  * Auto-provision a feedback user record in the testers table.
@@ -14471,6 +14521,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
14471
14521
  const [client, setClient] = (0, import_react.useState)(null);
14472
14522
  const [isTester, setIsTester] = (0, import_react.useState)(false);
14473
14523
  const [isQAEnabled, setIsQAEnabled] = (0, import_react.useState)(false);
14524
+ const [isFeedbackEnabled, setIsFeedbackEnabled] = (0, import_react.useState)(false);
14474
14525
  const [testerInfo, setTesterInfo] = (0, import_react.useState)(null);
14475
14526
  const [assignments, setAssignments] = (0, import_react.useState)([]);
14476
14527
  const [isLoading, setIsLoading] = (0, import_react.useState)(true);
@@ -14484,7 +14535,9 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
14484
14535
  const hasInitialized = (0, import_react.useRef)(false);
14485
14536
  const monitorHandlersRef = (0, import_react.useRef)([]);
14486
14537
  const rageClickRef = (0, import_react.useRef)(null);
14487
- const configColorScheme = config.theme?.colorScheme ?? "dark";
14538
+ const devColorScheme = config.theme?.colorScheme ?? "auto";
14539
+ const [serverColorScheme, setServerColorScheme] = (0, import_react.useState)(null);
14540
+ const configColorScheme = serverColorScheme ?? (devColorScheme === "auto" ? "auto" : devColorScheme);
14488
14541
  const [activeScheme, setActiveScheme] = (0, import_react.useState)(() => {
14489
14542
  if (configColorScheme !== "auto") return configColorScheme;
14490
14543
  return import_react_native2.Appearance.getColorScheme() === "light" ? "light" : "dark";
@@ -14601,16 +14654,22 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
14601
14654
  const initializeBugBear = (0, import_react.useCallback)(async (bugBearClient) => {
14602
14655
  setIsLoading(true);
14603
14656
  try {
14604
- const [effectiveMode, qaEnabled, info] = await Promise.all([
14657
+ const [effectiveMode, qaEnabled, feedbackEnabled, info, widgetConfig] = await Promise.all([
14605
14658
  bugBearClient.getEffectiveMode(),
14606
14659
  bugBearClient.isQAEnabled(),
14607
- bugBearClient.getTesterInfo()
14660
+ bugBearClient.isFeedbackEnabled(),
14661
+ bugBearClient.getTesterInfo(),
14662
+ bugBearClient.getWidgetConfig()
14608
14663
  ]);
14609
- console.log("BugBear: Init complete", { effectiveMode, qaEnabled, testerInfo: info });
14664
+ console.log("BugBear: Init complete", { effectiveMode, qaEnabled, feedbackEnabled, testerInfo: info, widgetConfig });
14610
14665
  setWidgetMode(effectiveMode);
14611
14666
  setIsQAEnabled(qaEnabled);
14667
+ setIsFeedbackEnabled(feedbackEnabled);
14612
14668
  setTesterInfo(info);
14613
14669
  setIsTester(!!info);
14670
+ if (widgetConfig.colorScheme && widgetConfig.colorScheme !== "auto") {
14671
+ setServerColorScheme(widgetConfig.colorScheme);
14672
+ }
14614
14673
  if (effectiveMode === "qa" && info && qaEnabled) {
14615
14674
  const [newAssignments, newThreads, session, counts] = await Promise.all([
14616
14675
  bugBearClient.getAssignedTests(),
@@ -14772,7 +14831,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
14772
14831
  ) || assignments.find(
14773
14832
  (a) => a.status === "pending"
14774
14833
  ) || null;
14775
- const shouldShowWidget = widgetMode === "qa" ? isQAEnabled && isTester : isTester;
14834
+ const shouldShowWidget = widgetMode === "qa" ? isQAEnabled && isTester : isFeedbackEnabled && isTester;
14776
14835
  return /* @__PURE__ */ import_react.default.createElement(
14777
14836
  BugBearContext.Provider,
14778
14837
  {
package/dist/index.mjs CHANGED
@@ -13392,12 +13392,56 @@ var BugBearClient = class {
13392
13392
  return true;
13393
13393
  }
13394
13394
  }
13395
+ /**
13396
+ * Fetch server-side widget config set by the project admin.
13397
+ * Returns settings like color scheme override. Returns empty config on error.
13398
+ */
13399
+ async getWidgetConfig() {
13400
+ try {
13401
+ await this.ensureReady();
13402
+ const { data, error } = await this.supabase.rpc("get_widget_config", {
13403
+ p_project_id: this.config.projectId
13404
+ });
13405
+ if (error) {
13406
+ console.warn("BugBear: Could not fetch widget config", error.message || error.code || "Unknown error");
13407
+ return {};
13408
+ }
13409
+ return data ?? {};
13410
+ } catch (err) {
13411
+ const message = err instanceof Error ? err.message : "Unknown error fetching widget config";
13412
+ console.error("BugBear: Error fetching widget config", err);
13413
+ this.config.onError?.(err instanceof Error ? err : new Error(message), { projectId: this.config.projectId });
13414
+ return {};
13415
+ }
13416
+ }
13417
+ /**
13418
+ * Check if feedback mode is enabled for this project.
13419
+ * This is a master switch that admins can toggle in the dashboard.
13420
+ */
13421
+ async isFeedbackEnabled() {
13422
+ try {
13423
+ await this.ensureReady();
13424
+ const { data, error } = await this.supabase.rpc("check_feedback_enabled", {
13425
+ p_project_id: this.config.projectId
13426
+ });
13427
+ if (error) {
13428
+ console.warn("BugBear: Could not check feedback status", error.message || error.code || "Unknown error");
13429
+ return false;
13430
+ }
13431
+ return data ?? false;
13432
+ } catch (err) {
13433
+ const message = err instanceof Error ? err.message : "Unknown error checking feedback status";
13434
+ console.error("BugBear: Error checking feedback status", err);
13435
+ this.config.onError?.(err instanceof Error ? err : new Error(message), { projectId: this.config.projectId });
13436
+ return false;
13437
+ }
13438
+ }
13395
13439
  /**
13396
13440
  * Check if the widget should be visible.
13397
13441
  * Behavior depends on the configured mode:
13398
13442
  * - 'qa': QA enabled AND user is a registered tester
13399
- * - 'feedback': Any authenticated user
13400
- * - 'auto': Either QA tester OR authenticated non-tester
13443
+ * - 'feedback': Feedback enabled AND user is authenticated
13444
+ * - 'auto': QA tester (if QA enabled) OR authenticated user (if feedback enabled)
13401
13445
  */
13402
13446
  async shouldShowWidget() {
13403
13447
  const mode = this.config.mode || "qa";
@@ -13409,33 +13453,39 @@ var BugBearClient = class {
13409
13453
  return qaEnabled2 && tester;
13410
13454
  }
13411
13455
  if (mode === "feedback") {
13412
- const userInfo2 = await this.getCurrentUserInfo();
13413
- return userInfo2 !== null;
13456
+ const [feedbackEnabled2, userInfo2] = await Promise.all([
13457
+ this.isFeedbackEnabled(),
13458
+ this.getCurrentUserInfo()
13459
+ ]);
13460
+ return feedbackEnabled2 && userInfo2 !== null;
13414
13461
  }
13415
- const [qaEnabled, testerInfo, userInfo] = await Promise.all([
13462
+ const [qaEnabled, feedbackEnabled, testerInfo, userInfo] = await Promise.all([
13416
13463
  this.isQAEnabled(),
13464
+ this.isFeedbackEnabled(),
13417
13465
  this.getTesterInfo(),
13418
13466
  this.getCurrentUserInfo()
13419
13467
  ]);
13420
13468
  if (qaEnabled && testerInfo && testerInfo.role !== "feedback") return true;
13421
- if (userInfo) return true;
13469
+ if (feedbackEnabled && userInfo) return true;
13422
13470
  return false;
13423
13471
  }
13424
13472
  /**
13425
13473
  * Resolve the effective widget mode for the current user.
13426
13474
  * - 'qa' or 'feedback' config → returned as-is
13427
- * - 'auto' → checks if user is a QA tester (role='tester') → 'qa', otherwise 'feedback'
13475
+ * - 'auto' → QA tester with QA enabled 'qa', feedback enabled → 'feedback', else 'qa'
13428
13476
  */
13429
13477
  async getEffectiveMode() {
13430
13478
  const mode = this.config.mode || "qa";
13431
13479
  if (mode === "qa") return "qa";
13432
13480
  if (mode === "feedback") return "feedback";
13433
- const [qaEnabled, testerInfo] = await Promise.all([
13481
+ const [qaEnabled, feedbackEnabled, testerInfo] = await Promise.all([
13434
13482
  this.isQAEnabled(),
13483
+ this.isFeedbackEnabled(),
13435
13484
  this.getTesterInfo()
13436
13485
  ]);
13437
13486
  if (qaEnabled && testerInfo && testerInfo.role !== "feedback") return "qa";
13438
- return "feedback";
13487
+ if (feedbackEnabled) return "feedback";
13488
+ return "qa";
13439
13489
  }
13440
13490
  /**
13441
13491
  * Auto-provision a feedback user record in the testers table.
@@ -14438,6 +14488,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
14438
14488
  const [client, setClient] = useState(null);
14439
14489
  const [isTester, setIsTester] = useState(false);
14440
14490
  const [isQAEnabled, setIsQAEnabled] = useState(false);
14491
+ const [isFeedbackEnabled, setIsFeedbackEnabled] = useState(false);
14441
14492
  const [testerInfo, setTesterInfo] = useState(null);
14442
14493
  const [assignments, setAssignments] = useState([]);
14443
14494
  const [isLoading, setIsLoading] = useState(true);
@@ -14451,7 +14502,9 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
14451
14502
  const hasInitialized = useRef(false);
14452
14503
  const monitorHandlersRef = useRef([]);
14453
14504
  const rageClickRef = useRef(null);
14454
- const configColorScheme = config.theme?.colorScheme ?? "dark";
14505
+ const devColorScheme = config.theme?.colorScheme ?? "auto";
14506
+ const [serverColorScheme, setServerColorScheme] = useState(null);
14507
+ const configColorScheme = serverColorScheme ?? (devColorScheme === "auto" ? "auto" : devColorScheme);
14455
14508
  const [activeScheme, setActiveScheme] = useState(() => {
14456
14509
  if (configColorScheme !== "auto") return configColorScheme;
14457
14510
  return Appearance2.getColorScheme() === "light" ? "light" : "dark";
@@ -14568,16 +14621,22 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
14568
14621
  const initializeBugBear = useCallback(async (bugBearClient) => {
14569
14622
  setIsLoading(true);
14570
14623
  try {
14571
- const [effectiveMode, qaEnabled, info] = await Promise.all([
14624
+ const [effectiveMode, qaEnabled, feedbackEnabled, info, widgetConfig] = await Promise.all([
14572
14625
  bugBearClient.getEffectiveMode(),
14573
14626
  bugBearClient.isQAEnabled(),
14574
- bugBearClient.getTesterInfo()
14627
+ bugBearClient.isFeedbackEnabled(),
14628
+ bugBearClient.getTesterInfo(),
14629
+ bugBearClient.getWidgetConfig()
14575
14630
  ]);
14576
- console.log("BugBear: Init complete", { effectiveMode, qaEnabled, testerInfo: info });
14631
+ console.log("BugBear: Init complete", { effectiveMode, qaEnabled, feedbackEnabled, testerInfo: info, widgetConfig });
14577
14632
  setWidgetMode(effectiveMode);
14578
14633
  setIsQAEnabled(qaEnabled);
14634
+ setIsFeedbackEnabled(feedbackEnabled);
14579
14635
  setTesterInfo(info);
14580
14636
  setIsTester(!!info);
14637
+ if (widgetConfig.colorScheme && widgetConfig.colorScheme !== "auto") {
14638
+ setServerColorScheme(widgetConfig.colorScheme);
14639
+ }
14581
14640
  if (effectiveMode === "qa" && info && qaEnabled) {
14582
14641
  const [newAssignments, newThreads, session, counts] = await Promise.all([
14583
14642
  bugBearClient.getAssignedTests(),
@@ -14739,7 +14798,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
14739
14798
  ) || assignments.find(
14740
14799
  (a) => a.status === "pending"
14741
14800
  ) || null;
14742
- const shouldShowWidget = widgetMode === "qa" ? isQAEnabled && isTester : isTester;
14801
+ const shouldShowWidget = widgetMode === "qa" ? isQAEnabled && isTester : isFeedbackEnabled && isTester;
14743
14802
  return /* @__PURE__ */ React.createElement(
14744
14803
  BugBearContext.Provider,
14745
14804
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/react-native",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "BugBear React Native components for mobile apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",