@bbearai/react-native 0.3.3 → 0.3.5
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 +192 -138
- package/dist/index.mjs +187 -132
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11659,6 +11659,11 @@ var BugBearClient = class {
|
|
|
11659
11659
|
try {
|
|
11660
11660
|
const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at").eq("id", assignmentId).single();
|
|
11661
11661
|
if (fetchError || !currentAssignment) {
|
|
11662
|
+
console.error("BugBear: Assignment not found", {
|
|
11663
|
+
message: fetchError?.message,
|
|
11664
|
+
code: fetchError?.code,
|
|
11665
|
+
assignmentId
|
|
11666
|
+
});
|
|
11662
11667
|
return { success: false, error: "Assignment not found" };
|
|
11663
11668
|
}
|
|
11664
11669
|
const updateData = { status };
|
|
@@ -11683,7 +11688,15 @@ var BugBearClient = class {
|
|
|
11683
11688
|
}
|
|
11684
11689
|
const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
|
|
11685
11690
|
if (error) {
|
|
11686
|
-
console.error("BugBear: Failed to update assignment status",
|
|
11691
|
+
console.error("BugBear: Failed to update assignment status", {
|
|
11692
|
+
message: error.message,
|
|
11693
|
+
details: error.details,
|
|
11694
|
+
hint: error.hint,
|
|
11695
|
+
code: error.code,
|
|
11696
|
+
assignmentId,
|
|
11697
|
+
status,
|
|
11698
|
+
updateData
|
|
11699
|
+
});
|
|
11687
11700
|
return { success: false, error: error.message };
|
|
11688
11701
|
}
|
|
11689
11702
|
if (options?.feedback && ["passed", "failed", "blocked"].includes(status)) {
|
|
@@ -11745,7 +11758,7 @@ var BugBearClient = class {
|
|
|
11745
11758
|
if (!testerInfo) {
|
|
11746
11759
|
return { success: false, error: "Not authenticated as tester" };
|
|
11747
11760
|
}
|
|
11748
|
-
const { testCaseId, assignmentId, feedback, timeToCompleteSeconds } = options;
|
|
11761
|
+
const { testCaseId, assignmentId, feedback, timeToCompleteSeconds, screenshotUrls } = options;
|
|
11749
11762
|
if (feedback.rating < 1 || feedback.rating > 5) {
|
|
11750
11763
|
return { success: false, error: "Rating must be between 1 and 5" };
|
|
11751
11764
|
}
|
|
@@ -11765,7 +11778,8 @@ var BugBearClient = class {
|
|
|
11765
11778
|
steps_unclear: feedback.stepsUnclear || false,
|
|
11766
11779
|
expected_result_unclear: feedback.expectedResultUnclear || false,
|
|
11767
11780
|
platform: this.getDeviceInfo().platform,
|
|
11768
|
-
time_to_complete_seconds: timeToCompleteSeconds || null
|
|
11781
|
+
time_to_complete_seconds: timeToCompleteSeconds || null,
|
|
11782
|
+
screenshot_urls: screenshotUrls || []
|
|
11769
11783
|
});
|
|
11770
11784
|
if (feedbackError) {
|
|
11771
11785
|
console.error("BugBear: Failed to submit feedback", feedbackError);
|
|
@@ -12080,19 +12094,21 @@ var BugBearClient = class {
|
|
|
12080
12094
|
/**
|
|
12081
12095
|
* Upload a screenshot (web - uses File/Blob)
|
|
12082
12096
|
*/
|
|
12083
|
-
async uploadScreenshot(file, filename) {
|
|
12097
|
+
async uploadScreenshot(file, filename, bucket = "screenshots") {
|
|
12084
12098
|
try {
|
|
12085
|
-
const
|
|
12099
|
+
const contentType = file.type || "image/png";
|
|
12100
|
+
const ext = contentType.includes("png") ? "png" : "jpg";
|
|
12101
|
+
const name = filename || `screenshot-${Date.now()}.${ext}`;
|
|
12086
12102
|
const path = `${this.config.projectId}/${name}`;
|
|
12087
|
-
const { error } = await this.supabase.storage.from(
|
|
12088
|
-
contentType
|
|
12103
|
+
const { error } = await this.supabase.storage.from(bucket).upload(path, file, {
|
|
12104
|
+
contentType,
|
|
12089
12105
|
upsert: false
|
|
12090
12106
|
});
|
|
12091
12107
|
if (error) {
|
|
12092
12108
|
console.error("BugBear: Failed to upload screenshot", error);
|
|
12093
12109
|
return null;
|
|
12094
12110
|
}
|
|
12095
|
-
const { data: { publicUrl } } = this.supabase.storage.from(
|
|
12111
|
+
const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
|
|
12096
12112
|
return publicUrl;
|
|
12097
12113
|
} catch (err) {
|
|
12098
12114
|
console.error("BugBear: Error uploading screenshot", err);
|
|
@@ -13058,7 +13074,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
|
|
|
13058
13074
|
(a) => a.status === "in_progress"
|
|
13059
13075
|
) || assignments.find(
|
|
13060
13076
|
(a) => a.status === "pending"
|
|
13061
|
-
) ||
|
|
13077
|
+
) || null;
|
|
13062
13078
|
const shouldShowWidget = isQAEnabled && isTester;
|
|
13063
13079
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
13064
13080
|
BugBearContext.Provider,
|
|
@@ -13104,6 +13120,9 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
|
|
|
13104
13120
|
var import_react16 = __toESM(require("react"));
|
|
13105
13121
|
var import_react_native15 = require("react-native");
|
|
13106
13122
|
|
|
13123
|
+
// src/widget/logo.ts
|
|
13124
|
+
var BUGBEAR_LOGO_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAJhlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAABIAAAAAQAAAEgAAAABAASQBAACAAAAFAAAAISgAQADAAAAAQABAACgAgAEAAAAAQAAAGCgAwAEAAAAAQAAAGAAAAAAMjAyNjowMToyNCAxNjoyMTozOABbbVCuAAAACXBIWXMAAAsTAAALEwEAmpwYAAACo2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpJcHRjNHhtcEV4dD0iaHR0cDovL2lwdGMub3JnL3N0ZC9JcHRjNHhtcEV4dC8yMDA4LTAyLTI5LyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPElwdGM0eG1wRXh0OkRpZ2l0YWxTb3VyY2VUeXBlPmh0dHA6Ly9jdi5pcHRjLm9yZy9uZXdzY29kZXMvZGlnaXRhbHNvdXJjZXR5cGUvdHJhaW5lZEFsZ29yaXRobWljTWVkaWE8L0lwdGM0eG1wRXh0OkRpZ2l0YWxTb3VyY2VUeXBlPgogICAgICAgICA8SXB0YzR4bXBFeHQ6RGlnSW1hZ2VHVUlEPmZjNzJlN2Q2LTYyYTEtNDE1ZS04MjY5LWM2NjA4MjY0OWRiMDwvSXB0YzR4bXBFeHQ6RGlnSW1hZ2VHVUlEPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyNi0wMS0yNFQxNjoyMTozODwveG1wOkNyZWF0ZURhdGU+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+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";
|
|
13125
|
+
|
|
13107
13126
|
// src/widget/navigation.ts
|
|
13108
13127
|
var import_react2 = require("react");
|
|
13109
13128
|
function navReducer(state, action) {
|
|
@@ -13608,7 +13627,14 @@ function TestDetailScreen({ testId, nav }) {
|
|
|
13608
13627
|
if (!client || !displayedAssignment) return;
|
|
13609
13628
|
await client.failAssignment(displayedAssignment.id);
|
|
13610
13629
|
await refreshAssignments();
|
|
13611
|
-
nav.replace({
|
|
13630
|
+
nav.replace({
|
|
13631
|
+
name: "REPORT",
|
|
13632
|
+
prefill: {
|
|
13633
|
+
type: "test_fail",
|
|
13634
|
+
assignmentId: displayedAssignment.id,
|
|
13635
|
+
testCaseId: displayedAssignment.testCase.id
|
|
13636
|
+
}
|
|
13637
|
+
});
|
|
13612
13638
|
}, [client, displayedAssignment, refreshAssignments, nav]);
|
|
13613
13639
|
const handleSkip = (0, import_react4.useCallback)(async () => {
|
|
13614
13640
|
if (!client || !displayedAssignment || !selectedSkipReason) return;
|
|
@@ -13622,9 +13648,11 @@ function TestDetailScreen({ testId, nav }) {
|
|
|
13622
13648
|
setSelectedSkipReason(null);
|
|
13623
13649
|
setSkipNotes("");
|
|
13624
13650
|
setSkipping(false);
|
|
13625
|
-
const remaining = assignments.filter(
|
|
13626
|
-
|
|
13627
|
-
|
|
13651
|
+
const remaining = assignments.filter(
|
|
13652
|
+
(a) => (a.status === "pending" || a.status === "in_progress") && a.id !== displayedAssignment.id
|
|
13653
|
+
);
|
|
13654
|
+
if (remaining.length > 0) {
|
|
13655
|
+
nav.replace({ name: "TEST_DETAIL", testId: remaining[0].id });
|
|
13628
13656
|
} else {
|
|
13629
13657
|
nav.reset();
|
|
13630
13658
|
}
|
|
@@ -13813,7 +13841,7 @@ var styles2 = import_react_native4.StyleSheet.create({
|
|
|
13813
13841
|
var import_react5 = __toESM(require("react"));
|
|
13814
13842
|
var import_react_native5 = require("react-native");
|
|
13815
13843
|
function TestListScreen({ nav }) {
|
|
13816
|
-
const { assignments, refreshAssignments } = useBugBear();
|
|
13844
|
+
const { assignments, currentAssignment, refreshAssignments } = useBugBear();
|
|
13817
13845
|
const [filter, setFilter] = (0, import_react5.useState)("all");
|
|
13818
13846
|
const [collapsedFolders, setCollapsedFolders] = (0, import_react5.useState)(/* @__PURE__ */ new Set());
|
|
13819
13847
|
const groupedAssignments = (0, import_react5.useMemo)(() => {
|
|
@@ -13868,11 +13896,12 @@ function TestListScreen({ nav }) {
|
|
|
13868
13896
|
if (filtered.length === 0 && filter !== "all") return null;
|
|
13869
13897
|
return /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { key: folderId, style: styles3.folder }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.TouchableOpacity, { style: styles3.folderHeader, onPress: () => toggleFolder(folderId) }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.folderToggle }, isCollapsed ? "\u25B6" : "\u25BC"), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.folderName }, folder.group?.name || "Ungrouped"), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: styles3.folderProgress }, /* @__PURE__ */ import_react5.default.createElement(import_react_native5.View, { style: [styles3.folderProgressFill, { width: `${Math.round((folder.stats.passed + folder.stats.failed) / folder.stats.total * 100)}%` }] })), /* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.folderCount }, folder.stats.passed + folder.stats.failed, "/", folder.stats.total)), !isCollapsed && filtered.map((assignment) => {
|
|
13870
13898
|
const badge = getStatusBadge(assignment.status);
|
|
13899
|
+
const isCurrent = currentAssignment?.id === assignment.id;
|
|
13871
13900
|
return /* @__PURE__ */ import_react5.default.createElement(
|
|
13872
13901
|
import_react_native5.TouchableOpacity,
|
|
13873
13902
|
{
|
|
13874
13903
|
key: assignment.id,
|
|
13875
|
-
style: styles3.testItem,
|
|
13904
|
+
style: [styles3.testItem, isCurrent && styles3.testItemCurrent],
|
|
13876
13905
|
onPress: () => nav.push({ name: "TEST_DETAIL", testId: assignment.id })
|
|
13877
13906
|
},
|
|
13878
13907
|
/* @__PURE__ */ import_react5.default.createElement(import_react_native5.Text, { style: styles3.testBadge }, badge.icon),
|
|
@@ -13895,6 +13924,7 @@ var styles3 = import_react_native5.StyleSheet.create({
|
|
|
13895
13924
|
folderProgressFill: { height: "100%", backgroundColor: colors.green, borderRadius: 2 },
|
|
13896
13925
|
folderCount: { fontSize: 12, color: colors.textMuted, width: 30, textAlign: "right" },
|
|
13897
13926
|
testItem: { flexDirection: "row", alignItems: "center", paddingVertical: 10, paddingHorizontal: 12, borderRadius: 8, marginBottom: 4, backgroundColor: colors.card },
|
|
13927
|
+
testItemCurrent: { backgroundColor: "rgba(59, 130, 246, 0.15)", borderLeftWidth: 3, borderLeftColor: colors.blue },
|
|
13898
13928
|
testBadge: { fontSize: 16, marginRight: 10, width: 20 },
|
|
13899
13929
|
testInfo: { flex: 1 },
|
|
13900
13930
|
testTitle: { fontSize: 14, color: colors.textPrimary, marginBottom: 2 },
|
|
@@ -13904,105 +13934,11 @@ var styles3 = import_react_native5.StyleSheet.create({
|
|
|
13904
13934
|
});
|
|
13905
13935
|
|
|
13906
13936
|
// src/widget/screens/TestFeedbackScreen.tsx
|
|
13907
|
-
var
|
|
13908
|
-
var
|
|
13909
|
-
function TestFeedbackScreen({ status, assignmentId, nav }) {
|
|
13910
|
-
const { client, assignments, refreshAssignments } = useBugBear();
|
|
13911
|
-
const [rating, setRating] = (0, import_react6.useState)(5);
|
|
13912
|
-
const [note, setNote] = (0, import_react6.useState)("");
|
|
13913
|
-
const [flags, setFlags] = (0, import_react6.useState)({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
|
|
13914
|
-
const [submitting, setSubmitting] = (0, import_react6.useState)(false);
|
|
13915
|
-
const assignment = assignments.find((a) => a.id === assignmentId);
|
|
13916
|
-
const showFlags = rating < 4;
|
|
13917
|
-
const handleSubmit = async () => {
|
|
13918
|
-
setSubmitting(true);
|
|
13919
|
-
if (client && assignment) {
|
|
13920
|
-
await client.submitTestFeedback(assignment.testCase.id, {
|
|
13921
|
-
rating,
|
|
13922
|
-
note: note.trim() || void 0,
|
|
13923
|
-
qualityFlags: showFlags ? flags : void 0
|
|
13924
|
-
});
|
|
13925
|
-
}
|
|
13926
|
-
await refreshAssignments();
|
|
13927
|
-
setSubmitting(false);
|
|
13928
|
-
if (status === "failed") {
|
|
13929
|
-
nav.replace({ name: "REPORT", prefill: { type: "test_fail", assignmentId, testCaseId: assignment?.testCase.id } });
|
|
13930
|
-
} else {
|
|
13931
|
-
const remaining = assignments.filter((a) => (a.status === "pending" || a.status === "in_progress") && a.id !== assignmentId);
|
|
13932
|
-
if (remaining.length > 0) {
|
|
13933
|
-
nav.replace({ name: "TEST_DETAIL" });
|
|
13934
|
-
} else {
|
|
13935
|
-
nav.reset();
|
|
13936
|
-
}
|
|
13937
|
-
}
|
|
13938
|
-
};
|
|
13939
|
-
const handleSkip = () => {
|
|
13940
|
-
if (status === "failed") {
|
|
13941
|
-
nav.replace({ name: "REPORT", prefill: { type: "test_fail", assignmentId, testCaseId: assignment?.testCase.id } });
|
|
13942
|
-
} else {
|
|
13943
|
-
const remaining = assignments.filter((a) => (a.status === "pending" || a.status === "in_progress") && a.id !== assignmentId);
|
|
13944
|
-
if (remaining.length > 0) {
|
|
13945
|
-
nav.replace({ name: "TEST_DETAIL" });
|
|
13946
|
-
} else {
|
|
13947
|
-
nav.reset();
|
|
13948
|
-
}
|
|
13949
|
-
}
|
|
13950
|
-
};
|
|
13951
|
-
return /* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: styles4.container }, /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: styles4.header }, status === "passed" ? "\u2705 Test Passed!" : "\u274C Test Failed"), /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: styles4.subheader }, "Rate this test case"), /* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: styles4.starRow }, [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ import_react6.default.createElement(import_react_native6.TouchableOpacity, { key: n, onPress: () => setRating(n), style: styles4.starButton }, /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: [styles4.star, n <= rating && styles4.starActive] }, n <= rating ? "\u2605" : "\u2606")))), showFlags && /* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: styles4.flagsSection }, /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: styles4.flagsLabel }, "What could be improved?"), [
|
|
13952
|
-
{ key: "isOutdated", label: "Test is outdated" },
|
|
13953
|
-
{ key: "needsMoreDetail", label: "Needs more detail" },
|
|
13954
|
-
{ key: "stepsUnclear", label: "Steps are unclear" },
|
|
13955
|
-
{ key: "expectedResultUnclear", label: "Expected result unclear" }
|
|
13956
|
-
].map(({ key, label }) => /* @__PURE__ */ import_react6.default.createElement(
|
|
13957
|
-
import_react_native6.TouchableOpacity,
|
|
13958
|
-
{
|
|
13959
|
-
key,
|
|
13960
|
-
style: [styles4.flagItem, flags[key] && styles4.flagItemActive],
|
|
13961
|
-
onPress: () => setFlags((prev) => ({ ...prev, [key]: !prev[key] }))
|
|
13962
|
-
},
|
|
13963
|
-
/* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: [styles4.flagCheck, flags[key] && styles4.flagCheckActive] }, flags[key] && /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: styles4.flagCheckmark }, "\u2713")),
|
|
13964
|
-
/* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: [styles4.flagText, flags[key] && styles4.flagTextActive] }, label)
|
|
13965
|
-
))), /* @__PURE__ */ import_react6.default.createElement(
|
|
13966
|
-
import_react_native6.TextInput,
|
|
13967
|
-
{
|
|
13968
|
-
style: styles4.noteInput,
|
|
13969
|
-
value: note,
|
|
13970
|
-
onChangeText: setNote,
|
|
13971
|
-
placeholder: "Add a note (optional)",
|
|
13972
|
-
placeholderTextColor: colors.textMuted,
|
|
13973
|
-
multiline: true
|
|
13974
|
-
}
|
|
13975
|
-
), /* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: styles4.actions }, /* @__PURE__ */ import_react6.default.createElement(import_react_native6.TouchableOpacity, { style: styles4.skipButton, onPress: handleSkip }, /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: styles4.skipText }, "Skip")), /* @__PURE__ */ import_react6.default.createElement(import_react_native6.TouchableOpacity, { style: [shared.primaryButton, { flex: 2 }], onPress: handleSubmit, disabled: submitting }, /* @__PURE__ */ import_react6.default.createElement(import_react_native6.Text, { style: shared.primaryButtonText }, submitting ? "Submitting..." : "Submit"))));
|
|
13976
|
-
}
|
|
13977
|
-
var styles4 = import_react_native6.StyleSheet.create({
|
|
13978
|
-
container: { paddingTop: 8 },
|
|
13979
|
-
header: { fontSize: 22, fontWeight: "700", color: colors.textPrimary, textAlign: "center", marginBottom: 4 },
|
|
13980
|
-
subheader: { fontSize: 14, color: colors.textMuted, textAlign: "center", marginBottom: 20 },
|
|
13981
|
-
starRow: { flexDirection: "row", justifyContent: "center", gap: 8, marginBottom: 20 },
|
|
13982
|
-
starButton: { padding: 4 },
|
|
13983
|
-
star: { fontSize: 36, color: colors.textDim },
|
|
13984
|
-
starActive: { color: "#facc15" },
|
|
13985
|
-
flagsSection: { marginBottom: 16 },
|
|
13986
|
-
flagsLabel: { fontSize: 14, fontWeight: "500", color: colors.textSecondary, marginBottom: 10 },
|
|
13987
|
-
flagItem: { flexDirection: "row", alignItems: "center", paddingVertical: 10, paddingHorizontal: 12, borderRadius: 8, marginBottom: 4, backgroundColor: colors.card },
|
|
13988
|
-
flagItemActive: { backgroundColor: colors.yellowDark, borderWidth: 1, borderColor: colors.yellow },
|
|
13989
|
-
flagCheck: { width: 20, height: 20, borderRadius: 4, borderWidth: 2, borderColor: colors.border, marginRight: 10, justifyContent: "center", alignItems: "center" },
|
|
13990
|
-
flagCheckActive: { backgroundColor: colors.yellow, borderColor: colors.yellow },
|
|
13991
|
-
flagCheckmark: { fontSize: 12, fontWeight: "bold", color: "#000" },
|
|
13992
|
-
flagText: { fontSize: 14, color: colors.textSecondary },
|
|
13993
|
-
flagTextActive: { color: colors.yellow },
|
|
13994
|
-
noteInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 10, padding: 12, fontSize: 14, color: colors.textPrimary, minHeight: 60, textAlignVertical: "top", marginBottom: 16 },
|
|
13995
|
-
actions: { flexDirection: "row", gap: 10 },
|
|
13996
|
-
skipButton: { flex: 1, paddingVertical: 14, borderRadius: 12, alignItems: "center", backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border },
|
|
13997
|
-
skipText: { fontSize: 15, color: colors.textSecondary }
|
|
13998
|
-
});
|
|
13999
|
-
|
|
14000
|
-
// src/widget/screens/ReportScreen.tsx
|
|
14001
|
-
var import_react10 = __toESM(require("react"));
|
|
14002
|
-
var import_react_native9 = require("react-native");
|
|
13937
|
+
var import_react9 = __toESM(require("react"));
|
|
13938
|
+
var import_react_native8 = require("react-native");
|
|
14003
13939
|
|
|
14004
13940
|
// src/widget/useImageAttachments.ts
|
|
14005
|
-
var
|
|
13941
|
+
var import_react6 = require("react");
|
|
14006
13942
|
var launchImageLibrary = null;
|
|
14007
13943
|
var launchCamera = null;
|
|
14008
13944
|
try {
|
|
@@ -14013,8 +13949,8 @@ try {
|
|
|
14013
13949
|
}
|
|
14014
13950
|
var IMAGE_PICKER_AVAILABLE = launchImageLibrary !== null;
|
|
14015
13951
|
function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
14016
|
-
const [images, setImages] = (0,
|
|
14017
|
-
const pickFromGallery = (0,
|
|
13952
|
+
const [images, setImages] = (0, import_react6.useState)([]);
|
|
13953
|
+
const pickFromGallery = (0, import_react6.useCallback)(async () => {
|
|
14018
13954
|
if (!launchImageLibrary || images.length >= maxImages) return;
|
|
14019
13955
|
launchImageLibrary(
|
|
14020
13956
|
{ mediaType: "photo", quality: 0.7, maxWidth: 1920, maxHeight: 1920, selectionLimit: maxImages - images.length },
|
|
@@ -14038,7 +13974,7 @@ function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
|
14038
13974
|
}
|
|
14039
13975
|
);
|
|
14040
13976
|
}, [images.length, maxImages, uploadFn, bucket]);
|
|
14041
|
-
const pickFromCamera = (0,
|
|
13977
|
+
const pickFromCamera = (0, import_react6.useCallback)(async () => {
|
|
14042
13978
|
if (!launchCamera || images.length >= maxImages) return;
|
|
14043
13979
|
launchCamera(
|
|
14044
13980
|
{ mediaType: "photo", quality: 0.7, maxWidth: 1920, maxHeight: 1920 },
|
|
@@ -14061,35 +13997,35 @@ function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
|
14061
13997
|
}
|
|
14062
13998
|
);
|
|
14063
13999
|
}, [images.length, maxImages, uploadFn, bucket]);
|
|
14064
|
-
const removeImage = (0,
|
|
14000
|
+
const removeImage = (0, import_react6.useCallback)((id) => {
|
|
14065
14001
|
setImages((prev) => prev.filter((img) => img.id !== id));
|
|
14066
14002
|
}, []);
|
|
14067
|
-
const clear = (0,
|
|
14003
|
+
const clear = (0, import_react6.useCallback)(() => {
|
|
14068
14004
|
setImages([]);
|
|
14069
14005
|
}, []);
|
|
14070
14006
|
const isUploading = images.some((img) => img.status === "uploading");
|
|
14071
14007
|
const hasError = images.some((img) => img.status === "error");
|
|
14072
|
-
const getAttachments = (0,
|
|
14008
|
+
const getAttachments = (0, import_react6.useCallback)(() => {
|
|
14073
14009
|
return images.filter((img) => img.status === "done" && img.remoteUrl).map((img) => ({ type: "image", url: img.remoteUrl, name: img.name }));
|
|
14074
14010
|
}, [images]);
|
|
14075
|
-
const getScreenshotUrls = (0,
|
|
14011
|
+
const getScreenshotUrls = (0, import_react6.useCallback)(() => {
|
|
14076
14012
|
return images.filter((img) => img.status === "done" && img.remoteUrl).map((img) => img.remoteUrl);
|
|
14077
14013
|
}, [images]);
|
|
14078
14014
|
return { images, pickFromGallery, pickFromCamera, removeImage, clear, isUploading, hasError, getAttachments, getScreenshotUrls };
|
|
14079
14015
|
}
|
|
14080
14016
|
|
|
14081
14017
|
// src/widget/ImagePickerButtons.tsx
|
|
14082
|
-
var import_react9 = __toESM(require("react"));
|
|
14083
|
-
var import_react_native8 = require("react-native");
|
|
14084
|
-
|
|
14085
|
-
// src/widget/ImagePreviewStrip.tsx
|
|
14086
14018
|
var import_react8 = __toESM(require("react"));
|
|
14087
14019
|
var import_react_native7 = require("react-native");
|
|
14020
|
+
|
|
14021
|
+
// src/widget/ImagePreviewStrip.tsx
|
|
14022
|
+
var import_react7 = __toESM(require("react"));
|
|
14023
|
+
var import_react_native6 = require("react-native");
|
|
14088
14024
|
function ImagePreviewStrip({ images, onRemove }) {
|
|
14089
14025
|
if (images.length === 0) return null;
|
|
14090
|
-
return /* @__PURE__ */
|
|
14026
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_react_native6.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles4.strip }, images.map((img) => /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { key: img.id, style: styles4.thumbContainer }, /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Image, { source: { uri: img.localUri }, style: styles4.thumb }), img.status === "uploading" && /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: styles4.thumbOverlay }, /* @__PURE__ */ import_react7.default.createElement(import_react_native6.ActivityIndicator, { size: "small", color: "#fff" })), img.status === "error" && /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: [styles4.thumbOverlay, styles4.thumbOverlayError] }, /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Text, { style: styles4.thumbErrorText }, "!")), /* @__PURE__ */ import_react7.default.createElement(import_react_native6.TouchableOpacity, { style: styles4.thumbRemove, onPress: () => onRemove(img.id) }, /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Text, { style: styles4.thumbRemoveText }, "\u2715")))));
|
|
14091
14027
|
}
|
|
14092
|
-
var
|
|
14028
|
+
var styles4 = import_react_native6.StyleSheet.create({
|
|
14093
14029
|
strip: {
|
|
14094
14030
|
flexDirection: "row",
|
|
14095
14031
|
marginTop: 4
|
|
@@ -14108,7 +14044,7 @@ var styles5 = import_react_native7.StyleSheet.create({
|
|
|
14108
14044
|
borderRadius: 8
|
|
14109
14045
|
},
|
|
14110
14046
|
thumbOverlay: {
|
|
14111
|
-
...
|
|
14047
|
+
...import_react_native6.StyleSheet.absoluteFillObject,
|
|
14112
14048
|
backgroundColor: "rgba(0,0,0,0.5)",
|
|
14113
14049
|
justifyContent: "center",
|
|
14114
14050
|
alignItems: "center",
|
|
@@ -14143,25 +14079,25 @@ var styles5 = import_react_native7.StyleSheet.create({
|
|
|
14143
14079
|
// src/widget/ImagePickerButtons.tsx
|
|
14144
14080
|
function ImagePickerButtons({ images, maxImages, onPickGallery, onPickCamera, onRemove, label }) {
|
|
14145
14081
|
if (!IMAGE_PICKER_AVAILABLE) return null;
|
|
14146
|
-
return /* @__PURE__ */
|
|
14147
|
-
|
|
14082
|
+
return /* @__PURE__ */ import_react8.default.createElement(import_react_native7.View, { style: styles5.section }, label && /* @__PURE__ */ import_react8.default.createElement(import_react_native7.Text, { style: styles5.label }, label), /* @__PURE__ */ import_react8.default.createElement(import_react_native7.View, { style: styles5.buttonRow }, /* @__PURE__ */ import_react8.default.createElement(
|
|
14083
|
+
import_react_native7.TouchableOpacity,
|
|
14148
14084
|
{
|
|
14149
|
-
style:
|
|
14085
|
+
style: styles5.pickButton,
|
|
14150
14086
|
onPress: onPickGallery,
|
|
14151
14087
|
disabled: images.length >= maxImages
|
|
14152
14088
|
},
|
|
14153
|
-
/* @__PURE__ */
|
|
14154
|
-
), /* @__PURE__ */
|
|
14155
|
-
|
|
14089
|
+
/* @__PURE__ */ import_react8.default.createElement(import_react_native7.Text, { style: [styles5.pickButtonText, images.length >= maxImages && styles5.pickButtonDisabled] }, "Gallery")
|
|
14090
|
+
), /* @__PURE__ */ import_react8.default.createElement(
|
|
14091
|
+
import_react_native7.TouchableOpacity,
|
|
14156
14092
|
{
|
|
14157
|
-
style:
|
|
14093
|
+
style: styles5.pickButton,
|
|
14158
14094
|
onPress: onPickCamera,
|
|
14159
14095
|
disabled: images.length >= maxImages
|
|
14160
14096
|
},
|
|
14161
|
-
/* @__PURE__ */
|
|
14162
|
-
), /* @__PURE__ */
|
|
14097
|
+
/* @__PURE__ */ import_react8.default.createElement(import_react_native7.Text, { style: [styles5.pickButtonText, images.length >= maxImages && styles5.pickButtonDisabled] }, "Camera")
|
|
14098
|
+
), /* @__PURE__ */ import_react8.default.createElement(import_react_native7.Text, { style: styles5.countText }, images.length, "/", maxImages)), /* @__PURE__ */ import_react8.default.createElement(ImagePreviewStrip, { images, onRemove }));
|
|
14163
14099
|
}
|
|
14164
|
-
var
|
|
14100
|
+
var styles5 = import_react_native7.StyleSheet.create({
|
|
14165
14101
|
section: {
|
|
14166
14102
|
marginTop: 12,
|
|
14167
14103
|
marginBottom: 4
|
|
@@ -14200,7 +14136,123 @@ var styles6 = import_react_native8.StyleSheet.create({
|
|
|
14200
14136
|
}
|
|
14201
14137
|
});
|
|
14202
14138
|
|
|
14139
|
+
// src/widget/screens/TestFeedbackScreen.tsx
|
|
14140
|
+
function TestFeedbackScreen({ status, assignmentId, nav }) {
|
|
14141
|
+
const { client, assignments, refreshAssignments, uploadImage } = useBugBear();
|
|
14142
|
+
const images = useImageAttachments(uploadImage, 3, "screenshots");
|
|
14143
|
+
const [rating, setRating] = (0, import_react9.useState)(5);
|
|
14144
|
+
const [note, setNote] = (0, import_react9.useState)("");
|
|
14145
|
+
const [flags, setFlags] = (0, import_react9.useState)({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
|
|
14146
|
+
const [submitting, setSubmitting] = (0, import_react9.useState)(false);
|
|
14147
|
+
const assignment = assignments.find((a) => a.id === assignmentId);
|
|
14148
|
+
const showFlags = rating < 4;
|
|
14149
|
+
const handleSubmit = async () => {
|
|
14150
|
+
setSubmitting(true);
|
|
14151
|
+
if (client && assignment) {
|
|
14152
|
+
const screenshotUrls = images.getScreenshotUrls();
|
|
14153
|
+
await client.submitTestFeedback({
|
|
14154
|
+
testCaseId: assignment.testCase.id,
|
|
14155
|
+
assignmentId,
|
|
14156
|
+
feedback: {
|
|
14157
|
+
rating,
|
|
14158
|
+
feedbackNote: note.trim() || void 0,
|
|
14159
|
+
...showFlags ? {
|
|
14160
|
+
isOutdated: flags.isOutdated,
|
|
14161
|
+
needsMoreDetail: flags.needsMoreDetail,
|
|
14162
|
+
stepsUnclear: flags.stepsUnclear,
|
|
14163
|
+
expectedResultUnclear: flags.expectedResultUnclear
|
|
14164
|
+
} : {}
|
|
14165
|
+
},
|
|
14166
|
+
screenshotUrls: screenshotUrls.length > 0 ? screenshotUrls : void 0
|
|
14167
|
+
});
|
|
14168
|
+
}
|
|
14169
|
+
await refreshAssignments();
|
|
14170
|
+
setSubmitting(false);
|
|
14171
|
+
if (status === "failed") {
|
|
14172
|
+
nav.replace({ name: "REPORT", prefill: { type: "test_fail", assignmentId, testCaseId: assignment?.testCase.id } });
|
|
14173
|
+
} else {
|
|
14174
|
+
const remaining = assignments.filter((a) => (a.status === "pending" || a.status === "in_progress") && a.id !== assignmentId);
|
|
14175
|
+
if (remaining.length > 0) {
|
|
14176
|
+
nav.replace({ name: "TEST_DETAIL", testId: remaining[0].id });
|
|
14177
|
+
} else {
|
|
14178
|
+
nav.reset();
|
|
14179
|
+
}
|
|
14180
|
+
}
|
|
14181
|
+
};
|
|
14182
|
+
const handleSkip = () => {
|
|
14183
|
+
if (status === "failed") {
|
|
14184
|
+
nav.replace({ name: "REPORT", prefill: { type: "test_fail", assignmentId, testCaseId: assignment?.testCase.id } });
|
|
14185
|
+
} else {
|
|
14186
|
+
const remaining = assignments.filter((a) => (a.status === "pending" || a.status === "in_progress") && a.id !== assignmentId);
|
|
14187
|
+
if (remaining.length > 0) {
|
|
14188
|
+
nav.replace({ name: "TEST_DETAIL", testId: remaining[0].id });
|
|
14189
|
+
} else {
|
|
14190
|
+
nav.reset();
|
|
14191
|
+
}
|
|
14192
|
+
}
|
|
14193
|
+
};
|
|
14194
|
+
return /* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: styles6.container }, /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: styles6.header }, status === "passed" ? "\u2705 Test Passed!" : "\u274C Test Failed"), /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: styles6.subheader }, "Rate this test case"), /* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: styles6.starRow }, [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ import_react9.default.createElement(import_react_native8.TouchableOpacity, { key: n, onPress: () => setRating(n), style: styles6.starButton }, /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: [styles6.star, n <= rating && styles6.starActive] }, n <= rating ? "\u2605" : "\u2606")))), showFlags && /* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: styles6.flagsSection }, /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: styles6.flagsLabel }, "What could be improved?"), [
|
|
14195
|
+
{ key: "isOutdated", label: "Test is outdated" },
|
|
14196
|
+
{ key: "needsMoreDetail", label: "Needs more detail" },
|
|
14197
|
+
{ key: "stepsUnclear", label: "Steps are unclear" },
|
|
14198
|
+
{ key: "expectedResultUnclear", label: "Expected result unclear" }
|
|
14199
|
+
].map(({ key, label }) => /* @__PURE__ */ import_react9.default.createElement(
|
|
14200
|
+
import_react_native8.TouchableOpacity,
|
|
14201
|
+
{
|
|
14202
|
+
key,
|
|
14203
|
+
style: [styles6.flagItem, flags[key] && styles6.flagItemActive],
|
|
14204
|
+
onPress: () => setFlags((prev) => ({ ...prev, [key]: !prev[key] }))
|
|
14205
|
+
},
|
|
14206
|
+
/* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: [styles6.flagCheck, flags[key] && styles6.flagCheckActive] }, flags[key] && /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: styles6.flagCheckmark }, "\u2713")),
|
|
14207
|
+
/* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: [styles6.flagText, flags[key] && styles6.flagTextActive] }, label)
|
|
14208
|
+
))), /* @__PURE__ */ import_react9.default.createElement(
|
|
14209
|
+
import_react_native8.TextInput,
|
|
14210
|
+
{
|
|
14211
|
+
style: styles6.noteInput,
|
|
14212
|
+
value: note,
|
|
14213
|
+
onChangeText: setNote,
|
|
14214
|
+
placeholder: "Add a note (optional)",
|
|
14215
|
+
placeholderTextColor: colors.textMuted,
|
|
14216
|
+
multiline: true
|
|
14217
|
+
}
|
|
14218
|
+
), /* @__PURE__ */ import_react9.default.createElement(
|
|
14219
|
+
ImagePickerButtons,
|
|
14220
|
+
{
|
|
14221
|
+
images: images.images,
|
|
14222
|
+
maxImages: 3,
|
|
14223
|
+
onPickGallery: images.pickFromGallery,
|
|
14224
|
+
onPickCamera: images.pickFromCamera,
|
|
14225
|
+
onRemove: images.removeImage,
|
|
14226
|
+
label: "Screenshots (optional)"
|
|
14227
|
+
}
|
|
14228
|
+
), /* @__PURE__ */ import_react9.default.createElement(import_react_native8.View, { style: styles6.actions }, /* @__PURE__ */ import_react9.default.createElement(import_react_native8.TouchableOpacity, { style: styles6.skipButton, onPress: handleSkip }, /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: styles6.skipText }, "Skip")), /* @__PURE__ */ import_react9.default.createElement(import_react_native8.TouchableOpacity, { style: [shared.primaryButton, { flex: 2, opacity: submitting || images.isUploading ? 0.5 : 1 }], onPress: handleSubmit, disabled: submitting || images.isUploading }, /* @__PURE__ */ import_react9.default.createElement(import_react_native8.Text, { style: shared.primaryButtonText }, images.isUploading ? "Uploading..." : submitting ? "Submitting..." : "Submit"))));
|
|
14229
|
+
}
|
|
14230
|
+
var styles6 = import_react_native8.StyleSheet.create({
|
|
14231
|
+
container: { paddingTop: 8 },
|
|
14232
|
+
header: { fontSize: 22, fontWeight: "700", color: colors.textPrimary, textAlign: "center", marginBottom: 4 },
|
|
14233
|
+
subheader: { fontSize: 14, color: colors.textMuted, textAlign: "center", marginBottom: 20 },
|
|
14234
|
+
starRow: { flexDirection: "row", justifyContent: "center", gap: 8, marginBottom: 20 },
|
|
14235
|
+
starButton: { padding: 4 },
|
|
14236
|
+
star: { fontSize: 36, color: colors.textDim },
|
|
14237
|
+
starActive: { color: "#facc15" },
|
|
14238
|
+
flagsSection: { marginBottom: 16 },
|
|
14239
|
+
flagsLabel: { fontSize: 14, fontWeight: "500", color: colors.textSecondary, marginBottom: 10 },
|
|
14240
|
+
flagItem: { flexDirection: "row", alignItems: "center", paddingVertical: 10, paddingHorizontal: 12, borderRadius: 8, marginBottom: 4, backgroundColor: colors.card },
|
|
14241
|
+
flagItemActive: { backgroundColor: colors.yellowDark, borderWidth: 1, borderColor: colors.yellow },
|
|
14242
|
+
flagCheck: { width: 20, height: 20, borderRadius: 4, borderWidth: 2, borderColor: colors.border, marginRight: 10, justifyContent: "center", alignItems: "center" },
|
|
14243
|
+
flagCheckActive: { backgroundColor: colors.yellow, borderColor: colors.yellow },
|
|
14244
|
+
flagCheckmark: { fontSize: 12, fontWeight: "bold", color: "#000" },
|
|
14245
|
+
flagText: { fontSize: 14, color: colors.textSecondary },
|
|
14246
|
+
flagTextActive: { color: colors.yellow },
|
|
14247
|
+
noteInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 10, padding: 12, fontSize: 14, color: colors.textPrimary, minHeight: 60, textAlignVertical: "top", marginBottom: 16 },
|
|
14248
|
+
actions: { flexDirection: "row", gap: 10 },
|
|
14249
|
+
skipButton: { flex: 1, paddingVertical: 14, borderRadius: 12, alignItems: "center", backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border },
|
|
14250
|
+
skipText: { fontSize: 15, color: colors.textSecondary }
|
|
14251
|
+
});
|
|
14252
|
+
|
|
14203
14253
|
// src/widget/screens/ReportScreen.tsx
|
|
14254
|
+
var import_react10 = __toESM(require("react"));
|
|
14255
|
+
var import_react_native9 = require("react-native");
|
|
14204
14256
|
function ReportScreen({ nav, prefill }) {
|
|
14205
14257
|
const { client, getDeviceInfo, uploadImage, refreshAssignments } = useBugBear();
|
|
14206
14258
|
const [reportType, setReportType] = (0, import_react10.useState)(prefill?.type || "bug");
|
|
@@ -14812,7 +14864,7 @@ function BugBearButton({
|
|
|
14812
14864
|
onPress: () => setModalVisible(true),
|
|
14813
14865
|
activeOpacity: draggable ? 1 : 0.7
|
|
14814
14866
|
},
|
|
14815
|
-
/* @__PURE__ */ import_react16.default.createElement(import_react_native15.
|
|
14867
|
+
/* @__PURE__ */ import_react16.default.createElement(import_react_native15.Image, { source: { uri: BUGBEAR_LOGO_BASE64 }, style: styles13.fabIcon }),
|
|
14816
14868
|
badgeCount > 0 && /* @__PURE__ */ import_react16.default.createElement(import_react_native15.View, { style: styles13.badge }, /* @__PURE__ */ import_react16.default.createElement(import_react_native15.Text, { style: styles13.badgeText }, badgeCount > 9 ? "9+" : badgeCount))
|
|
14817
14869
|
)
|
|
14818
14870
|
), /* @__PURE__ */ import_react16.default.createElement(
|
|
@@ -14862,7 +14914,9 @@ var styles13 = import_react_native15.StyleSheet.create({
|
|
|
14862
14914
|
elevation: 8
|
|
14863
14915
|
},
|
|
14864
14916
|
fabIcon: {
|
|
14865
|
-
|
|
14917
|
+
width: 32,
|
|
14918
|
+
height: 32,
|
|
14919
|
+
borderRadius: 16
|
|
14866
14920
|
},
|
|
14867
14921
|
badge: {
|
|
14868
14922
|
position: "absolute",
|
package/dist/index.mjs
CHANGED
|
@@ -11628,6 +11628,11 @@ var BugBearClient = class {
|
|
|
11628
11628
|
try {
|
|
11629
11629
|
const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at").eq("id", assignmentId).single();
|
|
11630
11630
|
if (fetchError || !currentAssignment) {
|
|
11631
|
+
console.error("BugBear: Assignment not found", {
|
|
11632
|
+
message: fetchError?.message,
|
|
11633
|
+
code: fetchError?.code,
|
|
11634
|
+
assignmentId
|
|
11635
|
+
});
|
|
11631
11636
|
return { success: false, error: "Assignment not found" };
|
|
11632
11637
|
}
|
|
11633
11638
|
const updateData = { status };
|
|
@@ -11652,7 +11657,15 @@ var BugBearClient = class {
|
|
|
11652
11657
|
}
|
|
11653
11658
|
const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
|
|
11654
11659
|
if (error) {
|
|
11655
|
-
console.error("BugBear: Failed to update assignment status",
|
|
11660
|
+
console.error("BugBear: Failed to update assignment status", {
|
|
11661
|
+
message: error.message,
|
|
11662
|
+
details: error.details,
|
|
11663
|
+
hint: error.hint,
|
|
11664
|
+
code: error.code,
|
|
11665
|
+
assignmentId,
|
|
11666
|
+
status,
|
|
11667
|
+
updateData
|
|
11668
|
+
});
|
|
11656
11669
|
return { success: false, error: error.message };
|
|
11657
11670
|
}
|
|
11658
11671
|
if (options?.feedback && ["passed", "failed", "blocked"].includes(status)) {
|
|
@@ -11714,7 +11727,7 @@ var BugBearClient = class {
|
|
|
11714
11727
|
if (!testerInfo) {
|
|
11715
11728
|
return { success: false, error: "Not authenticated as tester" };
|
|
11716
11729
|
}
|
|
11717
|
-
const { testCaseId, assignmentId, feedback, timeToCompleteSeconds } = options;
|
|
11730
|
+
const { testCaseId, assignmentId, feedback, timeToCompleteSeconds, screenshotUrls } = options;
|
|
11718
11731
|
if (feedback.rating < 1 || feedback.rating > 5) {
|
|
11719
11732
|
return { success: false, error: "Rating must be between 1 and 5" };
|
|
11720
11733
|
}
|
|
@@ -11734,7 +11747,8 @@ var BugBearClient = class {
|
|
|
11734
11747
|
steps_unclear: feedback.stepsUnclear || false,
|
|
11735
11748
|
expected_result_unclear: feedback.expectedResultUnclear || false,
|
|
11736
11749
|
platform: this.getDeviceInfo().platform,
|
|
11737
|
-
time_to_complete_seconds: timeToCompleteSeconds || null
|
|
11750
|
+
time_to_complete_seconds: timeToCompleteSeconds || null,
|
|
11751
|
+
screenshot_urls: screenshotUrls || []
|
|
11738
11752
|
});
|
|
11739
11753
|
if (feedbackError) {
|
|
11740
11754
|
console.error("BugBear: Failed to submit feedback", feedbackError);
|
|
@@ -12049,19 +12063,21 @@ var BugBearClient = class {
|
|
|
12049
12063
|
/**
|
|
12050
12064
|
* Upload a screenshot (web - uses File/Blob)
|
|
12051
12065
|
*/
|
|
12052
|
-
async uploadScreenshot(file, filename) {
|
|
12066
|
+
async uploadScreenshot(file, filename, bucket = "screenshots") {
|
|
12053
12067
|
try {
|
|
12054
|
-
const
|
|
12068
|
+
const contentType = file.type || "image/png";
|
|
12069
|
+
const ext = contentType.includes("png") ? "png" : "jpg";
|
|
12070
|
+
const name = filename || `screenshot-${Date.now()}.${ext}`;
|
|
12055
12071
|
const path = `${this.config.projectId}/${name}`;
|
|
12056
|
-
const { error } = await this.supabase.storage.from(
|
|
12057
|
-
contentType
|
|
12072
|
+
const { error } = await this.supabase.storage.from(bucket).upload(path, file, {
|
|
12073
|
+
contentType,
|
|
12058
12074
|
upsert: false
|
|
12059
12075
|
});
|
|
12060
12076
|
if (error) {
|
|
12061
12077
|
console.error("BugBear: Failed to upload screenshot", error);
|
|
12062
12078
|
return null;
|
|
12063
12079
|
}
|
|
12064
|
-
const { data: { publicUrl } } = this.supabase.storage.from(
|
|
12080
|
+
const { data: { publicUrl } } = this.supabase.storage.from(bucket).getPublicUrl(path);
|
|
12065
12081
|
return publicUrl;
|
|
12066
12082
|
} catch (err) {
|
|
12067
12083
|
console.error("BugBear: Error uploading screenshot", err);
|
|
@@ -13027,7 +13043,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
|
|
|
13027
13043
|
(a) => a.status === "in_progress"
|
|
13028
13044
|
) || assignments.find(
|
|
13029
13045
|
(a) => a.status === "pending"
|
|
13030
|
-
) ||
|
|
13046
|
+
) || null;
|
|
13031
13047
|
const shouldShowWidget = isQAEnabled && isTester;
|
|
13032
13048
|
return /* @__PURE__ */ React.createElement(
|
|
13033
13049
|
BugBearContext.Provider,
|
|
@@ -13074,6 +13090,7 @@ import React14, { useState as useState10, useRef as useRef2 } from "react";
|
|
|
13074
13090
|
import {
|
|
13075
13091
|
View as View13,
|
|
13076
13092
|
Text as Text13,
|
|
13093
|
+
Image as Image3,
|
|
13077
13094
|
TouchableOpacity as TouchableOpacity12,
|
|
13078
13095
|
Modal as Modal2,
|
|
13079
13096
|
ScrollView as ScrollView2,
|
|
@@ -13086,6 +13103,9 @@ import {
|
|
|
13086
13103
|
ActivityIndicator as ActivityIndicator2
|
|
13087
13104
|
} from "react-native";
|
|
13088
13105
|
|
|
13106
|
+
// src/widget/logo.ts
|
|
13107
|
+
var BUGBEAR_LOGO_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAJhlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAABIAAAAAQAAAEgAAAABAASQBAACAAAAFAAAAISgAQADAAAAAQABAACgAgAEAAAAAQAAAGCgAwAEAAAAAQAAAGAAAAAAMjAyNjowMToyNCAxNjoyMTozOABbbVCuAAAACXBIWXMAAAsTAAALEwEAmpwYAAACo2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpJcHRjNHhtcEV4dD0iaHR0cDovL2lwdGMub3JnL3N0ZC9JcHRjNHhtcEV4dC8yMDA4LTAyLTI5LyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPElwdGM0eG1wRXh0OkRpZ2l0YWxTb3VyY2VUeXBlPmh0dHA6Ly9jdi5pcHRjLm9yZy9uZXdzY29kZXMvZGlnaXRhbHNvdXJjZXR5cGUvdHJhaW5lZEFsZ29yaXRobWljTWVkaWE8L0lwdGM0eG1wRXh0OkRpZ2l0YWxTb3VyY2VUeXBlPgogICAgICAgICA8SXB0YzR4bXBFeHQ6RGlnSW1hZ2VHVUlEPmZjNzJlN2Q2LTYyYTEtNDE1ZS04MjY5LWM2NjA4MjY0OWRiMDwvSXB0YzR4bXBFeHQ6RGlnSW1hZ2VHVUlEPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyNi0wMS0yNFQxNjoyMTozODwveG1wOkNyZWF0ZURhdGU+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+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";
|
|
13108
|
+
|
|
13089
13109
|
// src/widget/navigation.ts
|
|
13090
13110
|
import { useReducer } from "react";
|
|
13091
13111
|
function navReducer(state, action) {
|
|
@@ -13590,7 +13610,14 @@ function TestDetailScreen({ testId, nav }) {
|
|
|
13590
13610
|
if (!client || !displayedAssignment) return;
|
|
13591
13611
|
await client.failAssignment(displayedAssignment.id);
|
|
13592
13612
|
await refreshAssignments();
|
|
13593
|
-
nav.replace({
|
|
13613
|
+
nav.replace({
|
|
13614
|
+
name: "REPORT",
|
|
13615
|
+
prefill: {
|
|
13616
|
+
type: "test_fail",
|
|
13617
|
+
assignmentId: displayedAssignment.id,
|
|
13618
|
+
testCaseId: displayedAssignment.testCase.id
|
|
13619
|
+
}
|
|
13620
|
+
});
|
|
13594
13621
|
}, [client, displayedAssignment, refreshAssignments, nav]);
|
|
13595
13622
|
const handleSkip = useCallback2(async () => {
|
|
13596
13623
|
if (!client || !displayedAssignment || !selectedSkipReason) return;
|
|
@@ -13604,9 +13631,11 @@ function TestDetailScreen({ testId, nav }) {
|
|
|
13604
13631
|
setSelectedSkipReason(null);
|
|
13605
13632
|
setSkipNotes("");
|
|
13606
13633
|
setSkipping(false);
|
|
13607
|
-
const remaining = assignments.filter(
|
|
13608
|
-
|
|
13609
|
-
|
|
13634
|
+
const remaining = assignments.filter(
|
|
13635
|
+
(a) => (a.status === "pending" || a.status === "in_progress") && a.id !== displayedAssignment.id
|
|
13636
|
+
);
|
|
13637
|
+
if (remaining.length > 0) {
|
|
13638
|
+
nav.replace({ name: "TEST_DETAIL", testId: remaining[0].id });
|
|
13610
13639
|
} else {
|
|
13611
13640
|
nav.reset();
|
|
13612
13641
|
}
|
|
@@ -13795,7 +13824,7 @@ var styles2 = StyleSheet3.create({
|
|
|
13795
13824
|
import React4, { useState as useState3, useMemo as useMemo2, useCallback as useCallback3 } from "react";
|
|
13796
13825
|
import { View as View3, Text as Text3, TouchableOpacity as TouchableOpacity3, StyleSheet as StyleSheet4 } from "react-native";
|
|
13797
13826
|
function TestListScreen({ nav }) {
|
|
13798
|
-
const { assignments, refreshAssignments } = useBugBear();
|
|
13827
|
+
const { assignments, currentAssignment, refreshAssignments } = useBugBear();
|
|
13799
13828
|
const [filter, setFilter] = useState3("all");
|
|
13800
13829
|
const [collapsedFolders, setCollapsedFolders] = useState3(/* @__PURE__ */ new Set());
|
|
13801
13830
|
const groupedAssignments = useMemo2(() => {
|
|
@@ -13850,11 +13879,12 @@ function TestListScreen({ nav }) {
|
|
|
13850
13879
|
if (filtered.length === 0 && filter !== "all") return null;
|
|
13851
13880
|
return /* @__PURE__ */ React4.createElement(View3, { key: folderId, style: styles3.folder }, /* @__PURE__ */ React4.createElement(TouchableOpacity3, { style: styles3.folderHeader, onPress: () => toggleFolder(folderId) }, /* @__PURE__ */ React4.createElement(Text3, { style: styles3.folderToggle }, isCollapsed ? "\u25B6" : "\u25BC"), /* @__PURE__ */ React4.createElement(Text3, { style: styles3.folderName }, folder.group?.name || "Ungrouped"), /* @__PURE__ */ React4.createElement(View3, { style: styles3.folderProgress }, /* @__PURE__ */ React4.createElement(View3, { style: [styles3.folderProgressFill, { width: `${Math.round((folder.stats.passed + folder.stats.failed) / folder.stats.total * 100)}%` }] })), /* @__PURE__ */ React4.createElement(Text3, { style: styles3.folderCount }, folder.stats.passed + folder.stats.failed, "/", folder.stats.total)), !isCollapsed && filtered.map((assignment) => {
|
|
13852
13881
|
const badge = getStatusBadge(assignment.status);
|
|
13882
|
+
const isCurrent = currentAssignment?.id === assignment.id;
|
|
13853
13883
|
return /* @__PURE__ */ React4.createElement(
|
|
13854
13884
|
TouchableOpacity3,
|
|
13855
13885
|
{
|
|
13856
13886
|
key: assignment.id,
|
|
13857
|
-
style: styles3.testItem,
|
|
13887
|
+
style: [styles3.testItem, isCurrent && styles3.testItemCurrent],
|
|
13858
13888
|
onPress: () => nav.push({ name: "TEST_DETAIL", testId: assignment.id })
|
|
13859
13889
|
},
|
|
13860
13890
|
/* @__PURE__ */ React4.createElement(Text3, { style: styles3.testBadge }, badge.icon),
|
|
@@ -13877,6 +13907,7 @@ var styles3 = StyleSheet4.create({
|
|
|
13877
13907
|
folderProgressFill: { height: "100%", backgroundColor: colors.green, borderRadius: 2 },
|
|
13878
13908
|
folderCount: { fontSize: 12, color: colors.textMuted, width: 30, textAlign: "right" },
|
|
13879
13909
|
testItem: { flexDirection: "row", alignItems: "center", paddingVertical: 10, paddingHorizontal: 12, borderRadius: 8, marginBottom: 4, backgroundColor: colors.card },
|
|
13910
|
+
testItemCurrent: { backgroundColor: "rgba(59, 130, 246, 0.15)", borderLeftWidth: 3, borderLeftColor: colors.blue },
|
|
13880
13911
|
testBadge: { fontSize: 16, marginRight: 10, width: 20 },
|
|
13881
13912
|
testInfo: { flex: 1 },
|
|
13882
13913
|
testTitle: { fontSize: 14, color: colors.textPrimary, marginBottom: 2 },
|
|
@@ -13886,105 +13917,11 @@ var styles3 = StyleSheet4.create({
|
|
|
13886
13917
|
});
|
|
13887
13918
|
|
|
13888
13919
|
// src/widget/screens/TestFeedbackScreen.tsx
|
|
13889
|
-
import
|
|
13890
|
-
import { View as
|
|
13891
|
-
function TestFeedbackScreen({ status, assignmentId, nav }) {
|
|
13892
|
-
const { client, assignments, refreshAssignments } = useBugBear();
|
|
13893
|
-
const [rating, setRating] = useState4(5);
|
|
13894
|
-
const [note, setNote] = useState4("");
|
|
13895
|
-
const [flags, setFlags] = useState4({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
|
|
13896
|
-
const [submitting, setSubmitting] = useState4(false);
|
|
13897
|
-
const assignment = assignments.find((a) => a.id === assignmentId);
|
|
13898
|
-
const showFlags = rating < 4;
|
|
13899
|
-
const handleSubmit = async () => {
|
|
13900
|
-
setSubmitting(true);
|
|
13901
|
-
if (client && assignment) {
|
|
13902
|
-
await client.submitTestFeedback(assignment.testCase.id, {
|
|
13903
|
-
rating,
|
|
13904
|
-
note: note.trim() || void 0,
|
|
13905
|
-
qualityFlags: showFlags ? flags : void 0
|
|
13906
|
-
});
|
|
13907
|
-
}
|
|
13908
|
-
await refreshAssignments();
|
|
13909
|
-
setSubmitting(false);
|
|
13910
|
-
if (status === "failed") {
|
|
13911
|
-
nav.replace({ name: "REPORT", prefill: { type: "test_fail", assignmentId, testCaseId: assignment?.testCase.id } });
|
|
13912
|
-
} else {
|
|
13913
|
-
const remaining = assignments.filter((a) => (a.status === "pending" || a.status === "in_progress") && a.id !== assignmentId);
|
|
13914
|
-
if (remaining.length > 0) {
|
|
13915
|
-
nav.replace({ name: "TEST_DETAIL" });
|
|
13916
|
-
} else {
|
|
13917
|
-
nav.reset();
|
|
13918
|
-
}
|
|
13919
|
-
}
|
|
13920
|
-
};
|
|
13921
|
-
const handleSkip = () => {
|
|
13922
|
-
if (status === "failed") {
|
|
13923
|
-
nav.replace({ name: "REPORT", prefill: { type: "test_fail", assignmentId, testCaseId: assignment?.testCase.id } });
|
|
13924
|
-
} else {
|
|
13925
|
-
const remaining = assignments.filter((a) => (a.status === "pending" || a.status === "in_progress") && a.id !== assignmentId);
|
|
13926
|
-
if (remaining.length > 0) {
|
|
13927
|
-
nav.replace({ name: "TEST_DETAIL" });
|
|
13928
|
-
} else {
|
|
13929
|
-
nav.reset();
|
|
13930
|
-
}
|
|
13931
|
-
}
|
|
13932
|
-
};
|
|
13933
|
-
return /* @__PURE__ */ React5.createElement(View4, { style: styles4.container }, /* @__PURE__ */ React5.createElement(Text4, { style: styles4.header }, status === "passed" ? "\u2705 Test Passed!" : "\u274C Test Failed"), /* @__PURE__ */ React5.createElement(Text4, { style: styles4.subheader }, "Rate this test case"), /* @__PURE__ */ React5.createElement(View4, { style: styles4.starRow }, [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ React5.createElement(TouchableOpacity4, { key: n, onPress: () => setRating(n), style: styles4.starButton }, /* @__PURE__ */ React5.createElement(Text4, { style: [styles4.star, n <= rating && styles4.starActive] }, n <= rating ? "\u2605" : "\u2606")))), showFlags && /* @__PURE__ */ React5.createElement(View4, { style: styles4.flagsSection }, /* @__PURE__ */ React5.createElement(Text4, { style: styles4.flagsLabel }, "What could be improved?"), [
|
|
13934
|
-
{ key: "isOutdated", label: "Test is outdated" },
|
|
13935
|
-
{ key: "needsMoreDetail", label: "Needs more detail" },
|
|
13936
|
-
{ key: "stepsUnclear", label: "Steps are unclear" },
|
|
13937
|
-
{ key: "expectedResultUnclear", label: "Expected result unclear" }
|
|
13938
|
-
].map(({ key, label }) => /* @__PURE__ */ React5.createElement(
|
|
13939
|
-
TouchableOpacity4,
|
|
13940
|
-
{
|
|
13941
|
-
key,
|
|
13942
|
-
style: [styles4.flagItem, flags[key] && styles4.flagItemActive],
|
|
13943
|
-
onPress: () => setFlags((prev) => ({ ...prev, [key]: !prev[key] }))
|
|
13944
|
-
},
|
|
13945
|
-
/* @__PURE__ */ React5.createElement(View4, { style: [styles4.flagCheck, flags[key] && styles4.flagCheckActive] }, flags[key] && /* @__PURE__ */ React5.createElement(Text4, { style: styles4.flagCheckmark }, "\u2713")),
|
|
13946
|
-
/* @__PURE__ */ React5.createElement(Text4, { style: [styles4.flagText, flags[key] && styles4.flagTextActive] }, label)
|
|
13947
|
-
))), /* @__PURE__ */ React5.createElement(
|
|
13948
|
-
TextInput2,
|
|
13949
|
-
{
|
|
13950
|
-
style: styles4.noteInput,
|
|
13951
|
-
value: note,
|
|
13952
|
-
onChangeText: setNote,
|
|
13953
|
-
placeholder: "Add a note (optional)",
|
|
13954
|
-
placeholderTextColor: colors.textMuted,
|
|
13955
|
-
multiline: true
|
|
13956
|
-
}
|
|
13957
|
-
), /* @__PURE__ */ React5.createElement(View4, { style: styles4.actions }, /* @__PURE__ */ React5.createElement(TouchableOpacity4, { style: styles4.skipButton, onPress: handleSkip }, /* @__PURE__ */ React5.createElement(Text4, { style: styles4.skipText }, "Skip")), /* @__PURE__ */ React5.createElement(TouchableOpacity4, { style: [shared.primaryButton, { flex: 2 }], onPress: handleSubmit, disabled: submitting }, /* @__PURE__ */ React5.createElement(Text4, { style: shared.primaryButtonText }, submitting ? "Submitting..." : "Submit"))));
|
|
13958
|
-
}
|
|
13959
|
-
var styles4 = StyleSheet5.create({
|
|
13960
|
-
container: { paddingTop: 8 },
|
|
13961
|
-
header: { fontSize: 22, fontWeight: "700", color: colors.textPrimary, textAlign: "center", marginBottom: 4 },
|
|
13962
|
-
subheader: { fontSize: 14, color: colors.textMuted, textAlign: "center", marginBottom: 20 },
|
|
13963
|
-
starRow: { flexDirection: "row", justifyContent: "center", gap: 8, marginBottom: 20 },
|
|
13964
|
-
starButton: { padding: 4 },
|
|
13965
|
-
star: { fontSize: 36, color: colors.textDim },
|
|
13966
|
-
starActive: { color: "#facc15" },
|
|
13967
|
-
flagsSection: { marginBottom: 16 },
|
|
13968
|
-
flagsLabel: { fontSize: 14, fontWeight: "500", color: colors.textSecondary, marginBottom: 10 },
|
|
13969
|
-
flagItem: { flexDirection: "row", alignItems: "center", paddingVertical: 10, paddingHorizontal: 12, borderRadius: 8, marginBottom: 4, backgroundColor: colors.card },
|
|
13970
|
-
flagItemActive: { backgroundColor: colors.yellowDark, borderWidth: 1, borderColor: colors.yellow },
|
|
13971
|
-
flagCheck: { width: 20, height: 20, borderRadius: 4, borderWidth: 2, borderColor: colors.border, marginRight: 10, justifyContent: "center", alignItems: "center" },
|
|
13972
|
-
flagCheckActive: { backgroundColor: colors.yellow, borderColor: colors.yellow },
|
|
13973
|
-
flagCheckmark: { fontSize: 12, fontWeight: "bold", color: "#000" },
|
|
13974
|
-
flagText: { fontSize: 14, color: colors.textSecondary },
|
|
13975
|
-
flagTextActive: { color: colors.yellow },
|
|
13976
|
-
noteInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 10, padding: 12, fontSize: 14, color: colors.textPrimary, minHeight: 60, textAlignVertical: "top", marginBottom: 16 },
|
|
13977
|
-
actions: { flexDirection: "row", gap: 10 },
|
|
13978
|
-
skipButton: { flex: 1, paddingVertical: 14, borderRadius: 12, alignItems: "center", backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border },
|
|
13979
|
-
skipText: { fontSize: 15, color: colors.textSecondary }
|
|
13980
|
-
});
|
|
13981
|
-
|
|
13982
|
-
// src/widget/screens/ReportScreen.tsx
|
|
13983
|
-
import React8, { useState as useState6 } from "react";
|
|
13984
|
-
import { View as View7, Text as Text7, TouchableOpacity as TouchableOpacity7, TextInput as TextInput3, StyleSheet as StyleSheet8 } from "react-native";
|
|
13920
|
+
import React7, { useState as useState5 } from "react";
|
|
13921
|
+
import { View as View6, Text as Text6, TouchableOpacity as TouchableOpacity6, TextInput as TextInput2, StyleSheet as StyleSheet7 } from "react-native";
|
|
13985
13922
|
|
|
13986
13923
|
// src/widget/useImageAttachments.ts
|
|
13987
|
-
import { useState as
|
|
13924
|
+
import { useState as useState4, useCallback as useCallback4 } from "react";
|
|
13988
13925
|
var launchImageLibrary = null;
|
|
13989
13926
|
var launchCamera = null;
|
|
13990
13927
|
try {
|
|
@@ -13995,7 +13932,7 @@ try {
|
|
|
13995
13932
|
}
|
|
13996
13933
|
var IMAGE_PICKER_AVAILABLE = launchImageLibrary !== null;
|
|
13997
13934
|
function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
13998
|
-
const [images, setImages] =
|
|
13935
|
+
const [images, setImages] = useState4([]);
|
|
13999
13936
|
const pickFromGallery = useCallback4(async () => {
|
|
14000
13937
|
if (!launchImageLibrary || images.length >= maxImages) return;
|
|
14001
13938
|
launchImageLibrary(
|
|
@@ -14061,17 +13998,17 @@ function useImageAttachments(uploadFn, maxImages, bucket = "screenshots") {
|
|
|
14061
13998
|
}
|
|
14062
13999
|
|
|
14063
14000
|
// src/widget/ImagePickerButtons.tsx
|
|
14064
|
-
import
|
|
14065
|
-
import { View as
|
|
14001
|
+
import React6 from "react";
|
|
14002
|
+
import { View as View5, Text as Text5, TouchableOpacity as TouchableOpacity5, StyleSheet as StyleSheet6 } from "react-native";
|
|
14066
14003
|
|
|
14067
14004
|
// src/widget/ImagePreviewStrip.tsx
|
|
14068
|
-
import
|
|
14069
|
-
import { View as
|
|
14005
|
+
import React5 from "react";
|
|
14006
|
+
import { View as View4, Text as Text4, TouchableOpacity as TouchableOpacity4, ScrollView, Image, ActivityIndicator, StyleSheet as StyleSheet5 } from "react-native";
|
|
14070
14007
|
function ImagePreviewStrip({ images, onRemove }) {
|
|
14071
14008
|
if (images.length === 0) return null;
|
|
14072
|
-
return /* @__PURE__ */
|
|
14009
|
+
return /* @__PURE__ */ React5.createElement(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: styles4.strip }, images.map((img) => /* @__PURE__ */ React5.createElement(View4, { key: img.id, style: styles4.thumbContainer }, /* @__PURE__ */ React5.createElement(Image, { source: { uri: img.localUri }, style: styles4.thumb }), img.status === "uploading" && /* @__PURE__ */ React5.createElement(View4, { style: styles4.thumbOverlay }, /* @__PURE__ */ React5.createElement(ActivityIndicator, { size: "small", color: "#fff" })), img.status === "error" && /* @__PURE__ */ React5.createElement(View4, { style: [styles4.thumbOverlay, styles4.thumbOverlayError] }, /* @__PURE__ */ React5.createElement(Text4, { style: styles4.thumbErrorText }, "!")), /* @__PURE__ */ React5.createElement(TouchableOpacity4, { style: styles4.thumbRemove, onPress: () => onRemove(img.id) }, /* @__PURE__ */ React5.createElement(Text4, { style: styles4.thumbRemoveText }, "\u2715")))));
|
|
14073
14010
|
}
|
|
14074
|
-
var
|
|
14011
|
+
var styles4 = StyleSheet5.create({
|
|
14075
14012
|
strip: {
|
|
14076
14013
|
flexDirection: "row",
|
|
14077
14014
|
marginTop: 4
|
|
@@ -14090,7 +14027,7 @@ var styles5 = StyleSheet6.create({
|
|
|
14090
14027
|
borderRadius: 8
|
|
14091
14028
|
},
|
|
14092
14029
|
thumbOverlay: {
|
|
14093
|
-
...
|
|
14030
|
+
...StyleSheet5.absoluteFillObject,
|
|
14094
14031
|
backgroundColor: "rgba(0,0,0,0.5)",
|
|
14095
14032
|
justifyContent: "center",
|
|
14096
14033
|
alignItems: "center",
|
|
@@ -14125,25 +14062,25 @@ var styles5 = StyleSheet6.create({
|
|
|
14125
14062
|
// src/widget/ImagePickerButtons.tsx
|
|
14126
14063
|
function ImagePickerButtons({ images, maxImages, onPickGallery, onPickCamera, onRemove, label }) {
|
|
14127
14064
|
if (!IMAGE_PICKER_AVAILABLE) return null;
|
|
14128
|
-
return /* @__PURE__ */
|
|
14129
|
-
|
|
14065
|
+
return /* @__PURE__ */ React6.createElement(View5, { style: styles5.section }, label && /* @__PURE__ */ React6.createElement(Text5, { style: styles5.label }, label), /* @__PURE__ */ React6.createElement(View5, { style: styles5.buttonRow }, /* @__PURE__ */ React6.createElement(
|
|
14066
|
+
TouchableOpacity5,
|
|
14130
14067
|
{
|
|
14131
|
-
style:
|
|
14068
|
+
style: styles5.pickButton,
|
|
14132
14069
|
onPress: onPickGallery,
|
|
14133
14070
|
disabled: images.length >= maxImages
|
|
14134
14071
|
},
|
|
14135
|
-
/* @__PURE__ */
|
|
14136
|
-
), /* @__PURE__ */
|
|
14137
|
-
|
|
14072
|
+
/* @__PURE__ */ React6.createElement(Text5, { style: [styles5.pickButtonText, images.length >= maxImages && styles5.pickButtonDisabled] }, "Gallery")
|
|
14073
|
+
), /* @__PURE__ */ React6.createElement(
|
|
14074
|
+
TouchableOpacity5,
|
|
14138
14075
|
{
|
|
14139
|
-
style:
|
|
14076
|
+
style: styles5.pickButton,
|
|
14140
14077
|
onPress: onPickCamera,
|
|
14141
14078
|
disabled: images.length >= maxImages
|
|
14142
14079
|
},
|
|
14143
|
-
/* @__PURE__ */
|
|
14144
|
-
), /* @__PURE__ */
|
|
14080
|
+
/* @__PURE__ */ React6.createElement(Text5, { style: [styles5.pickButtonText, images.length >= maxImages && styles5.pickButtonDisabled] }, "Camera")
|
|
14081
|
+
), /* @__PURE__ */ React6.createElement(Text5, { style: styles5.countText }, images.length, "/", maxImages)), /* @__PURE__ */ React6.createElement(ImagePreviewStrip, { images, onRemove }));
|
|
14145
14082
|
}
|
|
14146
|
-
var
|
|
14083
|
+
var styles5 = StyleSheet6.create({
|
|
14147
14084
|
section: {
|
|
14148
14085
|
marginTop: 12,
|
|
14149
14086
|
marginBottom: 4
|
|
@@ -14182,7 +14119,123 @@ var styles6 = StyleSheet7.create({
|
|
|
14182
14119
|
}
|
|
14183
14120
|
});
|
|
14184
14121
|
|
|
14122
|
+
// src/widget/screens/TestFeedbackScreen.tsx
|
|
14123
|
+
function TestFeedbackScreen({ status, assignmentId, nav }) {
|
|
14124
|
+
const { client, assignments, refreshAssignments, uploadImage } = useBugBear();
|
|
14125
|
+
const images = useImageAttachments(uploadImage, 3, "screenshots");
|
|
14126
|
+
const [rating, setRating] = useState5(5);
|
|
14127
|
+
const [note, setNote] = useState5("");
|
|
14128
|
+
const [flags, setFlags] = useState5({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
|
|
14129
|
+
const [submitting, setSubmitting] = useState5(false);
|
|
14130
|
+
const assignment = assignments.find((a) => a.id === assignmentId);
|
|
14131
|
+
const showFlags = rating < 4;
|
|
14132
|
+
const handleSubmit = async () => {
|
|
14133
|
+
setSubmitting(true);
|
|
14134
|
+
if (client && assignment) {
|
|
14135
|
+
const screenshotUrls = images.getScreenshotUrls();
|
|
14136
|
+
await client.submitTestFeedback({
|
|
14137
|
+
testCaseId: assignment.testCase.id,
|
|
14138
|
+
assignmentId,
|
|
14139
|
+
feedback: {
|
|
14140
|
+
rating,
|
|
14141
|
+
feedbackNote: note.trim() || void 0,
|
|
14142
|
+
...showFlags ? {
|
|
14143
|
+
isOutdated: flags.isOutdated,
|
|
14144
|
+
needsMoreDetail: flags.needsMoreDetail,
|
|
14145
|
+
stepsUnclear: flags.stepsUnclear,
|
|
14146
|
+
expectedResultUnclear: flags.expectedResultUnclear
|
|
14147
|
+
} : {}
|
|
14148
|
+
},
|
|
14149
|
+
screenshotUrls: screenshotUrls.length > 0 ? screenshotUrls : void 0
|
|
14150
|
+
});
|
|
14151
|
+
}
|
|
14152
|
+
await refreshAssignments();
|
|
14153
|
+
setSubmitting(false);
|
|
14154
|
+
if (status === "failed") {
|
|
14155
|
+
nav.replace({ name: "REPORT", prefill: { type: "test_fail", assignmentId, testCaseId: assignment?.testCase.id } });
|
|
14156
|
+
} else {
|
|
14157
|
+
const remaining = assignments.filter((a) => (a.status === "pending" || a.status === "in_progress") && a.id !== assignmentId);
|
|
14158
|
+
if (remaining.length > 0) {
|
|
14159
|
+
nav.replace({ name: "TEST_DETAIL", testId: remaining[0].id });
|
|
14160
|
+
} else {
|
|
14161
|
+
nav.reset();
|
|
14162
|
+
}
|
|
14163
|
+
}
|
|
14164
|
+
};
|
|
14165
|
+
const handleSkip = () => {
|
|
14166
|
+
if (status === "failed") {
|
|
14167
|
+
nav.replace({ name: "REPORT", prefill: { type: "test_fail", assignmentId, testCaseId: assignment?.testCase.id } });
|
|
14168
|
+
} else {
|
|
14169
|
+
const remaining = assignments.filter((a) => (a.status === "pending" || a.status === "in_progress") && a.id !== assignmentId);
|
|
14170
|
+
if (remaining.length > 0) {
|
|
14171
|
+
nav.replace({ name: "TEST_DETAIL", testId: remaining[0].id });
|
|
14172
|
+
} else {
|
|
14173
|
+
nav.reset();
|
|
14174
|
+
}
|
|
14175
|
+
}
|
|
14176
|
+
};
|
|
14177
|
+
return /* @__PURE__ */ React7.createElement(View6, { style: styles6.container }, /* @__PURE__ */ React7.createElement(Text6, { style: styles6.header }, status === "passed" ? "\u2705 Test Passed!" : "\u274C Test Failed"), /* @__PURE__ */ React7.createElement(Text6, { style: styles6.subheader }, "Rate this test case"), /* @__PURE__ */ React7.createElement(View6, { style: styles6.starRow }, [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ React7.createElement(TouchableOpacity6, { key: n, onPress: () => setRating(n), style: styles6.starButton }, /* @__PURE__ */ React7.createElement(Text6, { style: [styles6.star, n <= rating && styles6.starActive] }, n <= rating ? "\u2605" : "\u2606")))), showFlags && /* @__PURE__ */ React7.createElement(View6, { style: styles6.flagsSection }, /* @__PURE__ */ React7.createElement(Text6, { style: styles6.flagsLabel }, "What could be improved?"), [
|
|
14178
|
+
{ key: "isOutdated", label: "Test is outdated" },
|
|
14179
|
+
{ key: "needsMoreDetail", label: "Needs more detail" },
|
|
14180
|
+
{ key: "stepsUnclear", label: "Steps are unclear" },
|
|
14181
|
+
{ key: "expectedResultUnclear", label: "Expected result unclear" }
|
|
14182
|
+
].map(({ key, label }) => /* @__PURE__ */ React7.createElement(
|
|
14183
|
+
TouchableOpacity6,
|
|
14184
|
+
{
|
|
14185
|
+
key,
|
|
14186
|
+
style: [styles6.flagItem, flags[key] && styles6.flagItemActive],
|
|
14187
|
+
onPress: () => setFlags((prev) => ({ ...prev, [key]: !prev[key] }))
|
|
14188
|
+
},
|
|
14189
|
+
/* @__PURE__ */ React7.createElement(View6, { style: [styles6.flagCheck, flags[key] && styles6.flagCheckActive] }, flags[key] && /* @__PURE__ */ React7.createElement(Text6, { style: styles6.flagCheckmark }, "\u2713")),
|
|
14190
|
+
/* @__PURE__ */ React7.createElement(Text6, { style: [styles6.flagText, flags[key] && styles6.flagTextActive] }, label)
|
|
14191
|
+
))), /* @__PURE__ */ React7.createElement(
|
|
14192
|
+
TextInput2,
|
|
14193
|
+
{
|
|
14194
|
+
style: styles6.noteInput,
|
|
14195
|
+
value: note,
|
|
14196
|
+
onChangeText: setNote,
|
|
14197
|
+
placeholder: "Add a note (optional)",
|
|
14198
|
+
placeholderTextColor: colors.textMuted,
|
|
14199
|
+
multiline: true
|
|
14200
|
+
}
|
|
14201
|
+
), /* @__PURE__ */ React7.createElement(
|
|
14202
|
+
ImagePickerButtons,
|
|
14203
|
+
{
|
|
14204
|
+
images: images.images,
|
|
14205
|
+
maxImages: 3,
|
|
14206
|
+
onPickGallery: images.pickFromGallery,
|
|
14207
|
+
onPickCamera: images.pickFromCamera,
|
|
14208
|
+
onRemove: images.removeImage,
|
|
14209
|
+
label: "Screenshots (optional)"
|
|
14210
|
+
}
|
|
14211
|
+
), /* @__PURE__ */ React7.createElement(View6, { style: styles6.actions }, /* @__PURE__ */ React7.createElement(TouchableOpacity6, { style: styles6.skipButton, onPress: handleSkip }, /* @__PURE__ */ React7.createElement(Text6, { style: styles6.skipText }, "Skip")), /* @__PURE__ */ React7.createElement(TouchableOpacity6, { style: [shared.primaryButton, { flex: 2, opacity: submitting || images.isUploading ? 0.5 : 1 }], onPress: handleSubmit, disabled: submitting || images.isUploading }, /* @__PURE__ */ React7.createElement(Text6, { style: shared.primaryButtonText }, images.isUploading ? "Uploading..." : submitting ? "Submitting..." : "Submit"))));
|
|
14212
|
+
}
|
|
14213
|
+
var styles6 = StyleSheet7.create({
|
|
14214
|
+
container: { paddingTop: 8 },
|
|
14215
|
+
header: { fontSize: 22, fontWeight: "700", color: colors.textPrimary, textAlign: "center", marginBottom: 4 },
|
|
14216
|
+
subheader: { fontSize: 14, color: colors.textMuted, textAlign: "center", marginBottom: 20 },
|
|
14217
|
+
starRow: { flexDirection: "row", justifyContent: "center", gap: 8, marginBottom: 20 },
|
|
14218
|
+
starButton: { padding: 4 },
|
|
14219
|
+
star: { fontSize: 36, color: colors.textDim },
|
|
14220
|
+
starActive: { color: "#facc15" },
|
|
14221
|
+
flagsSection: { marginBottom: 16 },
|
|
14222
|
+
flagsLabel: { fontSize: 14, fontWeight: "500", color: colors.textSecondary, marginBottom: 10 },
|
|
14223
|
+
flagItem: { flexDirection: "row", alignItems: "center", paddingVertical: 10, paddingHorizontal: 12, borderRadius: 8, marginBottom: 4, backgroundColor: colors.card },
|
|
14224
|
+
flagItemActive: { backgroundColor: colors.yellowDark, borderWidth: 1, borderColor: colors.yellow },
|
|
14225
|
+
flagCheck: { width: 20, height: 20, borderRadius: 4, borderWidth: 2, borderColor: colors.border, marginRight: 10, justifyContent: "center", alignItems: "center" },
|
|
14226
|
+
flagCheckActive: { backgroundColor: colors.yellow, borderColor: colors.yellow },
|
|
14227
|
+
flagCheckmark: { fontSize: 12, fontWeight: "bold", color: "#000" },
|
|
14228
|
+
flagText: { fontSize: 14, color: colors.textSecondary },
|
|
14229
|
+
flagTextActive: { color: colors.yellow },
|
|
14230
|
+
noteInput: { backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border, borderRadius: 10, padding: 12, fontSize: 14, color: colors.textPrimary, minHeight: 60, textAlignVertical: "top", marginBottom: 16 },
|
|
14231
|
+
actions: { flexDirection: "row", gap: 10 },
|
|
14232
|
+
skipButton: { flex: 1, paddingVertical: 14, borderRadius: 12, alignItems: "center", backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border },
|
|
14233
|
+
skipText: { fontSize: 15, color: colors.textSecondary }
|
|
14234
|
+
});
|
|
14235
|
+
|
|
14185
14236
|
// src/widget/screens/ReportScreen.tsx
|
|
14237
|
+
import React8, { useState as useState6 } from "react";
|
|
14238
|
+
import { View as View7, Text as Text7, TouchableOpacity as TouchableOpacity7, TextInput as TextInput3, StyleSheet as StyleSheet8 } from "react-native";
|
|
14186
14239
|
function ReportScreen({ nav, prefill }) {
|
|
14187
14240
|
const { client, getDeviceInfo, uploadImage, refreshAssignments } = useBugBear();
|
|
14188
14241
|
const [reportType, setReportType] = useState6(prefill?.type || "bug");
|
|
@@ -14794,7 +14847,7 @@ function BugBearButton({
|
|
|
14794
14847
|
onPress: () => setModalVisible(true),
|
|
14795
14848
|
activeOpacity: draggable ? 1 : 0.7
|
|
14796
14849
|
},
|
|
14797
|
-
/* @__PURE__ */ React14.createElement(
|
|
14850
|
+
/* @__PURE__ */ React14.createElement(Image3, { source: { uri: BUGBEAR_LOGO_BASE64 }, style: styles13.fabIcon }),
|
|
14798
14851
|
badgeCount > 0 && /* @__PURE__ */ React14.createElement(View13, { style: styles13.badge }, /* @__PURE__ */ React14.createElement(Text13, { style: styles13.badgeText }, badgeCount > 9 ? "9+" : badgeCount))
|
|
14799
14852
|
)
|
|
14800
14853
|
), /* @__PURE__ */ React14.createElement(
|
|
@@ -14844,7 +14897,9 @@ var styles13 = StyleSheet14.create({
|
|
|
14844
14897
|
elevation: 8
|
|
14845
14898
|
},
|
|
14846
14899
|
fabIcon: {
|
|
14847
|
-
|
|
14900
|
+
width: 32,
|
|
14901
|
+
height: 32,
|
|
14902
|
+
borderRadius: 16
|
|
14848
14903
|
},
|
|
14849
14904
|
badge: {
|
|
14850
14905
|
position: "absolute",
|