@bbearai/react-native 0.5.4 → 0.5.6
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 +429 -203
- package/dist/index.mjs +409 -183
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -11361,6 +11361,7 @@ 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 BUG_CATEGORIES = ["ui_ux", "functional", "crash", "security", "other"];
|
|
11364
11365
|
var MAX_CONSOLE_LOGS = 50;
|
|
11365
11366
|
var MAX_NETWORK_REQUESTS = 20;
|
|
11366
11367
|
var MAX_NAVIGATION_HISTORY = 20;
|
|
@@ -11713,6 +11714,8 @@ var BugBearClient = class {
|
|
|
11713
11714
|
title: report.title || this.generateTitle(report),
|
|
11714
11715
|
description: report.description,
|
|
11715
11716
|
severity: report.severity,
|
|
11717
|
+
category: report.category,
|
|
11718
|
+
// Bug category (ui, performance, crash, etc.)
|
|
11716
11719
|
failed_at_step: report.failedAtStep,
|
|
11717
11720
|
voice_audio_url: report.voiceAudioUrl,
|
|
11718
11721
|
voice_transcript: report.voiceTranscript,
|
|
@@ -12301,6 +12304,9 @@ var BugBearClient = class {
|
|
|
12301
12304
|
if (report.severity && !validSeverities.includes(report.severity)) {
|
|
12302
12305
|
return `Invalid severity: ${report.severity}. Must be one of: ${validSeverities.join(", ")}`;
|
|
12303
12306
|
}
|
|
12307
|
+
if (report.category && !BUG_CATEGORIES.includes(report.category)) {
|
|
12308
|
+
return `Invalid category: ${report.category}. Must be one of: ${BUG_CATEGORIES.join(", ")}`;
|
|
12309
|
+
}
|
|
12304
12310
|
if (report.title && report.title.length > 500) {
|
|
12305
12311
|
return "Title must be 500 characters or less";
|
|
12306
12312
|
}
|
|
@@ -12373,6 +12379,10 @@ var BugBearClient = class {
|
|
|
12373
12379
|
});
|
|
12374
12380
|
if (error) {
|
|
12375
12381
|
console.warn("BugBear: Rate limit check failed, allowing request", error.message);
|
|
12382
|
+
this.config.onError?.(new Error(`Rate limit check failed: ${error.message}`), {
|
|
12383
|
+
projectId: this.config.projectId,
|
|
12384
|
+
context: "rate_limit_check_failed_open"
|
|
12385
|
+
});
|
|
12376
12386
|
return { allowed: true };
|
|
12377
12387
|
}
|
|
12378
12388
|
if (!data.allowed) {
|
|
@@ -12389,7 +12399,12 @@ var BugBearClient = class {
|
|
|
12389
12399
|
resetAt: data.reset_at
|
|
12390
12400
|
};
|
|
12391
12401
|
} catch (err) {
|
|
12402
|
+
const message = err instanceof Error ? err.message : "Unknown rate limit error";
|
|
12392
12403
|
console.warn("BugBear: Rate limit check error", err);
|
|
12404
|
+
this.config.onError?.(err instanceof Error ? err : new Error(message), {
|
|
12405
|
+
projectId: this.config.projectId,
|
|
12406
|
+
context: "rate_limit_check_failed_open"
|
|
12407
|
+
});
|
|
12393
12408
|
return { allowed: true };
|
|
12394
12409
|
}
|
|
12395
12410
|
}
|
|
@@ -12453,6 +12468,9 @@ var BugBearClient = class {
|
|
|
12453
12468
|
}
|
|
12454
12469
|
return data ?? true;
|
|
12455
12470
|
} catch (err) {
|
|
12471
|
+
const message = err instanceof Error ? err.message : "Unknown error checking QA status";
|
|
12472
|
+
console.error("BugBear: Error checking QA status", err);
|
|
12473
|
+
this.config.onError?.(err instanceof Error ? err : new Error(message), { projectId: this.config.projectId });
|
|
12456
12474
|
return true;
|
|
12457
12475
|
}
|
|
12458
12476
|
}
|
|
@@ -12481,13 +12499,24 @@ var BugBearClient = class {
|
|
|
12481
12499
|
upsert: false
|
|
12482
12500
|
});
|
|
12483
12501
|
if (error) {
|
|
12484
|
-
|
|
12502
|
+
const formattedError = formatPgError(error);
|
|
12503
|
+
const errorMessage = formattedError.message || "Failed to upload screenshot";
|
|
12504
|
+
console.error("BugBear: Failed to upload screenshot", formattedError);
|
|
12505
|
+
this.config.onError?.(new Error(errorMessage), {
|
|
12506
|
+
projectId: this.config.projectId,
|
|
12507
|
+
context: "screenshot_upload_failed"
|
|
12508
|
+
});
|
|
12485
12509
|
return null;
|
|
12486
12510
|
}
|
|
12487
12511
|
const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
|
|
12488
12512
|
return publicUrl;
|
|
12489
12513
|
} catch (err) {
|
|
12514
|
+
const message = err instanceof Error ? err.message : "Unknown error uploading screenshot";
|
|
12490
12515
|
console.error("BugBear: Error uploading screenshot", err);
|
|
12516
|
+
this.config.onError?.(err instanceof Error ? err : new Error(message), {
|
|
12517
|
+
projectId: this.config.projectId,
|
|
12518
|
+
context: "screenshot_upload_failed"
|
|
12519
|
+
});
|
|
12491
12520
|
return null;
|
|
12492
12521
|
}
|
|
12493
12522
|
}
|
|
@@ -12512,13 +12541,24 @@ var BugBearClient = class {
|
|
|
12512
12541
|
upsert: false
|
|
12513
12542
|
});
|
|
12514
12543
|
if (error) {
|
|
12515
|
-
|
|
12544
|
+
const formattedError = formatPgError(error);
|
|
12545
|
+
const errorMessage = formattedError.message || "Failed to upload image";
|
|
12546
|
+
console.error("BugBear: Failed to upload image from URI", formattedError);
|
|
12547
|
+
this.config.onError?.(new Error(errorMessage), {
|
|
12548
|
+
projectId: this.config.projectId,
|
|
12549
|
+
context: "image_upload_failed"
|
|
12550
|
+
});
|
|
12516
12551
|
return null;
|
|
12517
12552
|
}
|
|
12518
12553
|
const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
|
|
12519
12554
|
return publicUrl;
|
|
12520
12555
|
} catch (err) {
|
|
12556
|
+
const message = err instanceof Error ? err.message : "Unknown error uploading image";
|
|
12521
12557
|
console.error("BugBear: Error uploading image from URI", err);
|
|
12558
|
+
this.config.onError?.(err instanceof Error ? err : new Error(message), {
|
|
12559
|
+
projectId: this.config.projectId,
|
|
12560
|
+
context: "image_upload_failed"
|
|
12561
|
+
});
|
|
12522
12562
|
return null;
|
|
12523
12563
|
}
|
|
12524
12564
|
}
|
|
@@ -13328,15 +13368,15 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
|
|
|
13328
13368
|
}
|
|
13329
13369
|
|
|
13330
13370
|
// src/BugBearButton.tsx
|
|
13331
|
-
import
|
|
13371
|
+
import React17, { useState as useState12, useRef as useRef3 } from "react";
|
|
13332
13372
|
import {
|
|
13333
|
-
View as
|
|
13334
|
-
Text as
|
|
13373
|
+
View as View16,
|
|
13374
|
+
Text as Text16,
|
|
13335
13375
|
Image as Image4,
|
|
13336
|
-
TouchableOpacity as
|
|
13337
|
-
Modal as
|
|
13376
|
+
TouchableOpacity as TouchableOpacity15,
|
|
13377
|
+
Modal as Modal3,
|
|
13338
13378
|
ScrollView as ScrollView3,
|
|
13339
|
-
StyleSheet as
|
|
13379
|
+
StyleSheet as StyleSheet17,
|
|
13340
13380
|
Dimensions as Dimensions2,
|
|
13341
13381
|
KeyboardAvoidingView,
|
|
13342
13382
|
Platform as Platform4,
|
|
@@ -14378,7 +14418,12 @@ function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
|
14378
14418
|
launchImageLibrary(
|
|
14379
14419
|
{ mediaType: "photo", quality: 0.7, maxWidth: 1920, maxHeight: 1920, selectionLimit: maxImages - images.length },
|
|
14380
14420
|
async (response) => {
|
|
14381
|
-
if (response.didCancel
|
|
14421
|
+
if (response.didCancel) return;
|
|
14422
|
+
if (response.errorCode) {
|
|
14423
|
+
console.error("BugBear: Image picker error", response.errorCode, response.errorMessage);
|
|
14424
|
+
return;
|
|
14425
|
+
}
|
|
14426
|
+
if (!response.assets) return;
|
|
14382
14427
|
for (const asset of response.assets) {
|
|
14383
14428
|
const uri = asset.uri;
|
|
14384
14429
|
if (!uri) continue;
|
|
@@ -14392,6 +14437,11 @@ function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
|
14392
14437
|
setImages((prev) => prev.map(
|
|
14393
14438
|
(img) => img.id === id ? { ...img, remoteUrl: url, status: url ? "done" : "error" } : img
|
|
14394
14439
|
));
|
|
14440
|
+
}).catch((err) => {
|
|
14441
|
+
console.error("BugBear: Image upload failed", err);
|
|
14442
|
+
setImages((prev) => prev.map(
|
|
14443
|
+
(img) => img.id === id ? { ...img, status: "error" } : img
|
|
14444
|
+
));
|
|
14395
14445
|
});
|
|
14396
14446
|
}
|
|
14397
14447
|
}
|
|
@@ -14402,7 +14452,12 @@ function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
|
14402
14452
|
launchCamera(
|
|
14403
14453
|
{ mediaType: "photo", quality: 0.7, maxWidth: 1920, maxHeight: 1920 },
|
|
14404
14454
|
async (response) => {
|
|
14405
|
-
if (response.didCancel
|
|
14455
|
+
if (response.didCancel) return;
|
|
14456
|
+
if (response.errorCode) {
|
|
14457
|
+
console.error("BugBear: Camera error", response.errorCode, response.errorMessage);
|
|
14458
|
+
return;
|
|
14459
|
+
}
|
|
14460
|
+
if (!response.assets?.[0]) return;
|
|
14406
14461
|
const asset = response.assets[0];
|
|
14407
14462
|
const uri = asset.uri;
|
|
14408
14463
|
if (!uri) return;
|
|
@@ -14416,6 +14471,11 @@ function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
|
14416
14471
|
setImages((prev) => prev.map(
|
|
14417
14472
|
(img) => img.id === id ? { ...img, remoteUrl: url, status: url ? "done" : "error" } : img
|
|
14418
14473
|
));
|
|
14474
|
+
}).catch((err) => {
|
|
14475
|
+
console.error("BugBear: Image upload failed", err);
|
|
14476
|
+
setImages((prev) => prev.map(
|
|
14477
|
+
(img) => img.id === id ? { ...img, status: "error" } : img
|
|
14478
|
+
));
|
|
14419
14479
|
});
|
|
14420
14480
|
}
|
|
14421
14481
|
);
|
|
@@ -14680,20 +14740,185 @@ var styles6 = StyleSheet7.create({
|
|
|
14680
14740
|
});
|
|
14681
14741
|
|
|
14682
14742
|
// src/widget/screens/ReportScreen.tsx
|
|
14683
|
-
import
|
|
14684
|
-
import { View as
|
|
14743
|
+
import React9, { useState as useState7, useRef as useRef2, useEffect as useEffect5 } from "react";
|
|
14744
|
+
import { View as View8, Text as Text8, TouchableOpacity as TouchableOpacity8, TextInput as TextInput3, StyleSheet as StyleSheet9 } from "react-native";
|
|
14745
|
+
|
|
14746
|
+
// src/widget/CategoryPicker.tsx
|
|
14747
|
+
import React8, { useState as useState6 } from "react";
|
|
14748
|
+
import { View as View7, Text as Text7, TouchableOpacity as TouchableOpacity7, Modal as Modal2, StyleSheet as StyleSheet8 } from "react-native";
|
|
14749
|
+
var categoryOptions = [
|
|
14750
|
+
{ value: "ui_ux", label: "UI/UX", icon: "\u{1F3A8}" },
|
|
14751
|
+
{ value: "functional", label: "Functional", icon: "\u2699\uFE0F" },
|
|
14752
|
+
{ value: "crash", label: "Crash", icon: "\u{1F4A5}" },
|
|
14753
|
+
{ value: "security", label: "Security", icon: "\u{1F510}" },
|
|
14754
|
+
{ value: "other", label: "Other", icon: "\u{1F4DD}" }
|
|
14755
|
+
];
|
|
14756
|
+
function CategoryPicker({ value, onChange, optional = true }) {
|
|
14757
|
+
const [modalVisible, setModalVisible] = useState6(false);
|
|
14758
|
+
const selectedOption = value ? categoryOptions.find((o) => o.value === value) : null;
|
|
14759
|
+
const handleSelect = (category) => {
|
|
14760
|
+
onChange(category);
|
|
14761
|
+
setModalVisible(false);
|
|
14762
|
+
};
|
|
14763
|
+
return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
|
|
14764
|
+
TouchableOpacity7,
|
|
14765
|
+
{
|
|
14766
|
+
style: styles7.trigger,
|
|
14767
|
+
onPress: () => setModalVisible(true)
|
|
14768
|
+
},
|
|
14769
|
+
/* @__PURE__ */ React8.createElement(Text7, { style: selectedOption ? styles7.triggerTextSelected : styles7.triggerTextPlaceholder }, selectedOption ? `${selectedOption.icon} ${selectedOption.label}` : optional ? "Select category (optional)" : "Select category"),
|
|
14770
|
+
/* @__PURE__ */ React8.createElement(Text7, { style: styles7.chevron }, "\u25BC")
|
|
14771
|
+
), /* @__PURE__ */ React8.createElement(
|
|
14772
|
+
Modal2,
|
|
14773
|
+
{
|
|
14774
|
+
visible: modalVisible,
|
|
14775
|
+
transparent: true,
|
|
14776
|
+
animationType: "fade",
|
|
14777
|
+
onRequestClose: () => setModalVisible(false)
|
|
14778
|
+
},
|
|
14779
|
+
/* @__PURE__ */ React8.createElement(
|
|
14780
|
+
TouchableOpacity7,
|
|
14781
|
+
{
|
|
14782
|
+
style: styles7.overlay,
|
|
14783
|
+
activeOpacity: 1,
|
|
14784
|
+
onPress: () => setModalVisible(false)
|
|
14785
|
+
},
|
|
14786
|
+
/* @__PURE__ */ React8.createElement(View7, { style: styles7.modal, onStartShouldSetResponder: () => true }, /* @__PURE__ */ React8.createElement(Text7, { style: styles7.modalTitle }, "Select Category"), optional && /* @__PURE__ */ React8.createElement(
|
|
14787
|
+
TouchableOpacity7,
|
|
14788
|
+
{
|
|
14789
|
+
style: [styles7.option, !value && styles7.optionSelected],
|
|
14790
|
+
onPress: () => handleSelect(null)
|
|
14791
|
+
},
|
|
14792
|
+
/* @__PURE__ */ React8.createElement(Text7, { style: styles7.optionText }, "\u2014 None \u2014")
|
|
14793
|
+
), categoryOptions.map(({ value: optValue, label, icon }) => /* @__PURE__ */ React8.createElement(
|
|
14794
|
+
TouchableOpacity7,
|
|
14795
|
+
{
|
|
14796
|
+
key: optValue,
|
|
14797
|
+
style: [styles7.option, value === optValue && styles7.optionSelected],
|
|
14798
|
+
onPress: () => handleSelect(optValue)
|
|
14799
|
+
},
|
|
14800
|
+
/* @__PURE__ */ React8.createElement(Text7, { style: styles7.optionIcon }, icon),
|
|
14801
|
+
/* @__PURE__ */ React8.createElement(Text7, { style: styles7.optionText }, label),
|
|
14802
|
+
value === optValue && /* @__PURE__ */ React8.createElement(Text7, { style: styles7.checkmark }, "\u2713")
|
|
14803
|
+
)), /* @__PURE__ */ React8.createElement(
|
|
14804
|
+
TouchableOpacity7,
|
|
14805
|
+
{
|
|
14806
|
+
style: styles7.cancelButton,
|
|
14807
|
+
onPress: () => setModalVisible(false)
|
|
14808
|
+
},
|
|
14809
|
+
/* @__PURE__ */ React8.createElement(Text7, { style: styles7.cancelText }, "Cancel")
|
|
14810
|
+
))
|
|
14811
|
+
)
|
|
14812
|
+
));
|
|
14813
|
+
}
|
|
14814
|
+
var styles7 = StyleSheet8.create({
|
|
14815
|
+
trigger: {
|
|
14816
|
+
flexDirection: "row",
|
|
14817
|
+
alignItems: "center",
|
|
14818
|
+
justifyContent: "space-between",
|
|
14819
|
+
backgroundColor: colors.card,
|
|
14820
|
+
borderWidth: 1,
|
|
14821
|
+
borderColor: colors.border,
|
|
14822
|
+
borderRadius: 8,
|
|
14823
|
+
paddingHorizontal: 12,
|
|
14824
|
+
paddingVertical: 10
|
|
14825
|
+
},
|
|
14826
|
+
triggerTextSelected: {
|
|
14827
|
+
fontSize: 14,
|
|
14828
|
+
color: colors.textPrimary
|
|
14829
|
+
},
|
|
14830
|
+
triggerTextPlaceholder: {
|
|
14831
|
+
fontSize: 14,
|
|
14832
|
+
color: colors.textMuted
|
|
14833
|
+
},
|
|
14834
|
+
chevron: {
|
|
14835
|
+
fontSize: 10,
|
|
14836
|
+
color: colors.textMuted
|
|
14837
|
+
},
|
|
14838
|
+
overlay: {
|
|
14839
|
+
flex: 1,
|
|
14840
|
+
backgroundColor: "rgba(0, 0, 0, 0.6)",
|
|
14841
|
+
justifyContent: "center",
|
|
14842
|
+
alignItems: "center",
|
|
14843
|
+
padding: 24
|
|
14844
|
+
},
|
|
14845
|
+
modal: {
|
|
14846
|
+
width: "100%",
|
|
14847
|
+
maxWidth: 300,
|
|
14848
|
+
backgroundColor: colors.card,
|
|
14849
|
+
borderRadius: 16,
|
|
14850
|
+
padding: 8,
|
|
14851
|
+
borderWidth: 1,
|
|
14852
|
+
borderColor: colors.border
|
|
14853
|
+
},
|
|
14854
|
+
modalTitle: {
|
|
14855
|
+
fontSize: 16,
|
|
14856
|
+
fontWeight: "600",
|
|
14857
|
+
color: colors.textPrimary,
|
|
14858
|
+
textAlign: "center",
|
|
14859
|
+
paddingVertical: 12,
|
|
14860
|
+
borderBottomWidth: 1,
|
|
14861
|
+
borderBottomColor: colors.border,
|
|
14862
|
+
marginBottom: 4
|
|
14863
|
+
},
|
|
14864
|
+
option: {
|
|
14865
|
+
flexDirection: "row",
|
|
14866
|
+
alignItems: "center",
|
|
14867
|
+
paddingVertical: 14,
|
|
14868
|
+
paddingHorizontal: 16,
|
|
14869
|
+
borderRadius: 8
|
|
14870
|
+
},
|
|
14871
|
+
optionSelected: {
|
|
14872
|
+
backgroundColor: colors.blue + "20"
|
|
14873
|
+
},
|
|
14874
|
+
optionIcon: {
|
|
14875
|
+
fontSize: 18,
|
|
14876
|
+
marginRight: 12
|
|
14877
|
+
},
|
|
14878
|
+
optionText: {
|
|
14879
|
+
flex: 1,
|
|
14880
|
+
fontSize: 15,
|
|
14881
|
+
color: colors.textPrimary
|
|
14882
|
+
},
|
|
14883
|
+
checkmark: {
|
|
14884
|
+
fontSize: 16,
|
|
14885
|
+
color: colors.blue,
|
|
14886
|
+
fontWeight: "600"
|
|
14887
|
+
},
|
|
14888
|
+
cancelButton: {
|
|
14889
|
+
marginTop: 8,
|
|
14890
|
+
paddingVertical: 12,
|
|
14891
|
+
borderTopWidth: 1,
|
|
14892
|
+
borderTopColor: colors.border
|
|
14893
|
+
},
|
|
14894
|
+
cancelText: {
|
|
14895
|
+
fontSize: 15,
|
|
14896
|
+
color: colors.textMuted,
|
|
14897
|
+
textAlign: "center"
|
|
14898
|
+
}
|
|
14899
|
+
});
|
|
14900
|
+
|
|
14901
|
+
// src/widget/screens/ReportScreen.tsx
|
|
14685
14902
|
function ReportScreen({ nav, prefill }) {
|
|
14686
14903
|
const { client, getDeviceInfo, uploadImage, refreshAssignments } = useBugBear();
|
|
14687
|
-
const [reportType, setReportType] =
|
|
14688
|
-
const [severity, setSeverity] =
|
|
14689
|
-
const [
|
|
14690
|
-
const [
|
|
14691
|
-
const [
|
|
14692
|
-
const [
|
|
14904
|
+
const [reportType, setReportType] = useState7(prefill?.type || "bug");
|
|
14905
|
+
const [severity, setSeverity] = useState7("medium");
|
|
14906
|
+
const [category, setCategory] = useState7(null);
|
|
14907
|
+
const [description, setDescription] = useState7("");
|
|
14908
|
+
const [affectedScreen, setAffectedScreen] = useState7("");
|
|
14909
|
+
const [submitting, setSubmitting] = useState7(false);
|
|
14910
|
+
const [error, setError] = useState7(null);
|
|
14693
14911
|
const submittingRef = useRef2(false);
|
|
14694
14912
|
const images = useImageAttachments(uploadImage, 5, "screenshots");
|
|
14695
14913
|
const isRetestFailure = prefill?.type === "test_fail";
|
|
14696
14914
|
const isBugType = reportType === "bug" || reportType === "test_fail";
|
|
14915
|
+
useEffect5(() => {
|
|
14916
|
+
if (reportType === "feedback" || reportType === "suggestion") {
|
|
14917
|
+
setCategory("other");
|
|
14918
|
+
} else {
|
|
14919
|
+
setCategory(null);
|
|
14920
|
+
}
|
|
14921
|
+
}, [reportType]);
|
|
14697
14922
|
const handleSubmit = async () => {
|
|
14698
14923
|
if (!client || !description.trim()) return;
|
|
14699
14924
|
if (submittingRef.current) return;
|
|
@@ -14711,6 +14936,7 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14711
14936
|
type: reportType,
|
|
14712
14937
|
description: description.trim(),
|
|
14713
14938
|
severity: isBugType ? severity : void 0,
|
|
14939
|
+
category: category || void 0,
|
|
14714
14940
|
assignmentId: prefill?.assignmentId,
|
|
14715
14941
|
testCaseId: prefill?.testCaseId,
|
|
14716
14942
|
appContext,
|
|
@@ -14735,23 +14961,23 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14735
14961
|
submittingRef.current = false;
|
|
14736
14962
|
}
|
|
14737
14963
|
};
|
|
14738
|
-
return /* @__PURE__ */
|
|
14964
|
+
return /* @__PURE__ */ React9.createElement(View8, null, isRetestFailure ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(View8, { style: styles8.retestBanner }, /* @__PURE__ */ React9.createElement(Text8, { style: styles8.retestIcon }, "\u{1F504}"), /* @__PURE__ */ React9.createElement(View8, null, /* @__PURE__ */ React9.createElement(Text8, { style: styles8.retestTitle }, "Bug Still Present"), /* @__PURE__ */ React9.createElement(Text8, { style: styles8.retestSubtitle }, "The fix did not resolve this issue"))), /* @__PURE__ */ React9.createElement(View8, { style: styles8.section }, /* @__PURE__ */ React9.createElement(Text8, { style: shared.label }, "Severity"), /* @__PURE__ */ React9.createElement(View8, { style: styles8.severityRow }, [
|
|
14739
14965
|
{ sev: "critical", color: "#ef4444" },
|
|
14740
14966
|
{ sev: "high", color: "#f97316" },
|
|
14741
14967
|
{ sev: "medium", color: "#eab308" },
|
|
14742
14968
|
{ sev: "low", color: "#6b7280" }
|
|
14743
|
-
].map(({ sev, color }) => /* @__PURE__ */
|
|
14744
|
-
|
|
14969
|
+
].map(({ sev, color }) => /* @__PURE__ */ React9.createElement(
|
|
14970
|
+
TouchableOpacity8,
|
|
14745
14971
|
{
|
|
14746
14972
|
key: sev,
|
|
14747
|
-
style: [
|
|
14973
|
+
style: [styles8.sevButton, severity === sev && { backgroundColor: `${color}30`, borderColor: color }],
|
|
14748
14974
|
onPress: () => setSeverity(sev)
|
|
14749
14975
|
},
|
|
14750
|
-
/* @__PURE__ */
|
|
14751
|
-
)))), /* @__PURE__ */
|
|
14976
|
+
/* @__PURE__ */ React9.createElement(Text8, { style: [styles8.sevText, severity === sev && { color }] }, sev)
|
|
14977
|
+
)))), /* @__PURE__ */ React9.createElement(View8, { style: styles8.section }, /* @__PURE__ */ React9.createElement(Text8, { style: shared.label }, "Category (optional)"), /* @__PURE__ */ React9.createElement(CategoryPicker, { value: category, onChange: setCategory, optional: true })), /* @__PURE__ */ React9.createElement(View8, { style: styles8.section }, /* @__PURE__ */ React9.createElement(Text8, { style: shared.label }, "What went wrong?"), /* @__PURE__ */ React9.createElement(
|
|
14752
14978
|
TextInput3,
|
|
14753
14979
|
{
|
|
14754
|
-
style:
|
|
14980
|
+
style: styles8.descInput,
|
|
14755
14981
|
value: description,
|
|
14756
14982
|
onChangeText: setDescription,
|
|
14757
14983
|
placeholder: "Describe what you observed. What still doesn't work?",
|
|
@@ -14760,7 +14986,7 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14760
14986
|
numberOfLines: 4,
|
|
14761
14987
|
textAlignVertical: "top"
|
|
14762
14988
|
}
|
|
14763
|
-
)), /* @__PURE__ */
|
|
14989
|
+
)), /* @__PURE__ */ React9.createElement(
|
|
14764
14990
|
ImagePickerButtons,
|
|
14765
14991
|
{
|
|
14766
14992
|
images: images.images,
|
|
@@ -14770,44 +14996,44 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14770
14996
|
onRemove: images.removeImage,
|
|
14771
14997
|
label: "Attachments (optional)"
|
|
14772
14998
|
}
|
|
14773
|
-
), error && /* @__PURE__ */
|
|
14774
|
-
|
|
14999
|
+
), error && /* @__PURE__ */ React9.createElement(View8, { style: styles8.errorBanner }, /* @__PURE__ */ React9.createElement(Text8, { style: styles8.errorText }, error)), /* @__PURE__ */ React9.createElement(
|
|
15000
|
+
TouchableOpacity8,
|
|
14775
15001
|
{
|
|
14776
|
-
style: [shared.primaryButton,
|
|
15002
|
+
style: [shared.primaryButton, styles8.retestSubmitButton, (!description.trim() || submitting || images.isUploading) && shared.primaryButtonDisabled, { marginTop: 20 }],
|
|
14777
15003
|
onPress: handleSubmit,
|
|
14778
15004
|
disabled: !description.trim() || submitting || images.isUploading
|
|
14779
15005
|
},
|
|
14780
|
-
/* @__PURE__ */
|
|
14781
|
-
)) : /* @__PURE__ */
|
|
15006
|
+
/* @__PURE__ */ React9.createElement(Text8, { style: shared.primaryButtonText }, images.isUploading ? "Uploading images..." : submitting ? "Submitting..." : error ? "Retry" : "Submit Failed Retest")
|
|
15007
|
+
)) : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(Text8, { style: shared.label }, "What are you reporting?"), /* @__PURE__ */ React9.createElement(View8, { style: styles8.typeRow }, [
|
|
14782
15008
|
{ type: "bug", label: "Bug", icon: "\u{1F41B}" },
|
|
14783
15009
|
{ type: "feedback", label: "Feedback", icon: "\u{1F4A1}" },
|
|
14784
15010
|
{ type: "suggestion", label: "Idea", icon: "\u2728" }
|
|
14785
|
-
].map(({ type, label, icon }) => /* @__PURE__ */
|
|
14786
|
-
|
|
15011
|
+
].map(({ type, label, icon }) => /* @__PURE__ */ React9.createElement(
|
|
15012
|
+
TouchableOpacity8,
|
|
14787
15013
|
{
|
|
14788
15014
|
key: type,
|
|
14789
|
-
style: [
|
|
15015
|
+
style: [styles8.typeCard, reportType === type && styles8.typeCardActive],
|
|
14790
15016
|
onPress: () => setReportType(type)
|
|
14791
15017
|
},
|
|
14792
|
-
/* @__PURE__ */
|
|
14793
|
-
/* @__PURE__ */
|
|
14794
|
-
))), isBugType && /* @__PURE__ */
|
|
15018
|
+
/* @__PURE__ */ React9.createElement(Text8, { style: styles8.typeIcon }, icon),
|
|
15019
|
+
/* @__PURE__ */ React9.createElement(Text8, { style: [styles8.typeLabel, reportType === type && styles8.typeLabelActive] }, label)
|
|
15020
|
+
))), isBugType && /* @__PURE__ */ React9.createElement(View8, { style: styles8.section }, /* @__PURE__ */ React9.createElement(Text8, { style: shared.label }, "Severity"), /* @__PURE__ */ React9.createElement(View8, { style: styles8.severityRow }, [
|
|
14795
15021
|
{ sev: "critical", color: "#ef4444" },
|
|
14796
15022
|
{ sev: "high", color: "#f97316" },
|
|
14797
15023
|
{ sev: "medium", color: "#eab308" },
|
|
14798
15024
|
{ sev: "low", color: "#6b7280" }
|
|
14799
|
-
].map(({ sev, color }) => /* @__PURE__ */
|
|
14800
|
-
|
|
15025
|
+
].map(({ sev, color }) => /* @__PURE__ */ React9.createElement(
|
|
15026
|
+
TouchableOpacity8,
|
|
14801
15027
|
{
|
|
14802
15028
|
key: sev,
|
|
14803
|
-
style: [
|
|
15029
|
+
style: [styles8.sevButton, severity === sev && { backgroundColor: `${color}30`, borderColor: color }],
|
|
14804
15030
|
onPress: () => setSeverity(sev)
|
|
14805
15031
|
},
|
|
14806
|
-
/* @__PURE__ */
|
|
14807
|
-
)))), /* @__PURE__ */
|
|
15032
|
+
/* @__PURE__ */ React9.createElement(Text8, { style: [styles8.sevText, severity === sev && { color }] }, sev)
|
|
15033
|
+
)))), isBugType && /* @__PURE__ */ React9.createElement(View8, { style: styles8.section }, /* @__PURE__ */ React9.createElement(Text8, { style: shared.label }, "Category (optional)"), /* @__PURE__ */ React9.createElement(CategoryPicker, { value: category, onChange: setCategory, optional: true })), /* @__PURE__ */ React9.createElement(View8, { style: styles8.section }, /* @__PURE__ */ React9.createElement(Text8, { style: shared.label }, "What happened?"), /* @__PURE__ */ React9.createElement(
|
|
14808
15034
|
TextInput3,
|
|
14809
15035
|
{
|
|
14810
|
-
style:
|
|
15036
|
+
style: styles8.descInput,
|
|
14811
15037
|
value: description,
|
|
14812
15038
|
onChangeText: setDescription,
|
|
14813
15039
|
placeholder: "Describe the issue...",
|
|
@@ -14816,16 +15042,16 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14816
15042
|
numberOfLines: 4,
|
|
14817
15043
|
textAlignVertical: "top"
|
|
14818
15044
|
}
|
|
14819
|
-
)), isBugType && /* @__PURE__ */
|
|
15045
|
+
)), isBugType && /* @__PURE__ */ React9.createElement(View8, { style: styles8.section }, /* @__PURE__ */ React9.createElement(Text8, { style: shared.label }, "Which screen?"), /* @__PURE__ */ React9.createElement(
|
|
14820
15046
|
TextInput3,
|
|
14821
15047
|
{
|
|
14822
|
-
style:
|
|
15048
|
+
style: styles8.screenInput,
|
|
14823
15049
|
value: affectedScreen,
|
|
14824
15050
|
onChangeText: setAffectedScreen,
|
|
14825
15051
|
placeholder: "e.g. Reservations, Settings...",
|
|
14826
15052
|
placeholderTextColor: colors.textMuted
|
|
14827
15053
|
}
|
|
14828
|
-
), /* @__PURE__ */
|
|
15054
|
+
), /* @__PURE__ */ React9.createElement(Text8, { style: styles8.screenHint }, "Which screen or area was the bug on? (optional)")), /* @__PURE__ */ React9.createElement(
|
|
14829
15055
|
ImagePickerButtons,
|
|
14830
15056
|
{
|
|
14831
15057
|
images: images.images,
|
|
@@ -14835,17 +15061,17 @@ function ReportScreen({ nav, prefill }) {
|
|
|
14835
15061
|
onRemove: images.removeImage,
|
|
14836
15062
|
label: "Screenshots (optional)"
|
|
14837
15063
|
}
|
|
14838
|
-
), error && /* @__PURE__ */
|
|
14839
|
-
|
|
15064
|
+
), error && /* @__PURE__ */ React9.createElement(View8, { style: styles8.errorBanner }, /* @__PURE__ */ React9.createElement(Text8, { style: styles8.errorText }, error)), /* @__PURE__ */ React9.createElement(
|
|
15065
|
+
TouchableOpacity8,
|
|
14840
15066
|
{
|
|
14841
15067
|
style: [shared.primaryButton, (!description.trim() || submitting || images.isUploading) && shared.primaryButtonDisabled, { marginTop: 20 }],
|
|
14842
15068
|
onPress: handleSubmit,
|
|
14843
15069
|
disabled: !description.trim() || submitting || images.isUploading
|
|
14844
15070
|
},
|
|
14845
|
-
/* @__PURE__ */
|
|
15071
|
+
/* @__PURE__ */ React9.createElement(Text8, { style: shared.primaryButtonText }, images.isUploading ? "Uploading images..." : submitting ? "Submitting..." : error ? "Retry" : "Submit Report")
|
|
14846
15072
|
)));
|
|
14847
15073
|
}
|
|
14848
|
-
var
|
|
15074
|
+
var styles8 = StyleSheet9.create({
|
|
14849
15075
|
typeRow: { flexDirection: "row", gap: 10, marginBottom: 20 },
|
|
14850
15076
|
typeCard: { flex: 1, alignItems: "center", paddingVertical: 16, borderRadius: 12, backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border },
|
|
14851
15077
|
typeCardActive: { borderColor: colors.blue, backgroundColor: "#172554" },
|
|
@@ -14869,16 +15095,16 @@ var styles7 = StyleSheet8.create({
|
|
|
14869
15095
|
});
|
|
14870
15096
|
|
|
14871
15097
|
// src/widget/screens/ReportSuccessScreen.tsx
|
|
14872
|
-
import
|
|
14873
|
-
import { View as
|
|
15098
|
+
import React10, { useEffect as useEffect6 } from "react";
|
|
15099
|
+
import { View as View9, Text as Text9, StyleSheet as StyleSheet10 } from "react-native";
|
|
14874
15100
|
function ReportSuccessScreen({ nav }) {
|
|
14875
|
-
|
|
15101
|
+
useEffect6(() => {
|
|
14876
15102
|
const timer = setTimeout(() => nav.reset(), 2e3);
|
|
14877
15103
|
return () => clearTimeout(timer);
|
|
14878
15104
|
}, [nav]);
|
|
14879
|
-
return /* @__PURE__ */
|
|
15105
|
+
return /* @__PURE__ */ React10.createElement(View9, { style: styles9.container }, /* @__PURE__ */ React10.createElement(Text9, { style: styles9.emoji }, "\u{1F389}"), /* @__PURE__ */ React10.createElement(Text9, { style: styles9.title }, "Report submitted!"), /* @__PURE__ */ React10.createElement(Text9, { style: styles9.subtitle }, "Thank you for your feedback"));
|
|
14880
15106
|
}
|
|
14881
|
-
var
|
|
15107
|
+
var styles9 = StyleSheet10.create({
|
|
14882
15108
|
container: { alignItems: "center", paddingVertical: 60 },
|
|
14883
15109
|
emoji: { fontSize: 48, marginBottom: 16 },
|
|
14884
15110
|
title: { fontSize: 22, fontWeight: "700", color: colors.textPrimary, marginBottom: 6 },
|
|
@@ -14886,29 +15112,29 @@ var styles8 = StyleSheet9.create({
|
|
|
14886
15112
|
});
|
|
14887
15113
|
|
|
14888
15114
|
// src/widget/screens/MessageListScreen.tsx
|
|
14889
|
-
import
|
|
14890
|
-
import { View as
|
|
15115
|
+
import React11 from "react";
|
|
15116
|
+
import { View as View10, Text as Text10, TouchableOpacity as TouchableOpacity9, StyleSheet as StyleSheet11 } from "react-native";
|
|
14891
15117
|
function MessageListScreen({ nav }) {
|
|
14892
15118
|
const { threads, unreadCount, refreshThreads } = useBugBear();
|
|
14893
|
-
return /* @__PURE__ */
|
|
14894
|
-
|
|
15119
|
+
return /* @__PURE__ */ React11.createElement(View10, null, /* @__PURE__ */ React11.createElement(
|
|
15120
|
+
TouchableOpacity9,
|
|
14895
15121
|
{
|
|
14896
|
-
style:
|
|
15122
|
+
style: styles10.newMsgButton,
|
|
14897
15123
|
onPress: () => nav.push({ name: "COMPOSE_MESSAGE" })
|
|
14898
15124
|
},
|
|
14899
|
-
/* @__PURE__ */
|
|
14900
|
-
), threads.length === 0 ? /* @__PURE__ */
|
|
14901
|
-
|
|
15125
|
+
/* @__PURE__ */ React11.createElement(Text10, { style: styles10.newMsgText }, "\u2709\uFE0F New Message")
|
|
15126
|
+
), threads.length === 0 ? /* @__PURE__ */ React11.createElement(View10, { style: shared.emptyState }, /* @__PURE__ */ React11.createElement(Text10, { style: shared.emptyEmoji }, "\u{1F4AC}"), /* @__PURE__ */ React11.createElement(Text10, { style: shared.emptyTitle }, "No messages yet"), /* @__PURE__ */ React11.createElement(Text10, { style: shared.emptySubtitle }, "Start a conversation or wait for messages from admins")) : /* @__PURE__ */ React11.createElement(View10, null, threads.map((thread) => /* @__PURE__ */ React11.createElement(
|
|
15127
|
+
TouchableOpacity9,
|
|
14902
15128
|
{
|
|
14903
15129
|
key: thread.id,
|
|
14904
|
-
style: [
|
|
15130
|
+
style: [styles10.threadItem, thread.unreadCount > 0 && styles10.threadItemUnread],
|
|
14905
15131
|
onPress: () => nav.push({ name: "THREAD_DETAIL", thread })
|
|
14906
15132
|
},
|
|
14907
|
-
/* @__PURE__ */
|
|
14908
|
-
/* @__PURE__ */
|
|
14909
|
-
))), /* @__PURE__ */
|
|
15133
|
+
/* @__PURE__ */ React11.createElement(View10, { style: styles10.threadLeft }, /* @__PURE__ */ React11.createElement(Text10, { style: styles10.threadIcon }, getThreadTypeIcon(thread.threadType)), /* @__PURE__ */ React11.createElement(View10, { style: styles10.threadInfo }, /* @__PURE__ */ React11.createElement(View10, { style: styles10.threadTitleRow }, thread.isPinned && /* @__PURE__ */ React11.createElement(Text10, { style: styles10.pinIcon }, "\u{1F4CC}"), /* @__PURE__ */ React11.createElement(Text10, { style: styles10.threadSubject, numberOfLines: 1 }, thread.subject || "No subject")), thread.lastMessage && /* @__PURE__ */ React11.createElement(Text10, { style: styles10.threadPreview, numberOfLines: 1 }, thread.lastMessage.senderName, ": ", thread.lastMessage.content))),
|
|
15134
|
+
/* @__PURE__ */ React11.createElement(View10, { style: styles10.threadRight }, /* @__PURE__ */ React11.createElement(Text10, { style: styles10.threadTime }, formatRelativeTime(thread.lastMessageAt)), thread.unreadCount > 0 && /* @__PURE__ */ React11.createElement(View10, { style: styles10.unreadBadge }, /* @__PURE__ */ React11.createElement(Text10, { style: styles10.unreadText }, thread.unreadCount)), thread.priority !== "normal" && /* @__PURE__ */ React11.createElement(View10, { style: [styles10.priorityDot, { backgroundColor: getPriorityColor(thread.priority) }] }))
|
|
15135
|
+
))), /* @__PURE__ */ React11.createElement(View10, { style: styles10.footer }, /* @__PURE__ */ React11.createElement(Text10, { style: styles10.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ React11.createElement(TouchableOpacity9, { onPress: refreshThreads }, /* @__PURE__ */ React11.createElement(Text10, { style: styles10.refreshText }, "\u21BB Refresh"))));
|
|
14910
15136
|
}
|
|
14911
|
-
var
|
|
15137
|
+
var styles10 = StyleSheet11.create({
|
|
14912
15138
|
newMsgButton: { backgroundColor: colors.blue, paddingVertical: 12, borderRadius: 12, alignItems: "center", marginBottom: 16 },
|
|
14913
15139
|
newMsgText: { fontSize: 15, fontWeight: "600", color: "#fff" },
|
|
14914
15140
|
threadItem: { flexDirection: "row", justifyContent: "space-between", paddingVertical: 12, paddingHorizontal: 12, borderRadius: 10, marginBottom: 4, backgroundColor: colors.card },
|
|
@@ -14931,17 +15157,17 @@ var styles9 = StyleSheet10.create({
|
|
|
14931
15157
|
});
|
|
14932
15158
|
|
|
14933
15159
|
// src/widget/screens/ThreadDetailScreen.tsx
|
|
14934
|
-
import
|
|
14935
|
-
import { View as
|
|
15160
|
+
import React12, { useState as useState8, useEffect as useEffect7 } from "react";
|
|
15161
|
+
import { View as View11, Text as Text11, TouchableOpacity as TouchableOpacity10, TextInput as TextInput4, StyleSheet as StyleSheet12, Image as Image2 } from "react-native";
|
|
14936
15162
|
function ThreadDetailScreen({ thread, nav }) {
|
|
14937
15163
|
const { getThreadMessages, sendMessage, markAsRead, uploadImage } = useBugBear();
|
|
14938
|
-
const [messages, setMessages] =
|
|
14939
|
-
const [loading, setLoading] =
|
|
14940
|
-
const [replyText, setReplyText] =
|
|
14941
|
-
const [sending, setSending] =
|
|
14942
|
-
const [sendError, setSendError] =
|
|
15164
|
+
const [messages, setMessages] = useState8([]);
|
|
15165
|
+
const [loading, setLoading] = useState8(true);
|
|
15166
|
+
const [replyText, setReplyText] = useState8("");
|
|
15167
|
+
const [sending, setSending] = useState8(false);
|
|
15168
|
+
const [sendError, setSendError] = useState8(false);
|
|
14943
15169
|
const replyImages = useImageAttachments(uploadImage, 3, "discussion-attachments");
|
|
14944
|
-
|
|
15170
|
+
useEffect7(() => {
|
|
14945
15171
|
(async () => {
|
|
14946
15172
|
setLoading(true);
|
|
14947
15173
|
const msgs = await getThreadMessages(thread.id);
|
|
@@ -14953,7 +15179,7 @@ function ThreadDetailScreen({ thread, nav }) {
|
|
|
14953
15179
|
})();
|
|
14954
15180
|
}, [thread.id]);
|
|
14955
15181
|
const handleSend = async () => {
|
|
14956
|
-
if (!replyText.trim()) return;
|
|
15182
|
+
if (!replyText.trim() && replyImages.images.length === 0 || sending || replyImages.isUploading) return;
|
|
14957
15183
|
setSending(true);
|
|
14958
15184
|
setSendError(false);
|
|
14959
15185
|
const attachments = replyImages.getAttachments();
|
|
@@ -14973,20 +15199,20 @@ function ThreadDetailScreen({ thread, nav }) {
|
|
|
14973
15199
|
}
|
|
14974
15200
|
setSending(false);
|
|
14975
15201
|
};
|
|
14976
|
-
return /* @__PURE__ */
|
|
14977
|
-
|
|
15202
|
+
return /* @__PURE__ */ React12.createElement(View11, { style: styles11.container }, /* @__PURE__ */ React12.createElement(View11, { style: styles11.header }, /* @__PURE__ */ React12.createElement(Text11, { style: styles11.headerIcon }, getThreadTypeIcon(thread.threadType)), /* @__PURE__ */ React12.createElement(Text11, { style: styles11.headerSubject, numberOfLines: 2 }, thread.subject || "No subject")), loading ? /* @__PURE__ */ React12.createElement(View11, { style: styles11.loadingContainer }, /* @__PURE__ */ React12.createElement(Text11, { style: styles11.loadingText }, "Loading messages...")) : /* @__PURE__ */ React12.createElement(View11, { style: styles11.messagesContainer }, messages.map((msg) => /* @__PURE__ */ React12.createElement(
|
|
15203
|
+
View11,
|
|
14978
15204
|
{
|
|
14979
15205
|
key: msg.id,
|
|
14980
|
-
style: [
|
|
15206
|
+
style: [styles11.bubble, msg.senderType === "tester" ? styles11.bubbleTester : styles11.bubbleAdmin]
|
|
14981
15207
|
},
|
|
14982
|
-
/* @__PURE__ */
|
|
14983
|
-
/* @__PURE__ */
|
|
14984
|
-
msg.attachments && msg.attachments.length > 0 && /* @__PURE__ */
|
|
14985
|
-
/* @__PURE__ */
|
|
14986
|
-
))), sendError && /* @__PURE__ */
|
|
15208
|
+
/* @__PURE__ */ React12.createElement(Text11, { style: [styles11.sender, msg.senderType === "tester" && styles11.senderTester] }, msg.senderType === "tester" ? "You" : msg.senderName),
|
|
15209
|
+
/* @__PURE__ */ React12.createElement(Text11, { style: [styles11.content, msg.senderType === "tester" && styles11.contentTester] }, msg.content),
|
|
15210
|
+
msg.attachments && msg.attachments.length > 0 && /* @__PURE__ */ React12.createElement(View11, { style: styles11.attachments }, msg.attachments.filter((a) => a.type === "image").map((att, idx) => /* @__PURE__ */ React12.createElement(Image2, { key: idx, source: { uri: att.url }, style: styles11.attachmentImage, resizeMode: "cover" }))),
|
|
15211
|
+
/* @__PURE__ */ React12.createElement(Text11, { style: [styles11.time, msg.senderType === "tester" && styles11.timeTester] }, formatMessageTime(msg.createdAt))
|
|
15212
|
+
))), sendError && /* @__PURE__ */ React12.createElement(View11, { style: styles11.errorBar }, /* @__PURE__ */ React12.createElement(Text11, { style: styles11.errorText }, "Failed to send. Tap Send to retry.")), replyImages.images.length > 0 && /* @__PURE__ */ React12.createElement(View11, { style: styles11.replyPreview }, /* @__PURE__ */ React12.createElement(ImagePreviewStrip, { images: replyImages.images, onRemove: replyImages.removeImage })), /* @__PURE__ */ React12.createElement(View11, { style: styles11.composer }, IMAGE_PICKER_AVAILABLE && /* @__PURE__ */ React12.createElement(TouchableOpacity10, { style: styles11.attachBtn, onPress: replyImages.pickFromGallery, disabled: replyImages.images.length >= 3 }, /* @__PURE__ */ React12.createElement(Text11, { style: styles11.attachBtnText }, "\u{1F4CE}")), /* @__PURE__ */ React12.createElement(
|
|
14987
15213
|
TextInput4,
|
|
14988
15214
|
{
|
|
14989
|
-
style:
|
|
15215
|
+
style: styles11.replyInput,
|
|
14990
15216
|
value: replyText,
|
|
14991
15217
|
onChangeText: setReplyText,
|
|
14992
15218
|
placeholder: "Type a reply...",
|
|
@@ -14994,17 +15220,17 @@ function ThreadDetailScreen({ thread, nav }) {
|
|
|
14994
15220
|
multiline: true,
|
|
14995
15221
|
maxLength: 1e3
|
|
14996
15222
|
}
|
|
14997
|
-
), /* @__PURE__ */
|
|
14998
|
-
|
|
15223
|
+
), /* @__PURE__ */ React12.createElement(
|
|
15224
|
+
TouchableOpacity10,
|
|
14999
15225
|
{
|
|
15000
|
-
style: [
|
|
15226
|
+
style: [styles11.sendBtn, (!replyText.trim() || sending || replyImages.isUploading) && styles11.sendBtnDisabled],
|
|
15001
15227
|
onPress: handleSend,
|
|
15002
15228
|
disabled: !replyText.trim() || sending || replyImages.isUploading
|
|
15003
15229
|
},
|
|
15004
|
-
/* @__PURE__ */
|
|
15230
|
+
/* @__PURE__ */ React12.createElement(Text11, { style: styles11.sendBtnText }, sending ? "..." : "Send")
|
|
15005
15231
|
)));
|
|
15006
15232
|
}
|
|
15007
|
-
var
|
|
15233
|
+
var styles11 = StyleSheet12.create({
|
|
15008
15234
|
container: { flex: 1 },
|
|
15009
15235
|
header: { flexDirection: "row", alignItems: "center", gap: 8, marginBottom: 16, paddingBottom: 12, borderBottomWidth: 1, borderBottomColor: colors.border },
|
|
15010
15236
|
headerIcon: { fontSize: 20 },
|
|
@@ -15036,13 +15262,13 @@ var styles10 = StyleSheet11.create({
|
|
|
15036
15262
|
});
|
|
15037
15263
|
|
|
15038
15264
|
// src/widget/screens/ComposeMessageScreen.tsx
|
|
15039
|
-
import
|
|
15040
|
-
import { View as
|
|
15265
|
+
import React13, { useState as useState9 } from "react";
|
|
15266
|
+
import { View as View12, Text as Text12, TextInput as TextInput5, TouchableOpacity as TouchableOpacity11, StyleSheet as StyleSheet13 } from "react-native";
|
|
15041
15267
|
function ComposeMessageScreen({ nav }) {
|
|
15042
15268
|
const { createThread, uploadImage } = useBugBear();
|
|
15043
|
-
const [subject, setSubject] =
|
|
15044
|
-
const [message, setMessage] =
|
|
15045
|
-
const [sending, setSending] =
|
|
15269
|
+
const [subject, setSubject] = useState9("");
|
|
15270
|
+
const [message, setMessage] = useState9("");
|
|
15271
|
+
const [sending, setSending] = useState9(false);
|
|
15046
15272
|
const images = useImageAttachments(uploadImage, 3, "discussion-attachments");
|
|
15047
15273
|
const handleSend = async () => {
|
|
15048
15274
|
if (!subject.trim() || !message.trim()) return;
|
|
@@ -15058,20 +15284,20 @@ function ComposeMessageScreen({ nav }) {
|
|
|
15058
15284
|
nav.pop();
|
|
15059
15285
|
}
|
|
15060
15286
|
};
|
|
15061
|
-
return /* @__PURE__ */
|
|
15287
|
+
return /* @__PURE__ */ React13.createElement(View12, null, /* @__PURE__ */ React13.createElement(View12, { style: styles12.header }, /* @__PURE__ */ React13.createElement(Text12, { style: styles12.title }, "New Message"), /* @__PURE__ */ React13.createElement(Text12, { style: styles12.subtitle }, "Send a message to the QA team")), /* @__PURE__ */ React13.createElement(View12, { style: styles12.form }, /* @__PURE__ */ React13.createElement(Text12, { style: shared.label }, "Subject"), /* @__PURE__ */ React13.createElement(
|
|
15062
15288
|
TextInput5,
|
|
15063
15289
|
{
|
|
15064
|
-
style:
|
|
15290
|
+
style: styles12.subjectInput,
|
|
15065
15291
|
value: subject,
|
|
15066
15292
|
onChangeText: setSubject,
|
|
15067
15293
|
placeholder: "What's this about?",
|
|
15068
15294
|
placeholderTextColor: colors.textMuted,
|
|
15069
15295
|
maxLength: 100
|
|
15070
15296
|
}
|
|
15071
|
-
), /* @__PURE__ */
|
|
15297
|
+
), /* @__PURE__ */ React13.createElement(Text12, { style: [shared.label, { marginTop: 16 }] }, "Message"), /* @__PURE__ */ React13.createElement(
|
|
15072
15298
|
TextInput5,
|
|
15073
15299
|
{
|
|
15074
|
-
style:
|
|
15300
|
+
style: styles12.messageInput,
|
|
15075
15301
|
value: message,
|
|
15076
15302
|
onChangeText: setMessage,
|
|
15077
15303
|
placeholder: "Write your message...",
|
|
@@ -15081,7 +15307,7 @@ function ComposeMessageScreen({ nav }) {
|
|
|
15081
15307
|
textAlignVertical: "top",
|
|
15082
15308
|
maxLength: 2e3
|
|
15083
15309
|
}
|
|
15084
|
-
), /* @__PURE__ */
|
|
15310
|
+
), /* @__PURE__ */ React13.createElement(
|
|
15085
15311
|
ImagePickerButtons,
|
|
15086
15312
|
{
|
|
15087
15313
|
images: images.images,
|
|
@@ -15090,17 +15316,17 @@ function ComposeMessageScreen({ nav }) {
|
|
|
15090
15316
|
onPickCamera: images.pickFromCamera,
|
|
15091
15317
|
onRemove: images.removeImage
|
|
15092
15318
|
}
|
|
15093
|
-
), /* @__PURE__ */
|
|
15094
|
-
|
|
15319
|
+
), /* @__PURE__ */ React13.createElement(
|
|
15320
|
+
TouchableOpacity11,
|
|
15095
15321
|
{
|
|
15096
15322
|
style: [shared.primaryButton, (!subject.trim() || !message.trim() || sending || images.isUploading) && shared.primaryButtonDisabled, { marginTop: 20 }],
|
|
15097
15323
|
onPress: handleSend,
|
|
15098
15324
|
disabled: !subject.trim() || !message.trim() || sending || images.isUploading
|
|
15099
15325
|
},
|
|
15100
|
-
/* @__PURE__ */
|
|
15326
|
+
/* @__PURE__ */ React13.createElement(Text12, { style: shared.primaryButtonText }, images.isUploading ? "Uploading..." : sending ? "Sending..." : "Send Message")
|
|
15101
15327
|
)));
|
|
15102
15328
|
}
|
|
15103
|
-
var
|
|
15329
|
+
var styles12 = StyleSheet13.create({
|
|
15104
15330
|
header: { marginBottom: 20 },
|
|
15105
15331
|
title: { fontSize: 20, fontWeight: "600", color: colors.textPrimary, marginBottom: 4 },
|
|
15106
15332
|
subtitle: { fontSize: 14, color: colors.textMuted },
|
|
@@ -15110,20 +15336,20 @@ var styles11 = StyleSheet12.create({
|
|
|
15110
15336
|
});
|
|
15111
15337
|
|
|
15112
15338
|
// src/widget/screens/ProfileScreen.tsx
|
|
15113
|
-
import
|
|
15114
|
-
import { View as
|
|
15339
|
+
import React14, { useState as useState10, useEffect as useEffect8 } from "react";
|
|
15340
|
+
import { View as View13, Text as Text13, TouchableOpacity as TouchableOpacity12, TextInput as TextInput6, StyleSheet as StyleSheet14 } from "react-native";
|
|
15115
15341
|
function ProfileScreen({ nav }) {
|
|
15116
15342
|
const { testerInfo, assignments, updateTesterProfile, refreshTesterInfo } = useBugBear();
|
|
15117
|
-
const [editing, setEditing] =
|
|
15118
|
-
const [name, setName] =
|
|
15119
|
-
const [additionalEmails, setAdditionalEmails] =
|
|
15120
|
-
const [newEmailInput, setNewEmailInput] =
|
|
15121
|
-
const [platforms, setPlatforms] =
|
|
15122
|
-
const [saving, setSaving] =
|
|
15123
|
-
const [saved, setSaved] =
|
|
15124
|
-
const [showDetails, setShowDetails] =
|
|
15343
|
+
const [editing, setEditing] = useState10(false);
|
|
15344
|
+
const [name, setName] = useState10(testerInfo?.name || "");
|
|
15345
|
+
const [additionalEmails, setAdditionalEmails] = useState10(testerInfo?.additionalEmails || []);
|
|
15346
|
+
const [newEmailInput, setNewEmailInput] = useState10("");
|
|
15347
|
+
const [platforms, setPlatforms] = useState10(testerInfo?.platforms || []);
|
|
15348
|
+
const [saving, setSaving] = useState10(false);
|
|
15349
|
+
const [saved, setSaved] = useState10(false);
|
|
15350
|
+
const [showDetails, setShowDetails] = useState10(false);
|
|
15125
15351
|
const completedCount = assignments.filter((a) => a.status === "passed" || a.status === "failed").length;
|
|
15126
|
-
|
|
15352
|
+
useEffect8(() => {
|
|
15127
15353
|
if (testerInfo) {
|
|
15128
15354
|
setName(testerInfo.name);
|
|
15129
15355
|
setAdditionalEmails(testerInfo.additionalEmails || []);
|
|
@@ -15157,19 +15383,19 @@ function ProfileScreen({ nav }) {
|
|
|
15157
15383
|
}
|
|
15158
15384
|
};
|
|
15159
15385
|
if (saved) {
|
|
15160
|
-
return /* @__PURE__ */
|
|
15386
|
+
return /* @__PURE__ */ React14.createElement(View13, { style: shared.emptyState }, /* @__PURE__ */ React14.createElement(Text13, { style: shared.emptyEmoji }, "\u2705"), /* @__PURE__ */ React14.createElement(Text13, { style: shared.emptyTitle }, "Profile saved!"));
|
|
15161
15387
|
}
|
|
15162
15388
|
if (!testerInfo) {
|
|
15163
|
-
return /* @__PURE__ */
|
|
15389
|
+
return /* @__PURE__ */ React14.createElement(View13, { style: shared.emptyState }, /* @__PURE__ */ React14.createElement(Text13, { style: shared.emptyEmoji }, "\u{1F464}"), /* @__PURE__ */ React14.createElement(Text13, { style: shared.emptyTitle }, "No profile found"));
|
|
15164
15390
|
}
|
|
15165
15391
|
if (editing) {
|
|
15166
|
-
return /* @__PURE__ */
|
|
15392
|
+
return /* @__PURE__ */ React14.createElement(View13, null, /* @__PURE__ */ React14.createElement(View13, { style: styles13.editHeader }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.editTitle }, "Edit Profile"), /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => {
|
|
15167
15393
|
setEditing(false);
|
|
15168
15394
|
setNewEmailInput("");
|
|
15169
|
-
} }, /* @__PURE__ */
|
|
15395
|
+
} }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.cancelText }, "Cancel"))), /* @__PURE__ */ React14.createElement(View13, { style: styles13.field }, /* @__PURE__ */ React14.createElement(Text13, { style: shared.label }, "Name"), /* @__PURE__ */ React14.createElement(TextInput6, { style: styles13.input, value: name, onChangeText: setName, placeholder: "Your name", placeholderTextColor: colors.textMuted })), /* @__PURE__ */ React14.createElement(View13, { style: styles13.field }, /* @__PURE__ */ React14.createElement(Text13, { style: shared.label }, "Primary Email"), /* @__PURE__ */ React14.createElement(Text13, { style: styles13.emailFixed }, testerInfo.email)), /* @__PURE__ */ React14.createElement(View13, { style: styles13.field }, /* @__PURE__ */ React14.createElement(Text13, { style: shared.label }, "Additional Emails"), additionalEmails.map((email) => /* @__PURE__ */ React14.createElement(View13, { key: email, style: styles13.emailRow }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.emailText }, email), /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => setAdditionalEmails(additionalEmails.filter((e) => e !== email)) }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.removeEmail }, "\u2715")))), /* @__PURE__ */ React14.createElement(View13, { style: styles13.addEmailRow }, /* @__PURE__ */ React14.createElement(
|
|
15170
15396
|
TextInput6,
|
|
15171
15397
|
{
|
|
15172
|
-
style: [
|
|
15398
|
+
style: [styles13.input, { flex: 1, marginRight: 8 }],
|
|
15173
15399
|
value: newEmailInput,
|
|
15174
15400
|
onChangeText: setNewEmailInput,
|
|
15175
15401
|
placeholder: "Add email",
|
|
@@ -15177,26 +15403,26 @@ function ProfileScreen({ nav }) {
|
|
|
15177
15403
|
keyboardType: "email-address",
|
|
15178
15404
|
autoCapitalize: "none"
|
|
15179
15405
|
}
|
|
15180
|
-
), /* @__PURE__ */
|
|
15181
|
-
|
|
15406
|
+
), /* @__PURE__ */ React14.createElement(TouchableOpacity12, { style: styles13.addButton, onPress: handleAddEmail }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.addButtonText }, "Add")))), /* @__PURE__ */ React14.createElement(View13, { style: styles13.field }, /* @__PURE__ */ React14.createElement(Text13, { style: shared.label }, "Testing Platforms"), /* @__PURE__ */ React14.createElement(View13, { style: styles13.platformRow }, [{ key: "ios", label: "\u{1F4F1} iOS" }, { key: "android", label: "\u{1F916} Android" }, { key: "web", label: "\u{1F310} Web" }].map(({ key, label }) => /* @__PURE__ */ React14.createElement(
|
|
15407
|
+
TouchableOpacity12,
|
|
15182
15408
|
{
|
|
15183
15409
|
key,
|
|
15184
|
-
style: [
|
|
15410
|
+
style: [styles13.platformBtn, platforms.includes(key) && styles13.platformBtnActive],
|
|
15185
15411
|
onPress: () => setPlatforms((prev) => prev.includes(key) ? prev.filter((p) => p !== key) : [...prev, key])
|
|
15186
15412
|
},
|
|
15187
|
-
/* @__PURE__ */
|
|
15188
|
-
)))), /* @__PURE__ */
|
|
15413
|
+
/* @__PURE__ */ React14.createElement(Text13, { style: [styles13.platformText, platforms.includes(key) && styles13.platformTextActive] }, label)
|
|
15414
|
+
)))), /* @__PURE__ */ React14.createElement(TouchableOpacity12, { style: [shared.primaryButton, { marginTop: 20 }], onPress: handleSave, disabled: saving }, /* @__PURE__ */ React14.createElement(Text13, { style: shared.primaryButtonText }, saving ? "Saving..." : "Save Profile")));
|
|
15189
15415
|
}
|
|
15190
|
-
return /* @__PURE__ */
|
|
15191
|
-
|
|
15416
|
+
return /* @__PURE__ */ React14.createElement(View13, null, /* @__PURE__ */ React14.createElement(View13, { style: styles13.profileCard }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.avatar }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.avatarText }, testerInfo.name.charAt(0).toUpperCase())), /* @__PURE__ */ React14.createElement(Text13, { style: styles13.profileName }, testerInfo.name), /* @__PURE__ */ React14.createElement(Text13, { style: styles13.profileEmail }, testerInfo.email)), /* @__PURE__ */ React14.createElement(View13, { style: styles13.statsRow }, /* @__PURE__ */ React14.createElement(View13, { style: styles13.statItem }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.statNumber }, completedCount), /* @__PURE__ */ React14.createElement(Text13, { style: styles13.statLabel }, "Completed")), /* @__PURE__ */ React14.createElement(View13, { style: styles13.statDivider }), /* @__PURE__ */ React14.createElement(View13, { style: styles13.statItem }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.statNumber }, assignments.length), /* @__PURE__ */ React14.createElement(Text13, { style: styles13.statLabel }, "Total Assigned"))), /* @__PURE__ */ React14.createElement(TouchableOpacity12, { onPress: () => setShowDetails(!showDetails), style: styles13.detailsToggle }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.detailsToggleText }, showDetails ? "\u25BC" : "\u25B6", " Details")), showDetails && /* @__PURE__ */ React14.createElement(View13, { style: styles13.detailsSection }, additionalEmails.length > 0 && /* @__PURE__ */ React14.createElement(View13, { style: styles13.detailBlock }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.detailLabel }, "Additional Emails"), additionalEmails.map((e) => /* @__PURE__ */ React14.createElement(Text13, { key: e, style: styles13.detailValue }, e))), platforms.length > 0 && /* @__PURE__ */ React14.createElement(View13, { style: styles13.detailBlock }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.detailLabel }, "Platforms"), /* @__PURE__ */ React14.createElement(View13, { style: styles13.platformTags }, platforms.map((p) => /* @__PURE__ */ React14.createElement(View13, { key: p, style: styles13.platformTag }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.platformTagText }, p === "ios" ? "\u{1F4F1} iOS" : p === "android" ? "\u{1F916} Android" : "\u{1F310} Web")))))), /* @__PURE__ */ React14.createElement(
|
|
15417
|
+
TouchableOpacity12,
|
|
15192
15418
|
{
|
|
15193
15419
|
style: [shared.primaryButton, { marginTop: 20 }],
|
|
15194
15420
|
onPress: () => setEditing(true)
|
|
15195
15421
|
},
|
|
15196
|
-
/* @__PURE__ */
|
|
15422
|
+
/* @__PURE__ */ React14.createElement(Text13, { style: shared.primaryButtonText }, "Edit Profile")
|
|
15197
15423
|
));
|
|
15198
15424
|
}
|
|
15199
|
-
var
|
|
15425
|
+
var styles13 = StyleSheet14.create({
|
|
15200
15426
|
profileCard: { alignItems: "center", backgroundColor: colors.card, borderRadius: 16, padding: 24, marginBottom: 16 },
|
|
15201
15427
|
avatar: { width: 64, height: 64, borderRadius: 32, backgroundColor: colors.blue, justifyContent: "center", alignItems: "center", marginBottom: 12 },
|
|
15202
15428
|
avatarText: { fontSize: 28, fontWeight: "700", color: "#fff" },
|
|
@@ -15237,8 +15463,8 @@ var styles12 = StyleSheet13.create({
|
|
|
15237
15463
|
});
|
|
15238
15464
|
|
|
15239
15465
|
// src/widget/screens/IssueListScreen.tsx
|
|
15240
|
-
import
|
|
15241
|
-
import { View as
|
|
15466
|
+
import React15, { useState as useState11, useEffect as useEffect9 } from "react";
|
|
15467
|
+
import { View as View14, Text as Text14, TouchableOpacity as TouchableOpacity13, StyleSheet as StyleSheet15, ActivityIndicator as ActivityIndicator2 } from "react-native";
|
|
15242
15468
|
var CATEGORY_CONFIG = {
|
|
15243
15469
|
open: { label: "Open Issues", accent: "#f97316", emptyIcon: "\u2705", emptyText: "No open issues" },
|
|
15244
15470
|
done: { label: "Done", accent: "#22c55e", emptyIcon: "\u{1F389}", emptyText: "No completed issues yet" },
|
|
@@ -15252,10 +15478,10 @@ var SEVERITY_COLORS = {
|
|
|
15252
15478
|
};
|
|
15253
15479
|
function IssueListScreen({ nav, category }) {
|
|
15254
15480
|
const { client } = useBugBear();
|
|
15255
|
-
const [issues, setIssues] =
|
|
15256
|
-
const [loading, setLoading] =
|
|
15481
|
+
const [issues, setIssues] = useState11([]);
|
|
15482
|
+
const [loading, setLoading] = useState11(true);
|
|
15257
15483
|
const config = CATEGORY_CONFIG[category];
|
|
15258
|
-
|
|
15484
|
+
useEffect9(() => {
|
|
15259
15485
|
let cancelled = false;
|
|
15260
15486
|
setLoading(true);
|
|
15261
15487
|
(async () => {
|
|
@@ -15271,26 +15497,26 @@ function IssueListScreen({ nav, category }) {
|
|
|
15271
15497
|
};
|
|
15272
15498
|
}, [client, category]);
|
|
15273
15499
|
if (loading) {
|
|
15274
|
-
return /* @__PURE__ */
|
|
15500
|
+
return /* @__PURE__ */ React15.createElement(View14, { style: styles14.emptyContainer }, /* @__PURE__ */ React15.createElement(ActivityIndicator2, { size: "small", color: colors.textMuted }), /* @__PURE__ */ React15.createElement(Text14, { style: styles14.emptyText }, "Loading..."));
|
|
15275
15501
|
}
|
|
15276
15502
|
if (issues.length === 0) {
|
|
15277
|
-
return /* @__PURE__ */
|
|
15503
|
+
return /* @__PURE__ */ React15.createElement(View14, { style: styles14.emptyContainer }, /* @__PURE__ */ React15.createElement(Text14, { style: styles14.emptyIcon }, config.emptyIcon), /* @__PURE__ */ React15.createElement(Text14, { style: styles14.emptyText }, config.emptyText));
|
|
15278
15504
|
}
|
|
15279
|
-
return /* @__PURE__ */
|
|
15280
|
-
|
|
15505
|
+
return /* @__PURE__ */ React15.createElement(View14, null, issues.map((issue) => /* @__PURE__ */ React15.createElement(
|
|
15506
|
+
TouchableOpacity13,
|
|
15281
15507
|
{
|
|
15282
15508
|
key: issue.id,
|
|
15283
|
-
style:
|
|
15509
|
+
style: styles14.issueCard,
|
|
15284
15510
|
onPress: () => nav.push({ name: "ISSUE_DETAIL", issue }),
|
|
15285
15511
|
activeOpacity: 0.7
|
|
15286
15512
|
},
|
|
15287
|
-
/* @__PURE__ */
|
|
15288
|
-
/* @__PURE__ */
|
|
15289
|
-
category === "done" && issue.verifiedByName && /* @__PURE__ */
|
|
15290
|
-
category === "reopened" && issue.originalBugTitle && /* @__PURE__ */
|
|
15513
|
+
/* @__PURE__ */ React15.createElement(View14, { style: styles14.topRow }, issue.severity && /* @__PURE__ */ React15.createElement(View14, { style: [styles14.severityDot, { backgroundColor: SEVERITY_COLORS[issue.severity] || colors.textDim }] }), /* @__PURE__ */ React15.createElement(Text14, { style: styles14.issueTitle, numberOfLines: 1 }, issue.title)),
|
|
15514
|
+
/* @__PURE__ */ React15.createElement(View14, { style: styles14.bottomRow }, issue.route && /* @__PURE__ */ React15.createElement(Text14, { style: styles14.routeText, numberOfLines: 1 }, issue.route), /* @__PURE__ */ React15.createElement(Text14, { style: styles14.timeText }, formatRelativeTime(issue.updatedAt))),
|
|
15515
|
+
category === "done" && issue.verifiedByName && /* @__PURE__ */ React15.createElement(View14, { style: styles14.verifiedBadge }, /* @__PURE__ */ React15.createElement(Text14, { style: styles14.verifiedBadgeText }, "\u2714", " Verified by ", issue.verifiedByName)),
|
|
15516
|
+
category === "reopened" && issue.originalBugTitle && /* @__PURE__ */ React15.createElement(View14, { style: styles14.reopenedBadge }, /* @__PURE__ */ React15.createElement(Text14, { style: styles14.reopenedBadgeText, numberOfLines: 1 }, "\u{1F504}", " Retest of: ", issue.originalBugTitle))
|
|
15291
15517
|
)));
|
|
15292
15518
|
}
|
|
15293
|
-
var
|
|
15519
|
+
var styles14 = StyleSheet15.create({
|
|
15294
15520
|
emptyContainer: {
|
|
15295
15521
|
alignItems: "center",
|
|
15296
15522
|
paddingVertical: 40
|
|
@@ -15381,8 +15607,8 @@ var styles13 = StyleSheet14.create({
|
|
|
15381
15607
|
});
|
|
15382
15608
|
|
|
15383
15609
|
// src/widget/screens/IssueDetailScreen.tsx
|
|
15384
|
-
import
|
|
15385
|
-
import { View as
|
|
15610
|
+
import React16 from "react";
|
|
15611
|
+
import { View as View15, Text as Text15, Image as Image3, StyleSheet as StyleSheet16, Linking as Linking2, TouchableOpacity as TouchableOpacity14 } from "react-native";
|
|
15386
15612
|
var STATUS_LABELS = {
|
|
15387
15613
|
new: { label: "New", bg: "#1e3a5f", color: "#60a5fa" },
|
|
15388
15614
|
triaging: { label: "Triaging", bg: "#1e3a5f", color: "#60a5fa" },
|
|
@@ -15406,9 +15632,9 @@ var SEVERITY_CONFIG = {
|
|
|
15406
15632
|
function IssueDetailScreen({ nav, issue }) {
|
|
15407
15633
|
const statusConfig = STATUS_LABELS[issue.status] || { label: issue.status, bg: "#27272a", color: "#a1a1aa" };
|
|
15408
15634
|
const severityConfig = issue.severity ? SEVERITY_CONFIG[issue.severity] : null;
|
|
15409
|
-
return /* @__PURE__ */
|
|
15635
|
+
return /* @__PURE__ */ React16.createElement(View15, null, /* @__PURE__ */ React16.createElement(View15, { style: styles15.badgeRow }, /* @__PURE__ */ React16.createElement(View15, { style: [styles15.badge, { backgroundColor: statusConfig.bg }] }, /* @__PURE__ */ React16.createElement(Text15, { style: [styles15.badgeText, { color: statusConfig.color }] }, statusConfig.label)), severityConfig && /* @__PURE__ */ React16.createElement(View15, { style: [styles15.badge, { backgroundColor: severityConfig.bg }] }, /* @__PURE__ */ React16.createElement(Text15, { style: [styles15.badgeText, { color: severityConfig.color }] }, severityConfig.label))), /* @__PURE__ */ React16.createElement(Text15, { style: styles15.title }, issue.title), issue.route && /* @__PURE__ */ React16.createElement(Text15, { style: styles15.route }, issue.route), issue.description && /* @__PURE__ */ React16.createElement(View15, { style: styles15.descriptionCard }, /* @__PURE__ */ React16.createElement(Text15, { style: styles15.descriptionText }, issue.description)), issue.verifiedByName && /* @__PURE__ */ React16.createElement(View15, { style: styles15.verifiedCard }, /* @__PURE__ */ React16.createElement(View15, { style: styles15.verifiedHeader }, /* @__PURE__ */ React16.createElement(Text15, { style: styles15.verifiedIcon }, "\u2705"), /* @__PURE__ */ React16.createElement(Text15, { style: styles15.verifiedTitle }, "Retesting Proof")), /* @__PURE__ */ React16.createElement(Text15, { style: styles15.verifiedBody }, "Verified by ", issue.verifiedByName, issue.verifiedAt && ` on ${new Date(issue.verifiedAt).toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" })}`)), issue.originalBugTitle && /* @__PURE__ */ React16.createElement(View15, { style: styles15.originalBugCard }, /* @__PURE__ */ React16.createElement(View15, { style: styles15.originalBugHeader }, /* @__PURE__ */ React16.createElement(Text15, { style: styles15.originalBugIcon }, "\u{1F504}"), /* @__PURE__ */ React16.createElement(Text15, { style: styles15.originalBugTitle }, "Original Bug")), /* @__PURE__ */ React16.createElement(Text15, { style: styles15.originalBugBody }, "Retest of: ", issue.originalBugTitle)), issue.screenshotUrls && issue.screenshotUrls.length > 0 && /* @__PURE__ */ React16.createElement(View15, { style: styles15.screenshotSection }, /* @__PURE__ */ React16.createElement(Text15, { style: styles15.screenshotLabel }, "Screenshots (", issue.screenshotUrls.length, ")"), /* @__PURE__ */ React16.createElement(View15, { style: styles15.screenshotRow }, issue.screenshotUrls.map((url, i) => /* @__PURE__ */ React16.createElement(TouchableOpacity14, { key: i, onPress: () => Linking2.openURL(url), activeOpacity: 0.7 }, /* @__PURE__ */ React16.createElement(Image3, { source: { uri: url }, style: styles15.screenshotThumb }))))), /* @__PURE__ */ React16.createElement(View15, { style: styles15.metaSection }, issue.reporterName && /* @__PURE__ */ React16.createElement(Text15, { style: styles15.metaText }, "Reported by ", issue.reporterName), /* @__PURE__ */ React16.createElement(Text15, { style: styles15.metaTextSmall }, "Created ", formatRelativeTime(issue.createdAt), " ", "\xB7", " Updated ", formatRelativeTime(issue.updatedAt))));
|
|
15410
15636
|
}
|
|
15411
|
-
var
|
|
15637
|
+
var styles15 = StyleSheet16.create({
|
|
15412
15638
|
badgeRow: {
|
|
15413
15639
|
flexDirection: "row",
|
|
15414
15640
|
gap: 8,
|
|
@@ -15552,7 +15778,7 @@ function BugBearButton({
|
|
|
15552
15778
|
}) {
|
|
15553
15779
|
const { shouldShowWidget, testerInfo, isLoading, unreadCount, assignments } = useBugBear();
|
|
15554
15780
|
const { currentScreen, canGoBack, push, pop, replace, reset } = useNavigation();
|
|
15555
|
-
const [modalVisible, setModalVisible] =
|
|
15781
|
+
const [modalVisible, setModalVisible] = useState12(false);
|
|
15556
15782
|
const getInitialPosition = () => {
|
|
15557
15783
|
const buttonSize = 56;
|
|
15558
15784
|
const margin = 16;
|
|
@@ -15668,77 +15894,77 @@ function BugBearButton({
|
|
|
15668
15894
|
const renderScreen = () => {
|
|
15669
15895
|
switch (currentScreen.name) {
|
|
15670
15896
|
case "HOME":
|
|
15671
|
-
return /* @__PURE__ */
|
|
15897
|
+
return /* @__PURE__ */ React17.createElement(HomeScreen, { nav });
|
|
15672
15898
|
case "TEST_DETAIL":
|
|
15673
|
-
return /* @__PURE__ */
|
|
15899
|
+
return /* @__PURE__ */ React17.createElement(TestDetailScreen, { testId: currentScreen.testId, nav });
|
|
15674
15900
|
case "TEST_LIST":
|
|
15675
|
-
return /* @__PURE__ */
|
|
15901
|
+
return /* @__PURE__ */ React17.createElement(TestListScreen, { nav });
|
|
15676
15902
|
case "TEST_FEEDBACK":
|
|
15677
|
-
return /* @__PURE__ */
|
|
15903
|
+
return /* @__PURE__ */ React17.createElement(TestFeedbackScreen, { status: currentScreen.status, assignmentId: currentScreen.assignmentId, nav });
|
|
15678
15904
|
case "REPORT":
|
|
15679
|
-
return /* @__PURE__ */
|
|
15905
|
+
return /* @__PURE__ */ React17.createElement(ReportScreen, { nav, prefill: currentScreen.prefill });
|
|
15680
15906
|
case "REPORT_SUCCESS":
|
|
15681
|
-
return /* @__PURE__ */
|
|
15907
|
+
return /* @__PURE__ */ React17.createElement(ReportSuccessScreen, { nav });
|
|
15682
15908
|
case "MESSAGE_LIST":
|
|
15683
|
-
return /* @__PURE__ */
|
|
15909
|
+
return /* @__PURE__ */ React17.createElement(MessageListScreen, { nav });
|
|
15684
15910
|
case "THREAD_DETAIL":
|
|
15685
|
-
return /* @__PURE__ */
|
|
15911
|
+
return /* @__PURE__ */ React17.createElement(ThreadDetailScreen, { thread: currentScreen.thread, nav });
|
|
15686
15912
|
case "COMPOSE_MESSAGE":
|
|
15687
|
-
return /* @__PURE__ */
|
|
15913
|
+
return /* @__PURE__ */ React17.createElement(ComposeMessageScreen, { nav });
|
|
15688
15914
|
case "ISSUE_LIST":
|
|
15689
|
-
return /* @__PURE__ */
|
|
15915
|
+
return /* @__PURE__ */ React17.createElement(IssueListScreen, { nav, category: currentScreen.category });
|
|
15690
15916
|
case "ISSUE_DETAIL":
|
|
15691
|
-
return /* @__PURE__ */
|
|
15917
|
+
return /* @__PURE__ */ React17.createElement(IssueDetailScreen, { nav, issue: currentScreen.issue });
|
|
15692
15918
|
case "PROFILE":
|
|
15693
|
-
return /* @__PURE__ */
|
|
15919
|
+
return /* @__PURE__ */ React17.createElement(ProfileScreen, { nav });
|
|
15694
15920
|
default:
|
|
15695
|
-
return /* @__PURE__ */
|
|
15921
|
+
return /* @__PURE__ */ React17.createElement(HomeScreen, { nav });
|
|
15696
15922
|
}
|
|
15697
15923
|
};
|
|
15698
|
-
return /* @__PURE__ */
|
|
15924
|
+
return /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(
|
|
15699
15925
|
Animated.View,
|
|
15700
15926
|
{
|
|
15701
|
-
style: [
|
|
15927
|
+
style: [styles16.fabContainer, { transform: pan.getTranslateTransform() }, buttonStyle],
|
|
15702
15928
|
...panResponder.panHandlers
|
|
15703
15929
|
},
|
|
15704
|
-
/* @__PURE__ */
|
|
15705
|
-
|
|
15930
|
+
/* @__PURE__ */ React17.createElement(
|
|
15931
|
+
TouchableOpacity15,
|
|
15706
15932
|
{
|
|
15707
|
-
style:
|
|
15933
|
+
style: styles16.fab,
|
|
15708
15934
|
onPress: () => setModalVisible(true),
|
|
15709
15935
|
activeOpacity: draggable ? 1 : 0.7
|
|
15710
15936
|
},
|
|
15711
|
-
/* @__PURE__ */
|
|
15712
|
-
badgeCount > 0 && /* @__PURE__ */
|
|
15937
|
+
/* @__PURE__ */ React17.createElement(Image4, { source: { uri: BUGBEAR_LOGO_BASE64 }, style: styles16.fabIcon }),
|
|
15938
|
+
badgeCount > 0 && /* @__PURE__ */ React17.createElement(View16, { style: styles16.badge }, /* @__PURE__ */ React17.createElement(Text16, { style: styles16.badgeText }, badgeCount > 9 ? "9+" : badgeCount))
|
|
15713
15939
|
)
|
|
15714
|
-
), /* @__PURE__ */
|
|
15715
|
-
|
|
15940
|
+
), /* @__PURE__ */ React17.createElement(
|
|
15941
|
+
Modal3,
|
|
15716
15942
|
{
|
|
15717
15943
|
visible: modalVisible,
|
|
15718
15944
|
animationType: "slide",
|
|
15719
15945
|
transparent: true,
|
|
15720
15946
|
onRequestClose: handleClose
|
|
15721
15947
|
},
|
|
15722
|
-
/* @__PURE__ */
|
|
15948
|
+
/* @__PURE__ */ React17.createElement(
|
|
15723
15949
|
KeyboardAvoidingView,
|
|
15724
15950
|
{
|
|
15725
15951
|
behavior: Platform4.OS === "ios" ? "padding" : "height",
|
|
15726
|
-
style:
|
|
15952
|
+
style: styles16.modalOverlay
|
|
15727
15953
|
},
|
|
15728
|
-
/* @__PURE__ */
|
|
15954
|
+
/* @__PURE__ */ React17.createElement(View16, { style: styles16.modalContainer }, /* @__PURE__ */ React17.createElement(View16, { style: styles16.header }, /* @__PURE__ */ React17.createElement(View16, { style: styles16.headerLeft }, canGoBack ? /* @__PURE__ */ React17.createElement(View16, { style: styles16.headerNavRow }, /* @__PURE__ */ React17.createElement(TouchableOpacity15, { onPress: () => nav.pop(), style: styles16.backButton }, /* @__PURE__ */ React17.createElement(Text16, { style: styles16.backText }, "\u2190 Back")), /* @__PURE__ */ React17.createElement(TouchableOpacity15, { onPress: () => nav.reset(), style: styles16.homeButton }, /* @__PURE__ */ React17.createElement(Text16, { style: styles16.homeText }, "\u{1F3E0}"))) : /* @__PURE__ */ React17.createElement(View16, { style: styles16.headerTitleRow }, /* @__PURE__ */ React17.createElement(Text16, { style: styles16.headerTitle }, "BugBear"), testerInfo && /* @__PURE__ */ React17.createElement(TouchableOpacity15, { onPress: () => push({ name: "PROFILE" }) }, /* @__PURE__ */ React17.createElement(Text16, { style: styles16.headerName }, testerInfo.name, " \u270E")))), getHeaderTitle() ? /* @__PURE__ */ React17.createElement(Text16, { style: styles16.headerScreenTitle, numberOfLines: 1 }, getHeaderTitle()) : null, /* @__PURE__ */ React17.createElement(TouchableOpacity15, { onPress: handleClose, style: styles16.closeButton }, /* @__PURE__ */ React17.createElement(Text16, { style: styles16.closeText }, "\u2715"))), /* @__PURE__ */ React17.createElement(
|
|
15729
15955
|
ScrollView3,
|
|
15730
15956
|
{
|
|
15731
|
-
style:
|
|
15732
|
-
contentContainerStyle:
|
|
15957
|
+
style: styles16.content,
|
|
15958
|
+
contentContainerStyle: styles16.contentContainer,
|
|
15733
15959
|
keyboardShouldPersistTaps: "handled",
|
|
15734
15960
|
showsVerticalScrollIndicator: false
|
|
15735
15961
|
},
|
|
15736
|
-
isLoading ? /* @__PURE__ */
|
|
15962
|
+
isLoading ? /* @__PURE__ */ React17.createElement(View16, { style: styles16.loadingContainer }, /* @__PURE__ */ React17.createElement(ActivityIndicator3, { size: "large", color: colors.blue }), /* @__PURE__ */ React17.createElement(Text16, { style: styles16.loadingText }, "Loading...")) : renderScreen()
|
|
15737
15963
|
))
|
|
15738
15964
|
)
|
|
15739
15965
|
));
|
|
15740
15966
|
}
|
|
15741
|
-
var
|
|
15967
|
+
var styles16 = StyleSheet17.create({
|
|
15742
15968
|
// FAB
|
|
15743
15969
|
fabContainer: {
|
|
15744
15970
|
position: "absolute",
|
|
@@ -15880,8 +16106,8 @@ var styles15 = StyleSheet16.create({
|
|
|
15880
16106
|
});
|
|
15881
16107
|
|
|
15882
16108
|
// src/BugBearErrorBoundary.tsx
|
|
15883
|
-
import
|
|
15884
|
-
import { View as
|
|
16109
|
+
import React18, { Component } from "react";
|
|
16110
|
+
import { View as View17, Text as Text17, TouchableOpacity as TouchableOpacity16, StyleSheet as StyleSheet18 } from "react-native";
|
|
15885
16111
|
var BugBearErrorBoundary = class extends Component {
|
|
15886
16112
|
constructor(props) {
|
|
15887
16113
|
super(props);
|
|
@@ -15926,7 +16152,7 @@ var BugBearErrorBoundary = class extends Component {
|
|
|
15926
16152
|
if (fallback) {
|
|
15927
16153
|
return fallback;
|
|
15928
16154
|
}
|
|
15929
|
-
return /* @__PURE__ */
|
|
16155
|
+
return /* @__PURE__ */ React18.createElement(View17, { style: styles17.container }, /* @__PURE__ */ React18.createElement(Text17, { style: styles17.title }, "Something went wrong"), /* @__PURE__ */ React18.createElement(Text17, { style: styles17.message }, error.message), /* @__PURE__ */ React18.createElement(TouchableOpacity16, { style: styles17.button, onPress: this.reset }, /* @__PURE__ */ React18.createElement(Text17, { style: styles17.buttonText }, "Try Again")), /* @__PURE__ */ React18.createElement(Text17, { style: styles17.caption }, "The error has been captured by BugBear"));
|
|
15930
16156
|
}
|
|
15931
16157
|
return children;
|
|
15932
16158
|
}
|
|
@@ -15937,7 +16163,7 @@ function useErrorContext() {
|
|
|
15937
16163
|
getEnhancedContext: () => contextCapture.getEnhancedContext()
|
|
15938
16164
|
};
|
|
15939
16165
|
}
|
|
15940
|
-
var
|
|
16166
|
+
var styles17 = StyleSheet18.create({
|
|
15941
16167
|
container: {
|
|
15942
16168
|
padding: 20,
|
|
15943
16169
|
margin: 20,
|