@mushi-mushi/react-native 0.19.2 → 0.20.0
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/CHANGELOG.md +19 -0
- package/CONTRIBUTING.md +14 -2
- package/README.md +0 -1
- package/SECURITY.md +1 -1
- package/dist/index.cjs +392 -120
- package/dist/index.d.cts +56 -3
- package/dist/index.d.ts +56 -3
- package/dist/index.js +357 -81
- package/package.json +9 -4
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AsyncStorageQueue: () => AsyncStorageQueue,
|
|
34
|
+
MUSHI_BANNER_DEFAULT_HEIGHT: () => MUSHI_BANNER_DEFAULT_HEIGHT,
|
|
35
|
+
MushiBanner: () => MushiBanner,
|
|
34
36
|
MushiBottomSheet: () => MushiBottomSheet,
|
|
35
37
|
MushiFloatingButton: () => MushiFloatingButton,
|
|
36
38
|
MushiProvider: () => MushiProvider,
|
|
@@ -46,8 +48,8 @@ __export(index_exports, {
|
|
|
46
48
|
module.exports = __toCommonJS(index_exports);
|
|
47
49
|
|
|
48
50
|
// src/provider.tsx
|
|
49
|
-
var
|
|
50
|
-
var
|
|
51
|
+
var import_react4 = require("react");
|
|
52
|
+
var import_core6 = require("@mushi-mushi/core");
|
|
51
53
|
|
|
52
54
|
// src/capture/console-capture.ts
|
|
53
55
|
var import_core = require("@mushi-mushi/core");
|
|
@@ -476,32 +478,64 @@ function sleep(ms) {
|
|
|
476
478
|
var import_react = require("react");
|
|
477
479
|
var import_react_native2 = require("react-native");
|
|
478
480
|
var import_core3 = require("@mushi-mushi/core");
|
|
481
|
+
var import_i18n = require("@mushi-mushi/web/i18n");
|
|
482
|
+
|
|
483
|
+
// src/reporter-status.ts
|
|
484
|
+
function reporterStatusShort(status) {
|
|
485
|
+
switch (status) {
|
|
486
|
+
case "new":
|
|
487
|
+
case "queued":
|
|
488
|
+
case "pending":
|
|
489
|
+
case "submitted":
|
|
490
|
+
return "Received";
|
|
491
|
+
case "classified":
|
|
492
|
+
case "triaged":
|
|
493
|
+
case "grouped":
|
|
494
|
+
case "dispatched":
|
|
495
|
+
return "In review";
|
|
496
|
+
case "fixing":
|
|
497
|
+
return "Fixing";
|
|
498
|
+
case "fixed":
|
|
499
|
+
case "resolved":
|
|
500
|
+
case "completed":
|
|
501
|
+
return "Fixed";
|
|
502
|
+
case "dismissed":
|
|
503
|
+
return "Closed";
|
|
504
|
+
default:
|
|
505
|
+
return status.replace(/_/g, " ").slice(0, 16);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// src/components/MushiBottomSheet.tsx
|
|
479
510
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
480
511
|
var { height: SCREEN_HEIGHT } = import_react_native2.Dimensions.get("window");
|
|
481
512
|
var SHEET_HEIGHT = SCREEN_HEIGHT * 0.55;
|
|
482
513
|
var DISMISS_THRESHOLD = 80;
|
|
483
|
-
var
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
514
|
+
var CATEGORY_KEYS = ["bug", "slow", "visual", "confusing", "other"];
|
|
515
|
+
var CATEGORY_EMOJI = {
|
|
516
|
+
bug: "\u{1F41B}",
|
|
517
|
+
slow: "\u{1F422}",
|
|
518
|
+
visual: "\u{1F3A8}",
|
|
519
|
+
confusing: "\u{1F615}",
|
|
520
|
+
other: "\u{1F4AC}"
|
|
488
521
|
};
|
|
489
|
-
var CATEGORIES = [
|
|
490
|
-
{ key: "bug", emoji: "\u{1F41B}", label: "Bug" },
|
|
491
|
-
{ key: "slow", emoji: "\u{1F422}", label: "Slow" },
|
|
492
|
-
{ key: "visual", emoji: "\u{1F3A8}", label: "Visual" },
|
|
493
|
-
{ key: "confusing", emoji: "\u{1F615}", label: "Confusing" },
|
|
494
|
-
{ key: "other", emoji: "\u{1F4AC}", label: "Other" }
|
|
495
|
-
];
|
|
496
522
|
var VERIFIABLE_STATUSES = /* @__PURE__ */ new Set(["fixed", "resolved", "verified"]);
|
|
497
523
|
var MushiBottomSheet = ({
|
|
498
524
|
visible,
|
|
499
525
|
onClose,
|
|
526
|
+
preferredTab = "report",
|
|
500
527
|
screenshotDataUrl,
|
|
501
528
|
onClearScreenshot,
|
|
502
|
-
screenshotSensitiveHint
|
|
529
|
+
screenshotSensitiveHint,
|
|
530
|
+
assistantEnabled = false,
|
|
531
|
+
assistantLabel = import_core3.MUSHI_COPY.assistantTab,
|
|
532
|
+
assistantGreeting,
|
|
533
|
+
assistantSuggestions = [],
|
|
534
|
+
inboxPollIntervalMs = 0
|
|
503
535
|
}) => {
|
|
504
536
|
const mushi = useMushiContext();
|
|
537
|
+
const t = (0, import_i18n.getLocale)();
|
|
538
|
+
const greeting = assistantGreeting ?? t.assistant.defaultGreeting;
|
|
505
539
|
const scheme = (0, import_react_native2.useColorScheme)();
|
|
506
540
|
const dark = scheme === "dark";
|
|
507
541
|
const translateY = (0, import_react.useRef)(new import_react_native2.Animated.Value(SHEET_HEIGHT)).current;
|
|
@@ -515,6 +549,11 @@ var MushiBottomSheet = ({
|
|
|
515
549
|
const [selectedReportId, setSelectedReportId] = (0, import_react.useState)(null);
|
|
516
550
|
const [threadComments, setThreadComments] = (0, import_react.useState)([]);
|
|
517
551
|
const [replyText, setReplyText] = (0, import_react.useState)("");
|
|
552
|
+
const [assistantInput, setAssistantInput] = (0, import_react.useState)("");
|
|
553
|
+
const [assistantThreadId, setAssistantThreadId] = (0, import_react.useState)(null);
|
|
554
|
+
const [assistantSending, setAssistantSending] = (0, import_react.useState)(false);
|
|
555
|
+
const [assistantError, setAssistantError] = (0, import_react.useState)(null);
|
|
556
|
+
const [assistantTurns, setAssistantTurns] = (0, import_react.useState)([]);
|
|
518
557
|
const [screenshotAttached, setScreenshotAttached] = (0, import_react.useState)(true);
|
|
519
558
|
const loadInbox = (0, import_react.useCallback)(async () => {
|
|
520
559
|
if (!mushi?.listMyReports) return;
|
|
@@ -529,9 +568,17 @@ var MushiBottomSheet = ({
|
|
|
529
568
|
(0, import_react.useEffect)(() => {
|
|
530
569
|
if (visible) {
|
|
531
570
|
setScreenshotAttached(true);
|
|
532
|
-
|
|
571
|
+
setSheetTab(preferredTab);
|
|
572
|
+
if (preferredTab === "inbox") void loadInbox();
|
|
533
573
|
}
|
|
534
|
-
}, [visible,
|
|
574
|
+
}, [visible, preferredTab, loadInbox]);
|
|
575
|
+
(0, import_react.useEffect)(() => {
|
|
576
|
+
if (!visible || sheetTab !== "inbox" || inboxPollIntervalMs <= 0) return;
|
|
577
|
+
const timer = setInterval(() => {
|
|
578
|
+
void loadInbox();
|
|
579
|
+
}, inboxPollIntervalMs);
|
|
580
|
+
return () => clearInterval(timer);
|
|
581
|
+
}, [visible, sheetTab, inboxPollIntervalMs, loadInbox]);
|
|
535
582
|
const openThread = (0, import_react.useCallback)(async (reportId) => {
|
|
536
583
|
setSelectedReportId(reportId);
|
|
537
584
|
if (!mushi?.listMyComments) return;
|
|
@@ -550,6 +597,29 @@ var MushiBottomSheet = ({
|
|
|
550
597
|
await loadInbox();
|
|
551
598
|
await openThread(selectedReportId);
|
|
552
599
|
}, [mushi, selectedReportId, loadInbox, openThread]);
|
|
600
|
+
const sendAssistant = (0, import_react.useCallback)(async (message) => {
|
|
601
|
+
if (!mushi?.askAssistant || !message.trim() || assistantSending) return;
|
|
602
|
+
const trimmed = message.trim();
|
|
603
|
+
setAssistantInput("");
|
|
604
|
+
setAssistantError(null);
|
|
605
|
+
setAssistantTurns((prev) => [...prev, { role: "user", text: trimmed }]);
|
|
606
|
+
setAssistantSending(true);
|
|
607
|
+
try {
|
|
608
|
+
const reply = await mushi.askAssistant(trimmed, assistantThreadId);
|
|
609
|
+
if (!reply) {
|
|
610
|
+
setAssistantError("Could not reach the assistant. Try again.");
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (reply.threadId) setAssistantThreadId(reply.threadId);
|
|
614
|
+
const botText = reply.kind === "clarify" ? reply.question ?? reply.text ?? "" : reply.text ?? "";
|
|
615
|
+
setAssistantTurns((prev) => [
|
|
616
|
+
...prev,
|
|
617
|
+
{ role: "bot", text: botText, options: reply.options }
|
|
618
|
+
]);
|
|
619
|
+
} finally {
|
|
620
|
+
setAssistantSending(false);
|
|
621
|
+
}
|
|
622
|
+
}, [mushi, assistantSending, assistantThreadId]);
|
|
553
623
|
const resetForm = (0, import_react.useCallback)(() => {
|
|
554
624
|
setCategory(null);
|
|
555
625
|
setDescription("");
|
|
@@ -634,7 +704,8 @@ var MushiBottomSheet = ({
|
|
|
634
704
|
};
|
|
635
705
|
const activeScreenshot = screenshotDataUrl && screenshotAttached ? screenshotDataUrl : null;
|
|
636
706
|
const pal = (0, import_core3.mushiPalette)(dark ? "dark" : "light");
|
|
637
|
-
const colors = dark ? { bg: pal.paper, text: pal.ink, sub: pal.inkMuted, card: pal.paperRaised, accent:
|
|
707
|
+
const colors = dark ? { bg: pal.paper, text: pal.ink, sub: pal.inkMuted, card: pal.paperRaised, accent: import_core3.MUSHI_BANNER_NEON.bg, accentInk: import_core3.MUSHI_BANNER_NEON.fg, border: pal.ruleStrong, backdrop: "rgba(0,0,0,0.6)", disabled: "#3a3a3c", disabledText: pal.inkFaint } : { bg: pal.paperRaised, text: pal.ink, sub: pal.inkMuted, card: pal.paper, accent: import_core3.MUSHI_BANNER_NEON.bg, accentInk: import_core3.MUSHI_BANNER_NEON.fg, border: pal.ruleStrong, backdrop: "rgba(0,0,0,0.35)", disabled: "#d1d1d6", disabledText: pal.inkFaint };
|
|
708
|
+
const sheetTabs = ["report", "inbox", ...assistantEnabled ? ["assistant"] : []];
|
|
638
709
|
const canSubmit = !!category && description.trim().length > 0 && phase === "form";
|
|
639
710
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Modal, { visible, transparent: true, animationType: "none", statusBarTranslucent: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
640
711
|
import_react_native2.KeyboardAvoidingView,
|
|
@@ -659,11 +730,11 @@ var MushiBottomSheet = ({
|
|
|
659
730
|
],
|
|
660
731
|
children: [
|
|
661
732
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { ...panResponder.panHandlers, style: s.handleArea, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [s.handle, { backgroundColor: colors.sub }] }) }),
|
|
662
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [s.brandHeader, { backgroundColor:
|
|
663
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.brandEyebrow, { color:
|
|
664
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.brandTitle, { color:
|
|
733
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [s.brandHeader, { backgroundColor: import_core3.MUSHI_BANNER_NEON.bg, borderBottomColor: import_core3.MUSHI_BANNER_NEON.border }], children: [
|
|
734
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.brandEyebrow, { color: import_core3.MUSHI_BANNER_NEON.fg }], children: "MUSHI \xB7 BETA" }),
|
|
735
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.brandTitle, { color: import_core3.MUSHI_BANNER_NEON.fg }], children: sheetTab === "assistant" ? assistantLabel : sheetTab === "inbox" ? t.flows.reports.title : t.widget.title })
|
|
665
736
|
] }),
|
|
666
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: s.tabRow, children:
|
|
737
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: s.tabRow, children: sheetTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
667
738
|
import_react_native2.TouchableOpacity,
|
|
668
739
|
{
|
|
669
740
|
onPress: () => {
|
|
@@ -672,12 +743,68 @@ var MushiBottomSheet = ({
|
|
|
672
743
|
else setSelectedReportId(null);
|
|
673
744
|
},
|
|
674
745
|
style: [s.tabBtn, sheetTab === tab && { borderBottomColor: colors.accent }],
|
|
675
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.tabLabel, { color: sheetTab === tab ? colors.text : colors.sub }], children: tab === "report" ?
|
|
746
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.tabLabel, { color: sheetTab === tab ? colors.text : colors.sub }], children: tab === "report" ? t.widget.trigger : tab === "inbox" ? t.flows.reports.title : assistantLabel })
|
|
676
747
|
},
|
|
677
748
|
tab
|
|
678
749
|
)) }),
|
|
679
|
-
sheetTab === "
|
|
680
|
-
|
|
750
|
+
sheetTab === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.ScrollView, { style: s.body, keyboardShouldPersistTaps: "handled", children: [
|
|
751
|
+
assistantTurns.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
752
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, marginBottom: 12, lineHeight: 20 }, children: greeting }),
|
|
753
|
+
assistantSuggestions.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
754
|
+
import_react_native2.TouchableOpacity,
|
|
755
|
+
{
|
|
756
|
+
style: [s.assistantChip, { borderColor: colors.border, backgroundColor: colors.card }],
|
|
757
|
+
onPress: () => void sendAssistant(chip),
|
|
758
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.text, fontSize: 13 }, children: chip })
|
|
759
|
+
},
|
|
760
|
+
chip
|
|
761
|
+
))
|
|
762
|
+
] }) : assistantTurns.map((turn, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
763
|
+
import_react_native2.View,
|
|
764
|
+
{
|
|
765
|
+
style: [
|
|
766
|
+
s.assistantBubble,
|
|
767
|
+
{
|
|
768
|
+
alignSelf: turn.role === "user" ? "flex-end" : "flex-start",
|
|
769
|
+
backgroundColor: turn.role === "user" ? colors.accent : colors.card
|
|
770
|
+
}
|
|
771
|
+
],
|
|
772
|
+
children: [
|
|
773
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: turn.role === "user" ? colors.accentInk : colors.text }, children: turn.text }),
|
|
774
|
+
turn.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { onPress: () => void sendAssistant(opt), style: { marginTop: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.accent, fontSize: 12 }, children: opt }) }, opt))
|
|
775
|
+
]
|
|
776
|
+
},
|
|
777
|
+
`${turn.role}-${idx}`
|
|
778
|
+
)),
|
|
779
|
+
assistantSending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, marginTop: 8 }, accessibilityLiveRegion: "polite", children: t.assistant.thinking }) : null,
|
|
780
|
+
assistantError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: pal.danger, marginTop: 8 }, accessibilityRole: "alert", children: assistantError }) : null,
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.assistantComposer, children: [
|
|
782
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
783
|
+
import_react_native2.TextInput,
|
|
784
|
+
{
|
|
785
|
+
style: [s.input, { flex: 1, minHeight: 44, backgroundColor: colors.card, color: colors.text, borderColor: colors.border }],
|
|
786
|
+
placeholder: t.assistant.inputPlaceholder,
|
|
787
|
+
placeholderTextColor: colors.sub,
|
|
788
|
+
value: assistantInput,
|
|
789
|
+
onChangeText: setAssistantInput,
|
|
790
|
+
editable: !assistantSending
|
|
791
|
+
}
|
|
792
|
+
),
|
|
793
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
794
|
+
import_react_native2.TouchableOpacity,
|
|
795
|
+
{
|
|
796
|
+
style: [s.submitBtn, { backgroundColor: colors.accent, paddingHorizontal: 16 }],
|
|
797
|
+
onPress: () => void sendAssistant(assistantInput),
|
|
798
|
+
disabled: !assistantInput.trim() || assistantSending,
|
|
799
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.accentInk }], children: "\u2191" })
|
|
800
|
+
}
|
|
801
|
+
)
|
|
802
|
+
] })
|
|
803
|
+
] }) : sheetTab === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.ScrollView, { style: s.body, keyboardShouldPersistTaps: "handled", children: inboxLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub }, children: t.flows.reports.loading }) : selectedReportId ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
804
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { onPress: () => setSelectedReportId(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: { color: colors.accent, marginBottom: 8 }, children: [
|
|
805
|
+
"\u2190 ",
|
|
806
|
+
t.widget.back
|
|
807
|
+
] }) }),
|
|
681
808
|
threadComments.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [s.threadBubble, { backgroundColor: colors.card }], children: [
|
|
682
809
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, fontSize: 11 }, children: c.author_kind }),
|
|
683
810
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.text }, children: c.body })
|
|
@@ -685,42 +812,26 @@ var MushiBottomSheet = ({
|
|
|
685
812
|
VERIFIABLE_STATUSES.has(
|
|
686
813
|
inboxReports.find((r) => r.id === selectedReportId)?.status ?? ""
|
|
687
814
|
) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.verifyRow, children: [
|
|
688
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { style: [s.verifyBtn, { backgroundColor: colors.accent }], onPress: () => submitFeedback("confirms"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.accentInk }], children:
|
|
689
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { style: [s.verifyBtn, { backgroundColor: colors.border }], onPress: () => submitFeedback("not_fixed"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.text }], children:
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { style: [s.verifyBtn, { backgroundColor: colors.accent }], onPress: () => submitFeedback("confirms"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.accentInk }], children: t.flows.thread.confirmFixed }) }),
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { style: [s.verifyBtn, { backgroundColor: colors.border }], onPress: () => submitFeedback("not_fixed"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.text }], children: t.flows.thread.notFixed }) })
|
|
690
817
|
] }),
|
|
691
818
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
692
819
|
import_react_native2.TextInput,
|
|
693
820
|
{
|
|
694
821
|
style: [s.input, { backgroundColor: colors.card, color: colors.text, borderColor: colors.border, minHeight: 48 }],
|
|
695
|
-
placeholder:
|
|
822
|
+
placeholder: t.flows.thread.replyPlaceholder,
|
|
696
823
|
placeholderTextColor: colors.sub,
|
|
697
824
|
value: replyText,
|
|
698
825
|
onChangeText: setReplyText
|
|
699
826
|
}
|
|
700
827
|
),
|
|
701
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { style: [s.submitBtn, { backgroundColor: colors.accent }], onPress: sendReply, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.accentInk }], children:
|
|
828
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { style: [s.submitBtn, { backgroundColor: colors.accent }], onPress: sendReply, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.accentInk }], children: t.flows.thread.send }) })
|
|
702
829
|
] }) : inboxReports.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.TouchableOpacity, { style: [s.inboxRow, { borderColor: colors.border }], onPress: () => openThread(r.id), children: [
|
|
703
830
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.text, fontWeight: "600" }, numberOfLines: 1, children: (r.summary ?? r.description ?? "Report").slice(0, 60) }),
|
|
704
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, fontSize: 11 }, children: r.status })
|
|
705
|
-
] }, r.id)) }) :
|
|
706
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, fontSize: 13, marginBottom: 16, lineHeight: 18 }, children: "Sign in to track your reports across apps and see the global leaderboard. No password needed." }),
|
|
707
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
708
|
-
import_react_native2.TextInput,
|
|
709
|
-
{
|
|
710
|
-
style: [s.input, { backgroundColor: colors.card, color: colors.text, borderColor: colors.border, minHeight: 48 }],
|
|
711
|
-
placeholder: "you@example.com",
|
|
712
|
-
placeholderTextColor: colors.sub,
|
|
713
|
-
keyboardType: "email-address",
|
|
714
|
-
autoCapitalize: "none",
|
|
715
|
-
autoCorrect: false,
|
|
716
|
-
textContentType: "emailAddress"
|
|
717
|
-
}
|
|
718
|
-
),
|
|
719
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.TouchableOpacity, { style: [s.submitBtn, { backgroundColor: colors.accent }], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.accentInk }], children: "Send sign-in link \u2192" }) }),
|
|
720
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, fontSize: 11, textAlign: "center", marginTop: 12 }, children: "We'll email you a one-tap sign-in link. No password, ever." })
|
|
721
|
-
] }) : phase === "sent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.sentWrap, children: [
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, fontSize: 11 }, children: reporterStatusShort(r.status) })
|
|
832
|
+
] }, r.id)) }) : phase === "sent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.sentWrap, children: [
|
|
722
833
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.sentEmoji], children: "\u2705" }),
|
|
723
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.sentText, { color: colors.text }], children:
|
|
834
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.sentText, { color: colors.text }], children: t.widget.submitted })
|
|
724
835
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
725
836
|
import_react_native2.ScrollView,
|
|
726
837
|
{
|
|
@@ -728,13 +839,13 @@ var MushiBottomSheet = ({
|
|
|
728
839
|
keyboardShouldPersistTaps: "handled",
|
|
729
840
|
contentContainerStyle: { paddingBottom: 24 },
|
|
730
841
|
children: [
|
|
731
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.stepLabel, { color: colors.sub }], children:
|
|
732
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: s.catRow, children:
|
|
733
|
-
const active = category ===
|
|
842
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.stepLabel, { color: colors.sub }], children: t.step1.heading }),
|
|
843
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: s.catRow, children: CATEGORY_KEYS.map((key) => {
|
|
844
|
+
const active = category === key;
|
|
734
845
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
735
846
|
import_react_native2.TouchableOpacity,
|
|
736
847
|
{
|
|
737
|
-
onPress: () => setCategory(
|
|
848
|
+
onPress: () => setCategory(key),
|
|
738
849
|
activeOpacity: 0.7,
|
|
739
850
|
style: [
|
|
740
851
|
s.catBtn,
|
|
@@ -744,7 +855,7 @@ var MushiBottomSheet = ({
|
|
|
744
855
|
}
|
|
745
856
|
],
|
|
746
857
|
children: [
|
|
747
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: s.catEmoji, children:
|
|
858
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: s.catEmoji, children: CATEGORY_EMOJI[key] }),
|
|
748
859
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
749
860
|
import_react_native2.Text,
|
|
750
861
|
{
|
|
@@ -752,12 +863,12 @@ var MushiBottomSheet = ({
|
|
|
752
863
|
s.catLabel,
|
|
753
864
|
{ color: active ? colors.accentInk : colors.text }
|
|
754
865
|
],
|
|
755
|
-
children:
|
|
866
|
+
children: t.step1.categories[key]
|
|
756
867
|
}
|
|
757
868
|
)
|
|
758
869
|
]
|
|
759
870
|
},
|
|
760
|
-
|
|
871
|
+
key
|
|
761
872
|
);
|
|
762
873
|
}) }),
|
|
763
874
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -771,7 +882,7 @@ var MushiBottomSheet = ({
|
|
|
771
882
|
borderColor: colors.border
|
|
772
883
|
}
|
|
773
884
|
],
|
|
774
|
-
placeholder:
|
|
885
|
+
placeholder: t.step3.descriptionPlaceholder,
|
|
775
886
|
placeholderTextColor: colors.sub,
|
|
776
887
|
multiline: true,
|
|
777
888
|
textAlignVertical: "top",
|
|
@@ -786,12 +897,12 @@ var MushiBottomSheet = ({
|
|
|
786
897
|
{
|
|
787
898
|
source: { uri: activeScreenshot },
|
|
788
899
|
style: s.screenshotThumb,
|
|
789
|
-
accessibilityLabel:
|
|
900
|
+
accessibilityLabel: t.step3.screenshotPreviewAlt
|
|
790
901
|
}
|
|
791
902
|
),
|
|
792
903
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.screenshotMeta, children: [
|
|
793
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotLabel, { color: colors.text }], children: "
|
|
794
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotSub, { color: colors.sub }], children: screenshotSensitiveHint && screenshotSensitiveHint.trim() ? `\u26A0 ${screenshotSensitiveHint}` : "
|
|
904
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotLabel, { color: colors.text }], children: t.step3.screenshotAttached.replace(" \u2713", "") }),
|
|
905
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotSub, { color: colors.sub }], children: screenshotSensitiveHint && screenshotSensitiveHint.trim() ? `\u26A0 ${screenshotSensitiveHint}` : t.step3.screenshotSensitiveHint.split("\u2014")[0]?.trim() ?? t.step3.screenshotSensitiveHint })
|
|
795
906
|
] }),
|
|
796
907
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
797
908
|
import_react_native2.TouchableOpacity,
|
|
@@ -801,7 +912,7 @@ var MushiBottomSheet = ({
|
|
|
801
912
|
onClearScreenshot?.();
|
|
802
913
|
},
|
|
803
914
|
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
804
|
-
accessibilityLabel:
|
|
915
|
+
accessibilityLabel: t.widget.close,
|
|
805
916
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotRemove, { color: colors.sub }], children: "\u2715" })
|
|
806
917
|
}
|
|
807
918
|
)
|
|
@@ -816,7 +927,7 @@ var MushiBottomSheet = ({
|
|
|
816
927
|
s.submitBtn,
|
|
817
928
|
{ backgroundColor: canSubmit ? colors.accent : colors.disabled }
|
|
818
929
|
],
|
|
819
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: canSubmit ? colors.accentInk : colors.disabledText }], children: phase === "sending" ?
|
|
930
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: canSubmit ? colors.accentInk : colors.disabledText }], children: phase === "sending" ? t.widget.submitting : t.widget.submit })
|
|
820
931
|
}
|
|
821
932
|
)
|
|
822
933
|
]
|
|
@@ -1022,6 +1133,27 @@ var s = import_react_native2.StyleSheet.create({
|
|
|
1022
1133
|
borderRadius: 10,
|
|
1023
1134
|
paddingVertical: 10,
|
|
1024
1135
|
alignItems: "center"
|
|
1136
|
+
},
|
|
1137
|
+
assistantBubble: {
|
|
1138
|
+
maxWidth: "88%",
|
|
1139
|
+
borderRadius: 12,
|
|
1140
|
+
padding: 12,
|
|
1141
|
+
marginBottom: 10
|
|
1142
|
+
},
|
|
1143
|
+
assistantChip: {
|
|
1144
|
+
borderWidth: 1,
|
|
1145
|
+
borderRadius: 999,
|
|
1146
|
+
paddingHorizontal: 12,
|
|
1147
|
+
paddingVertical: 8,
|
|
1148
|
+
marginBottom: 8,
|
|
1149
|
+
alignSelf: "flex-start"
|
|
1150
|
+
},
|
|
1151
|
+
assistantComposer: {
|
|
1152
|
+
flexDirection: "row",
|
|
1153
|
+
alignItems: "flex-end",
|
|
1154
|
+
gap: 8,
|
|
1155
|
+
marginTop: 12,
|
|
1156
|
+
paddingBottom: 8
|
|
1025
1157
|
}
|
|
1026
1158
|
});
|
|
1027
1159
|
|
|
@@ -1030,7 +1162,7 @@ var import_react2 = require("react");
|
|
|
1030
1162
|
var import_react_native3 = require("react-native");
|
|
1031
1163
|
var import_core4 = require("@mushi-mushi/core");
|
|
1032
1164
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1033
|
-
var FAB_SIZE =
|
|
1165
|
+
var FAB_SIZE = import_core4.MUSHI_GEOMETRY.fabSize;
|
|
1034
1166
|
var EDGE_PADDING = 12;
|
|
1035
1167
|
function getScreenBounds() {
|
|
1036
1168
|
const { width, height } = import_react_native3.Dimensions.get("window");
|
|
@@ -1213,13 +1345,114 @@ var s2 = import_react_native3.StyleSheet.create({
|
|
|
1213
1345
|
}
|
|
1214
1346
|
});
|
|
1215
1347
|
|
|
1348
|
+
// src/components/MushiBanner.tsx
|
|
1349
|
+
var import_react3 = require("react");
|
|
1350
|
+
var import_react_native4 = require("react-native");
|
|
1351
|
+
var import_core5 = require("@mushi-mushi/core");
|
|
1352
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1353
|
+
var MUSHI_BANNER_DEFAULT_HEIGHT = import_core5.MUSHI_GEOMETRY.bannerHeight;
|
|
1354
|
+
var MushiBanner = ({
|
|
1355
|
+
onPress,
|
|
1356
|
+
onDismiss,
|
|
1357
|
+
message = import_core5.MUSHI_COPY.bannerMessage,
|
|
1358
|
+
label = import_core5.MUSHI_COPY.bannerLabel,
|
|
1359
|
+
onLayoutHeight
|
|
1360
|
+
}) => {
|
|
1361
|
+
const handleLayout = (0, import_react3.useCallback)(
|
|
1362
|
+
(e) => {
|
|
1363
|
+
onLayoutHeight?.(e.nativeEvent.layout.height);
|
|
1364
|
+
},
|
|
1365
|
+
[onLayoutHeight]
|
|
1366
|
+
);
|
|
1367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1368
|
+
import_react_native4.View,
|
|
1369
|
+
{
|
|
1370
|
+
style: s3.wrap,
|
|
1371
|
+
onLayout: handleLayout,
|
|
1372
|
+
accessibilityRole: "header",
|
|
1373
|
+
accessibilityLabel: "Mushi feedback banner",
|
|
1374
|
+
children: [
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.TouchableOpacity, { style: s3.main, onPress, activeOpacity: 0.85, children: [
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: s3.eyebrow, children: label.toUpperCase() }),
|
|
1377
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: s3.message, numberOfLines: 2, children: message }),
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: s3.cta, children: import_core5.MUSHI_COPY.bugCta })
|
|
1379
|
+
] }),
|
|
1380
|
+
onDismiss ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1381
|
+
import_react_native4.TouchableOpacity,
|
|
1382
|
+
{
|
|
1383
|
+
style: s3.dismiss,
|
|
1384
|
+
onPress: onDismiss,
|
|
1385
|
+
accessibilityRole: "button",
|
|
1386
|
+
accessibilityLabel: "Dismiss banner",
|
|
1387
|
+
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
1388
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: s3.dismissText, children: "\xD7" })
|
|
1389
|
+
}
|
|
1390
|
+
) : null
|
|
1391
|
+
]
|
|
1392
|
+
}
|
|
1393
|
+
);
|
|
1394
|
+
};
|
|
1395
|
+
var s3 = import_react_native4.StyleSheet.create({
|
|
1396
|
+
wrap: {
|
|
1397
|
+
position: "absolute",
|
|
1398
|
+
left: 0,
|
|
1399
|
+
right: 0,
|
|
1400
|
+
bottom: 0,
|
|
1401
|
+
minHeight: import_core5.MUSHI_GEOMETRY.bannerHeight,
|
|
1402
|
+
flexDirection: "row",
|
|
1403
|
+
alignItems: "stretch",
|
|
1404
|
+
backgroundColor: import_core5.MUSHI_BANNER_NEON.bg,
|
|
1405
|
+
borderTopWidth: 1,
|
|
1406
|
+
borderTopColor: import_core5.MUSHI_BANNER_NEON.border,
|
|
1407
|
+
zIndex: 99998,
|
|
1408
|
+
elevation: 8,
|
|
1409
|
+
paddingBottom: import_react_native4.Platform.OS === "ios" ? 0 : 0
|
|
1410
|
+
},
|
|
1411
|
+
main: {
|
|
1412
|
+
flex: 1,
|
|
1413
|
+
flexDirection: "row",
|
|
1414
|
+
alignItems: "center",
|
|
1415
|
+
gap: 8,
|
|
1416
|
+
paddingHorizontal: 12,
|
|
1417
|
+
paddingVertical: 8
|
|
1418
|
+
},
|
|
1419
|
+
eyebrow: {
|
|
1420
|
+
fontSize: 10,
|
|
1421
|
+
fontWeight: "700",
|
|
1422
|
+
letterSpacing: 1.2,
|
|
1423
|
+
color: import_core5.MUSHI_BANNER_NEON.fg
|
|
1424
|
+
},
|
|
1425
|
+
message: {
|
|
1426
|
+
flex: 1,
|
|
1427
|
+
fontSize: 12,
|
|
1428
|
+
fontWeight: "500",
|
|
1429
|
+
color: import_core5.MUSHI_BANNER_NEON.fg
|
|
1430
|
+
},
|
|
1431
|
+
cta: {
|
|
1432
|
+
fontSize: 12,
|
|
1433
|
+
fontWeight: "700",
|
|
1434
|
+
color: import_core5.MUSHI_BANNER_NEON.fg,
|
|
1435
|
+
textDecorationLine: "underline"
|
|
1436
|
+
},
|
|
1437
|
+
dismiss: {
|
|
1438
|
+
justifyContent: "center",
|
|
1439
|
+
paddingHorizontal: 12
|
|
1440
|
+
},
|
|
1441
|
+
dismissText: {
|
|
1442
|
+
fontSize: 20,
|
|
1443
|
+
lineHeight: 22,
|
|
1444
|
+
color: import_core5.MUSHI_BANNER_NEON.fg,
|
|
1445
|
+
opacity: 0.7
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
|
|
1216
1449
|
// src/version.ts
|
|
1217
1450
|
var MUSHI_SDK_PACKAGE = "@mushi-mushi/react-native";
|
|
1218
|
-
var MUSHI_SDK_VERSION = "0.
|
|
1451
|
+
var MUSHI_SDK_VERSION = "0.20.0" ? "0.20.0" : "0.17.0";
|
|
1219
1452
|
|
|
1220
1453
|
// src/provider.tsx
|
|
1221
|
-
var
|
|
1222
|
-
var MushiContext = (0,
|
|
1454
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1455
|
+
var MushiContext = (0, import_react4.createContext)(null);
|
|
1223
1456
|
var DEFAULT_SCREENSHOT_HINT = "Check the preview \u2014 remove it if any private info (balances, personal details) is visible.";
|
|
1224
1457
|
function resolveScreenshotHint(v) {
|
|
1225
1458
|
if (v === false) return null;
|
|
@@ -1258,26 +1491,28 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1258
1491
|
);
|
|
1259
1492
|
}
|
|
1260
1493
|
}
|
|
1261
|
-
const consoleRef = (0,
|
|
1262
|
-
const networkRef = (0,
|
|
1263
|
-
const queueRef = (0,
|
|
1264
|
-
const apiClientRef = (0,
|
|
1265
|
-
const sessionIdRef = (0,
|
|
1266
|
-
const breadcrumbsRef = (0,
|
|
1267
|
-
(0,
|
|
1494
|
+
const consoleRef = (0, import_react4.useRef)(null);
|
|
1495
|
+
const networkRef = (0, import_react4.useRef)(null);
|
|
1496
|
+
const queueRef = (0, import_react4.useRef)(null);
|
|
1497
|
+
const apiClientRef = (0, import_react4.useRef)(null);
|
|
1498
|
+
const sessionIdRef = (0, import_react4.useRef)(`sess_${(0, import_core6.newUuid)()}`);
|
|
1499
|
+
const breadcrumbsRef = (0, import_react4.useRef)(
|
|
1500
|
+
(0, import_core6.createBreadcrumbBuffer)({ max: config.capture?.maxBreadcrumbs ?? 50 })
|
|
1268
1501
|
);
|
|
1269
|
-
const [sheetVisible, setSheetVisible] = (0,
|
|
1270
|
-
const [
|
|
1271
|
-
const
|
|
1502
|
+
const [sheetVisible, setSheetVisible] = (0, import_react4.useState)(false);
|
|
1503
|
+
const [sheetPreferredTab, setSheetPreferredTab] = (0, import_react4.useState)("report");
|
|
1504
|
+
const [bannerDismissed, setBannerDismissed] = (0, import_react4.useState)(false);
|
|
1505
|
+
const [sheetScreenshot, setSheetScreenshot] = (0, import_react4.useState)(null);
|
|
1506
|
+
const reporterTokenRef = (0, import_react4.useRef)(`rn-${config.projectId}-anon`);
|
|
1272
1507
|
let resolveReporterTokenReady = () => {
|
|
1273
1508
|
};
|
|
1274
|
-
const reporterTokenReadyRef = (0,
|
|
1509
|
+
const reporterTokenReadyRef = (0, import_react4.useRef)(
|
|
1275
1510
|
new Promise((resolve) => {
|
|
1276
1511
|
resolveReporterTokenReady = resolve;
|
|
1277
1512
|
})
|
|
1278
1513
|
);
|
|
1279
|
-
const userTokenRef = (0,
|
|
1280
|
-
const pageContextRef = (0,
|
|
1514
|
+
const userTokenRef = (0, import_react4.useRef)(null);
|
|
1515
|
+
const pageContextRef = (0, import_react4.useRef)(null);
|
|
1281
1516
|
const rawEndpoint = config.apiEndpoint ?? config.endpoint;
|
|
1282
1517
|
if (rawEndpoint !== void 0 && rawEndpoint.trim() === "") {
|
|
1283
1518
|
throw new Error(
|
|
@@ -1287,15 +1522,15 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1287
1522
|
if (config.endpoint && !config.apiEndpoint && __DEV__) {
|
|
1288
1523
|
console.warn("[MushiProvider] `endpoint` is deprecated \u2014 use `apiEndpoint` instead.");
|
|
1289
1524
|
}
|
|
1290
|
-
const apiEndpoint = rawEndpoint ??
|
|
1291
|
-
(0,
|
|
1525
|
+
const apiEndpoint = rawEndpoint ?? import_core6.DEFAULT_API_ENDPOINT;
|
|
1526
|
+
(0, import_react4.useEffect)(() => {
|
|
1292
1527
|
if (config.capture?.console !== false) {
|
|
1293
1528
|
consoleRef.current = setupConsoleCapture(config.capture?.maxConsoleEntries);
|
|
1294
1529
|
}
|
|
1295
1530
|
if (config.capture?.network !== false) {
|
|
1296
1531
|
networkRef.current = setupNetworkCapture(config.capture?.maxNetworkEntries, apiEndpoint);
|
|
1297
1532
|
}
|
|
1298
|
-
apiClientRef.current = (0,
|
|
1533
|
+
apiClientRef.current = (0, import_core6.createApiClient)({
|
|
1299
1534
|
projectId: config.projectId,
|
|
1300
1535
|
apiKey: config.apiKey,
|
|
1301
1536
|
apiEndpoint,
|
|
@@ -1332,14 +1567,14 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1332
1567
|
if (existing && existing.startsWith("mushi_")) {
|
|
1333
1568
|
reporterTokenRef.current = existing;
|
|
1334
1569
|
} else {
|
|
1335
|
-
const fresh = `mushi_${(0,
|
|
1570
|
+
const fresh = `mushi_${(0, import_core6.newUuid)()}`;
|
|
1336
1571
|
reporterTokenRef.current = fresh;
|
|
1337
1572
|
await saveReporterToken(fresh, secureStorage);
|
|
1338
1573
|
}
|
|
1339
1574
|
resolveReporterTokenReady();
|
|
1340
1575
|
} catch {
|
|
1341
1576
|
if (reporterTokenRef.current === `rn-${config.projectId}-anon`) {
|
|
1342
|
-
reporterTokenRef.current = `mushi_${(0,
|
|
1577
|
+
reporterTokenRef.current = `mushi_${(0, import_core6.newUuid)()}`;
|
|
1343
1578
|
}
|
|
1344
1579
|
resolveReporterTokenReady();
|
|
1345
1580
|
}
|
|
@@ -1350,7 +1585,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1350
1585
|
networkRef.current?.restore();
|
|
1351
1586
|
};
|
|
1352
1587
|
}, []);
|
|
1353
|
-
(0,
|
|
1588
|
+
(0, import_react4.useEffect)(() => {
|
|
1354
1589
|
let unsubscribe;
|
|
1355
1590
|
try {
|
|
1356
1591
|
const NetInfo = require("@react-native-community/netinfo").default;
|
|
@@ -1364,7 +1599,8 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1364
1599
|
}
|
|
1365
1600
|
return () => unsubscribe?.();
|
|
1366
1601
|
}, []);
|
|
1367
|
-
const open = (0,
|
|
1602
|
+
const open = (0, import_react4.useCallback)(() => {
|
|
1603
|
+
setSheetPreferredTab("report");
|
|
1368
1604
|
breadcrumbsRef.current.add({
|
|
1369
1605
|
category: "lifecycle",
|
|
1370
1606
|
level: "info",
|
|
@@ -1394,9 +1630,15 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1394
1630
|
setSheetVisible(true);
|
|
1395
1631
|
});
|
|
1396
1632
|
}, [config.capture?.screenshot]);
|
|
1397
|
-
const
|
|
1398
|
-
|
|
1399
|
-
|
|
1633
|
+
const openAssistant = (0, import_react4.useCallback)(() => {
|
|
1634
|
+
if (!config.assistant?.enabled) return;
|
|
1635
|
+
setSheetPreferredTab("assistant");
|
|
1636
|
+
setSheetScreenshot(null);
|
|
1637
|
+
setSheetVisible(true);
|
|
1638
|
+
}, [config.assistant?.enabled]);
|
|
1639
|
+
const close = (0, import_react4.useCallback)(() => setSheetVisible(false), []);
|
|
1640
|
+
const attachTo = (0, import_react4.useCallback)(() => ({ onPress: open }), [open]);
|
|
1641
|
+
(0, import_react4.useEffect)(() => {
|
|
1400
1642
|
const trigger2 = config.widget?.trigger ?? "button";
|
|
1401
1643
|
if (trigger2 !== "shake" && trigger2 !== "both") return;
|
|
1402
1644
|
let disposed = false;
|
|
@@ -1424,8 +1666,9 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1424
1666
|
cleanup?.();
|
|
1425
1667
|
};
|
|
1426
1668
|
}, [config.widget?.trigger, config.widget?.shakeThreshold, open]);
|
|
1427
|
-
const submitReport = (0,
|
|
1669
|
+
const submitReport = (0, import_react4.useCallback)(
|
|
1428
1670
|
async (data) => {
|
|
1671
|
+
await reporterTokenReadyRef.current;
|
|
1429
1672
|
const deviceInfo = getDeviceInfo();
|
|
1430
1673
|
breadcrumbsRef.current.add({
|
|
1431
1674
|
category: "lifecycle",
|
|
@@ -1451,7 +1694,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1451
1694
|
const merged = Object.keys(metadataRef.current).length > 0 ? { ...contextMeta, ...metadataRef.current } : Object.keys(contextMeta).length > 0 ? contextMeta : void 0;
|
|
1452
1695
|
const breadcrumbs = breadcrumbsRef.current.getAll().map((c) => ({
|
|
1453
1696
|
...c,
|
|
1454
|
-
message: (0,
|
|
1697
|
+
message: (0, import_core6.scrubPii)(c.message)
|
|
1455
1698
|
}));
|
|
1456
1699
|
const timeline = breadcrumbs.map((c) => ({
|
|
1457
1700
|
ts: c.timestamp,
|
|
@@ -1460,10 +1703,10 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1460
1703
|
}));
|
|
1461
1704
|
const fingerprintHash = getDeviceFingerprintHash(deviceInfo);
|
|
1462
1705
|
const report = {
|
|
1463
|
-
id: (0,
|
|
1706
|
+
id: (0, import_core6.newUuid)(),
|
|
1464
1707
|
projectId: config.projectId,
|
|
1465
1708
|
category: data.category,
|
|
1466
|
-
description: (0,
|
|
1709
|
+
description: (0, import_core6.scrubPii)(data.description),
|
|
1467
1710
|
environment: {
|
|
1468
1711
|
userAgent: deviceInfo.systemName ?? "ReactNative",
|
|
1469
1712
|
platform: deviceInfo.platform ?? "mobile",
|
|
@@ -1476,7 +1719,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1476
1719
|
},
|
|
1477
1720
|
consoleLogs: (consoleRef.current?.getEntries() ?? []).map((entry) => ({
|
|
1478
1721
|
...entry,
|
|
1479
|
-
message: (0,
|
|
1722
|
+
message: (0, import_core6.scrubPii)(entry.message)
|
|
1480
1723
|
})),
|
|
1481
1724
|
networkLogs: networkRef.current?.getEntries().map((entry) => ({
|
|
1482
1725
|
...entry,
|
|
@@ -1500,7 +1743,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1500
1743
|
if (!result.ok) {
|
|
1501
1744
|
const isCredentialError = result.error?.code === "HTTP_401" || result.error?.code === "HTTP_403" || result.error?.code?.includes("UNAUTHORIZED") || result.error?.code?.includes("FORBIDDEN");
|
|
1502
1745
|
if (isCredentialError) {
|
|
1503
|
-
const where = apiEndpoint.replace(/\/$/, "") ===
|
|
1746
|
+
const where = apiEndpoint.replace(/\/$/, "") === import_core6.DEFAULT_API_ENDPOINT ? "Get the correct values at: https://kensaur.us/mushi-mushi/admin/projects" : "Get the correct values from your Mushi console's Projects page.";
|
|
1504
1747
|
console.error(
|
|
1505
1748
|
'[Mushi] Credentials rejected. Check your projectId and apiKey (must have "report:write" scope). ' + where
|
|
1506
1749
|
);
|
|
@@ -1514,12 +1757,12 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1514
1757
|
},
|
|
1515
1758
|
[config.projectId, config.callbacks, apiEndpoint]
|
|
1516
1759
|
);
|
|
1517
|
-
const userRef = (0,
|
|
1518
|
-
const metadataRef = (0,
|
|
1519
|
-
const screenRef = (0,
|
|
1520
|
-
const activityQueueRef = (0,
|
|
1521
|
-
const rewardsFlushRef = (0,
|
|
1522
|
-
(0,
|
|
1760
|
+
const userRef = (0, import_react4.useRef)(null);
|
|
1761
|
+
const metadataRef = (0, import_react4.useRef)({});
|
|
1762
|
+
const screenRef = (0, import_react4.useRef)(null);
|
|
1763
|
+
const activityQueueRef = (0, import_react4.useRef)([]);
|
|
1764
|
+
const rewardsFlushRef = (0, import_react4.useRef)(null);
|
|
1765
|
+
(0, import_react4.useEffect)(() => {
|
|
1523
1766
|
const rewards = config.rewards;
|
|
1524
1767
|
if (!rewards?.enabled || !rewards.trackActivity) return;
|
|
1525
1768
|
const flushMs = Math.max(3e4, rewards.flushIntervalMs ?? 3e5);
|
|
@@ -1539,7 +1782,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1539
1782
|
if (rewardsFlushRef.current) clearInterval(rewardsFlushRef.current);
|
|
1540
1783
|
};
|
|
1541
1784
|
}, [config.rewards?.enabled, config.rewards?.trackActivity, config.rewards?.flushIntervalMs]);
|
|
1542
|
-
const instance = (0,
|
|
1785
|
+
const instance = (0, import_react4.useMemo)(
|
|
1543
1786
|
() => ({
|
|
1544
1787
|
open,
|
|
1545
1788
|
close,
|
|
@@ -1568,7 +1811,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1568
1811
|
identifyWithToken(token) {
|
|
1569
1812
|
userTokenRef.current = token && typeof token === "string" ? token : null;
|
|
1570
1813
|
if (userTokenRef.current) {
|
|
1571
|
-
const claims = (0,
|
|
1814
|
+
const claims = (0, import_core6.parseIdentityToken)(userTokenRef.current);
|
|
1572
1815
|
if (claims?.sub) {
|
|
1573
1816
|
userRef.current = {
|
|
1574
1817
|
id: claims.sub,
|
|
@@ -1669,15 +1912,36 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1669
1912
|
confirmedBugs: 0,
|
|
1670
1913
|
totalReports: 0
|
|
1671
1914
|
};
|
|
1915
|
+
},
|
|
1916
|
+
openAssistant,
|
|
1917
|
+
async askAssistant(message, threadId) {
|
|
1918
|
+
const client = apiClientRef.current;
|
|
1919
|
+
if (!client || !config.assistant?.enabled) return null;
|
|
1920
|
+
const res = await client.askAssistant({
|
|
1921
|
+
message,
|
|
1922
|
+
threadId: threadId ?? null,
|
|
1923
|
+
context: pageContextRef.current
|
|
1924
|
+
});
|
|
1925
|
+
return res.ok ? res.data : null;
|
|
1672
1926
|
}
|
|
1673
1927
|
}),
|
|
1674
|
-
[open, close, attachTo, submitReport, config.rewards?.enabled]
|
|
1928
|
+
[open, close, attachTo, submitReport, openAssistant, config.rewards?.enabled, config.assistant?.enabled]
|
|
1675
1929
|
);
|
|
1676
1930
|
const trigger = config.widget?.trigger ?? "button";
|
|
1677
|
-
const
|
|
1678
|
-
|
|
1931
|
+
const showBanner = trigger === "banner" && !bannerDismissed;
|
|
1932
|
+
const showFab = !showBanner && (trigger === "button" || trigger === "both" || trigger === "auto" || trigger === "edge-tab");
|
|
1933
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MushiContext.Provider, { value: instance, children: [
|
|
1679
1934
|
children,
|
|
1680
|
-
|
|
1935
|
+
showBanner ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1936
|
+
MushiBanner,
|
|
1937
|
+
{
|
|
1938
|
+
onPress: open,
|
|
1939
|
+
onDismiss: () => setBannerDismissed(true),
|
|
1940
|
+
message: config.widget?.banner?.message,
|
|
1941
|
+
label: config.widget?.banner?.label
|
|
1942
|
+
}
|
|
1943
|
+
) : null,
|
|
1944
|
+
showFab && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1681
1945
|
MushiFloatingButton,
|
|
1682
1946
|
{
|
|
1683
1947
|
onPress: open,
|
|
@@ -1685,20 +1949,26 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1685
1949
|
inset: config.widget?.inset
|
|
1686
1950
|
}
|
|
1687
1951
|
),
|
|
1688
|
-
/* @__PURE__ */ (0,
|
|
1952
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1689
1953
|
MushiBottomSheet,
|
|
1690
1954
|
{
|
|
1691
1955
|
visible: sheetVisible,
|
|
1692
1956
|
onClose: close,
|
|
1957
|
+
preferredTab: sheetPreferredTab,
|
|
1693
1958
|
screenshotDataUrl: sheetScreenshot ?? void 0,
|
|
1694
1959
|
onClearScreenshot: () => setSheetScreenshot(null),
|
|
1695
|
-
screenshotSensitiveHint: resolveScreenshotHint(config.widget?.screenshotSensitiveHint)
|
|
1960
|
+
screenshotSensitiveHint: resolveScreenshotHint(config.widget?.screenshotSensitiveHint),
|
|
1961
|
+
assistantEnabled: Boolean(config.assistant?.enabled),
|
|
1962
|
+
assistantLabel: config.assistant?.label,
|
|
1963
|
+
assistantGreeting: config.assistant?.greeting,
|
|
1964
|
+
assistantSuggestions: config.assistant?.suggestions,
|
|
1965
|
+
inboxPollIntervalMs: config.widget?.inboxPollIntervalMs ?? 0
|
|
1696
1966
|
}
|
|
1697
1967
|
)
|
|
1698
1968
|
] });
|
|
1699
1969
|
}
|
|
1700
1970
|
function useMushiContext() {
|
|
1701
|
-
return (0,
|
|
1971
|
+
return (0, import_react4.useContext)(MushiContext);
|
|
1702
1972
|
}
|
|
1703
1973
|
|
|
1704
1974
|
// src/hooks/useMushi.ts
|
|
@@ -1707,10 +1977,10 @@ function useMushi() {
|
|
|
1707
1977
|
}
|
|
1708
1978
|
|
|
1709
1979
|
// src/hooks/useMushiReport.ts
|
|
1710
|
-
var
|
|
1980
|
+
var import_react5 = require("react");
|
|
1711
1981
|
function useMushiReport() {
|
|
1712
1982
|
const mushi = useMushiContext();
|
|
1713
|
-
const submitReport = (0,
|
|
1983
|
+
const submitReport = (0, import_react5.useCallback)(
|
|
1714
1984
|
async (data) => {
|
|
1715
1985
|
if (!mushi) throw new Error("MushiProvider not found");
|
|
1716
1986
|
await mushi.submitReport(data);
|
|
@@ -1721,22 +1991,22 @@ function useMushiReport() {
|
|
|
1721
1991
|
}
|
|
1722
1992
|
|
|
1723
1993
|
// src/hooks/useMushiWidget.ts
|
|
1724
|
-
var
|
|
1994
|
+
var import_react6 = require("react");
|
|
1725
1995
|
function useMushiWidget() {
|
|
1726
1996
|
const mushi = useMushiContext();
|
|
1727
1997
|
return {
|
|
1728
|
-
open: (0,
|
|
1729
|
-
close: (0,
|
|
1998
|
+
open: (0, import_react6.useCallback)(() => mushi?.open(), [mushi]),
|
|
1999
|
+
close: (0, import_react6.useCallback)(() => mushi?.close(), [mushi])
|
|
1730
2000
|
};
|
|
1731
2001
|
}
|
|
1732
2002
|
|
|
1733
2003
|
// src/components/MushiTrigger.tsx
|
|
1734
|
-
var
|
|
2004
|
+
var import_react7 = require("react");
|
|
1735
2005
|
function MushiTrigger({ children }) {
|
|
1736
2006
|
const mushi = useMushiContext();
|
|
1737
|
-
if (!(0,
|
|
2007
|
+
if (!(0, import_react7.isValidElement)(children)) return children;
|
|
1738
2008
|
const originalOnPress = children.props.onPress;
|
|
1739
|
-
return (0,
|
|
2009
|
+
return (0, import_react7.cloneElement)(children, {
|
|
1740
2010
|
onPress: () => {
|
|
1741
2011
|
originalOnPress?.();
|
|
1742
2012
|
mushi?.open();
|
|
@@ -1745,10 +2015,10 @@ function MushiTrigger({ children }) {
|
|
|
1745
2015
|
}
|
|
1746
2016
|
|
|
1747
2017
|
// src/capture/navigation-capture.ts
|
|
1748
|
-
var
|
|
2018
|
+
var import_react8 = require("react");
|
|
1749
2019
|
function useNavigationCapture(navigationRef) {
|
|
1750
|
-
const historyRef = (0,
|
|
1751
|
-
(0,
|
|
2020
|
+
const historyRef = (0, import_react8.useRef)([]);
|
|
2021
|
+
(0, import_react8.useEffect)(() => {
|
|
1752
2022
|
if (!navigationRef?.addListener || !navigationRef?.getCurrentRoute) return;
|
|
1753
2023
|
const unsubscribe = navigationRef.addListener("state", () => {
|
|
1754
2024
|
const route = navigationRef.getCurrentRoute?.();
|
|
@@ -1764,6 +2034,8 @@ function useNavigationCapture(navigationRef) {
|
|
|
1764
2034
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1765
2035
|
0 && (module.exports = {
|
|
1766
2036
|
AsyncStorageQueue,
|
|
2037
|
+
MUSHI_BANNER_DEFAULT_HEIGHT,
|
|
2038
|
+
MushiBanner,
|
|
1767
2039
|
MushiBottomSheet,
|
|
1768
2040
|
MushiFloatingButton,
|
|
1769
2041
|
MushiProvider,
|