@mushi-mushi/react-native 0.22.0 → 0.23.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/README.md +18 -1
- package/dist/index.cjs +615 -226
- package/dist/index.d.cts +57 -2
- package/dist/index.d.ts +57 -2
- package/dist/index.js +563 -177
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -50,7 +50,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
50
50
|
// src/provider.tsx
|
|
51
51
|
var import_react4 = require("react");
|
|
52
52
|
var import_react_native5 = require("react-native");
|
|
53
|
-
var
|
|
53
|
+
var import_core9 = require("@mushi-mushi/core");
|
|
54
54
|
|
|
55
55
|
// src/capture/console-capture.ts
|
|
56
56
|
var import_core = require("@mushi-mushi/core");
|
|
@@ -478,32 +478,99 @@ function sleep(ms) {
|
|
|
478
478
|
// src/components/MushiBottomSheet.tsx
|
|
479
479
|
var import_react = require("react");
|
|
480
480
|
var import_react_native2 = require("react-native");
|
|
481
|
-
var
|
|
481
|
+
var import_core4 = require("@mushi-mushi/core");
|
|
482
|
+
var import_reporter_ui = require("@mushi-mushi/core/reporter-ui");
|
|
482
483
|
var import_i18n = require("@mushi-mushi/web/i18n");
|
|
483
484
|
|
|
484
|
-
// src/
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
485
|
+
// src/theme.ts
|
|
486
|
+
var import_core3 = require("@mushi-mushi/core");
|
|
487
|
+
function hexToRgb(hex) {
|
|
488
|
+
const m = /^#([0-9a-f]{3}|[0-9a-f]{6})([0-9a-f]{2})?$/i.exec(hex.trim());
|
|
489
|
+
if (!m) return null;
|
|
490
|
+
const h = m[1].length === 3 ? m[1].split("").map((c) => c + c).join("") : m[1];
|
|
491
|
+
return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16));
|
|
492
|
+
}
|
|
493
|
+
function luminance([r, g, b]) {
|
|
494
|
+
const lin = (c) => {
|
|
495
|
+
const s4 = c / 255;
|
|
496
|
+
return s4 <= 0.03928 ? s4 / 12.92 : ((s4 + 0.055) / 1.055) ** 2.4;
|
|
497
|
+
};
|
|
498
|
+
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
|
|
499
|
+
}
|
|
500
|
+
function contrastingText(bg, fallback) {
|
|
501
|
+
const rgb = hexToRgb(bg);
|
|
502
|
+
if (!rgb) return fallback;
|
|
503
|
+
const l = luminance(rgb);
|
|
504
|
+
return 1.05 / (l + 0.05) >= (l + 0.05) / 0.05 ? "#FFFFFF" : "#000000";
|
|
505
|
+
}
|
|
506
|
+
function resolveRNTheme(dark, override = {}) {
|
|
507
|
+
const pal = (0, import_core3.mushiPalette)(dark ? "dark" : "light");
|
|
508
|
+
const base = {
|
|
509
|
+
bg: dark ? pal.paper : pal.paperRaised,
|
|
510
|
+
fg: pal.ink,
|
|
511
|
+
muted: pal.inkMuted,
|
|
512
|
+
surface: dark ? pal.paperRaised : pal.paper,
|
|
513
|
+
border: pal.ruleStrong,
|
|
514
|
+
accent: pal.ink,
|
|
515
|
+
accentFg: dark ? pal.paper : pal.paperRaised,
|
|
516
|
+
success: pal.ok,
|
|
517
|
+
error: pal.danger,
|
|
518
|
+
fontFamily: void 0,
|
|
519
|
+
radius: import_core3.MUSHI_RADIUS.card
|
|
520
|
+
};
|
|
521
|
+
const defined = Object.fromEntries(
|
|
522
|
+
Object.entries(override).filter(([, v]) => v !== void 0 && v !== null && v !== "")
|
|
523
|
+
);
|
|
524
|
+
const merged = { ...base, ...defined };
|
|
525
|
+
if (defined.accent && !defined.accentFg) merged.accentFg = contrastingText(defined.accent, base.accentFg);
|
|
526
|
+
return {
|
|
527
|
+
...merged,
|
|
528
|
+
backdrop: dark ? "rgba(0,0,0,0.6)" : "rgba(0,0,0,0.35)",
|
|
529
|
+
disabled: dark ? import_core3.MUSHI_CONTROL_DISABLED.dark : import_core3.MUSHI_CONTROL_DISABLED.light,
|
|
530
|
+
disabledFg: pal.inkFaint
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// src/reporter-thread.ts
|
|
535
|
+
var THREAD_LOAD_TIMEOUT_MS = 12e3;
|
|
536
|
+
function settleWithin(p, ms) {
|
|
537
|
+
return new Promise((resolve) => {
|
|
538
|
+
const timer = setTimeout(() => resolve(null), ms);
|
|
539
|
+
p.then(
|
|
540
|
+
(value) => {
|
|
541
|
+
clearTimeout(timer);
|
|
542
|
+
resolve(value);
|
|
543
|
+
},
|
|
544
|
+
() => {
|
|
545
|
+
clearTimeout(timer);
|
|
546
|
+
resolve(null);
|
|
547
|
+
}
|
|
548
|
+
);
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
function loadReporterThread(load, reportId, timeoutMs = THREAD_LOAD_TIMEOUT_MS) {
|
|
552
|
+
let started;
|
|
553
|
+
try {
|
|
554
|
+
started = load(reportId);
|
|
555
|
+
} catch {
|
|
556
|
+
return Promise.resolve(null);
|
|
557
|
+
}
|
|
558
|
+
return settleWithin(started, timeoutMs);
|
|
559
|
+
}
|
|
560
|
+
async function markReporterReportRead(client, reporterToken, reportId) {
|
|
561
|
+
try {
|
|
562
|
+
const res = await client.listNotifications(reporterToken, { limit: 100 });
|
|
563
|
+
if (!res.ok) return 0;
|
|
564
|
+
const rows = res.data?.notifications ?? [];
|
|
565
|
+
const ids = rows.filter((n) => !n.read_at && n.payload?.reportId === reportId).map((n) => String(n.id));
|
|
566
|
+
let marked = 0;
|
|
567
|
+
for (const id of ids) {
|
|
568
|
+
const r = await client.markNotificationRead(id, reporterToken);
|
|
569
|
+
if (r.ok) marked++;
|
|
570
|
+
}
|
|
571
|
+
return marked;
|
|
572
|
+
} catch {
|
|
573
|
+
return 0;
|
|
507
574
|
}
|
|
508
575
|
}
|
|
509
576
|
|
|
@@ -512,6 +579,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
512
579
|
var { height: SCREEN_HEIGHT } = import_react_native2.Dimensions.get("window");
|
|
513
580
|
var SHEET_HEIGHT = SCREEN_HEIGHT * 0.55;
|
|
514
581
|
var DISMISS_THRESHOLD = 80;
|
|
582
|
+
var MIN_DESCRIPTION = 20;
|
|
515
583
|
var CATEGORY_KEYS = ["bug", "slow", "visual", "confusing", "other"];
|
|
516
584
|
var CATEGORY_EMOJI = {
|
|
517
585
|
bug: "\u{1F41B}",
|
|
@@ -520,7 +588,6 @@ var CATEGORY_EMOJI = {
|
|
|
520
588
|
confusing: "\u{1F615}",
|
|
521
589
|
other: "\u{1F4AC}"
|
|
522
590
|
};
|
|
523
|
-
var VERIFIABLE_STATUSES = /* @__PURE__ */ new Set(["fixed", "resolved", "verified"]);
|
|
524
591
|
var MushiBottomSheet = ({
|
|
525
592
|
visible,
|
|
526
593
|
onClose,
|
|
@@ -529,13 +596,18 @@ var MushiBottomSheet = ({
|
|
|
529
596
|
onClearScreenshot,
|
|
530
597
|
screenshotSensitiveHint,
|
|
531
598
|
assistantEnabled = false,
|
|
532
|
-
assistantLabel =
|
|
599
|
+
assistantLabel = import_core4.MUSHI_COPY.assistantTab,
|
|
533
600
|
assistantGreeting,
|
|
534
601
|
assistantSuggestions = [],
|
|
535
|
-
inboxPollIntervalMs = 0
|
|
602
|
+
inboxPollIntervalMs = 0,
|
|
603
|
+
theme
|
|
536
604
|
}) => {
|
|
537
605
|
const mushi = useMushiContext();
|
|
538
606
|
const t = (0, import_i18n.getLocale)();
|
|
607
|
+
const locale = (0, import_reporter_ui.resolveReporterLocale)(
|
|
608
|
+
typeof navigator !== "undefined" ? navigator.language : void 0
|
|
609
|
+
);
|
|
610
|
+
const rc = (0, import_reporter_ui.reporterCopy)(locale);
|
|
539
611
|
const greeting = assistantGreeting ?? t.assistant.defaultGreeting;
|
|
540
612
|
const scheme = (0, import_react_native2.useColorScheme)();
|
|
541
613
|
const dark = scheme === "dark";
|
|
@@ -547,26 +619,37 @@ var MushiBottomSheet = ({
|
|
|
547
619
|
const [submitError, setSubmitError] = (0, import_react.useState)(null);
|
|
548
620
|
const [sheetTab, setSheetTab] = (0, import_react.useState)("report");
|
|
549
621
|
const [inboxReports, setInboxReports] = (0, import_react.useState)([]);
|
|
622
|
+
const [inboxLoaded, setInboxLoaded] = (0, import_react.useState)(false);
|
|
550
623
|
const [inboxLoading, setInboxLoading] = (0, import_react.useState)(false);
|
|
551
624
|
const [selectedReportId, setSelectedReportId] = (0, import_react.useState)(null);
|
|
625
|
+
const selectedRef = (0, import_react.useRef)(null);
|
|
552
626
|
const [threadComments, setThreadComments] = (0, import_react.useState)([]);
|
|
627
|
+
const [threadStatus, setThreadStatus] = (0, import_react.useState)("idle");
|
|
553
628
|
const [replyText, setReplyText] = (0, import_react.useState)("");
|
|
629
|
+
const [replyState, setReplyState] = (0, import_react.useState)("idle");
|
|
630
|
+
const [feedbackSending, setFeedbackSending] = (0, import_react.useState)(false);
|
|
631
|
+
const [feedbackError, setFeedbackError] = (0, import_react.useState)(false);
|
|
554
632
|
const [assistantInput, setAssistantInput] = (0, import_react.useState)("");
|
|
555
633
|
const [assistantThreadId, setAssistantThreadId] = (0, import_react.useState)(null);
|
|
556
634
|
const [assistantSending, setAssistantSending] = (0, import_react.useState)(false);
|
|
557
635
|
const [assistantError, setAssistantError] = (0, import_react.useState)(null);
|
|
558
636
|
const [assistantTurns, setAssistantTurns] = (0, import_react.useState)([]);
|
|
559
637
|
const [screenshotAttached, setScreenshotAttached] = (0, import_react.useState)(true);
|
|
560
|
-
const loadInbox = (0, import_react.useCallback)(
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
638
|
+
const loadInbox = (0, import_react.useCallback)(
|
|
639
|
+
async (opts = {}) => {
|
|
640
|
+
if (!mushi?.listMyReports) return;
|
|
641
|
+
if (!opts.silent) setInboxLoading(true);
|
|
642
|
+
try {
|
|
643
|
+
const rows = await mushi.listMyReports();
|
|
644
|
+
setInboxReports(rows.filter((r) => !(0, import_reporter_ui.reporterStatus)(r, locale).hidden));
|
|
645
|
+
setInboxLoaded(true);
|
|
646
|
+
} catch {
|
|
647
|
+
} finally {
|
|
648
|
+
if (!opts.silent) setInboxLoading(false);
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
[mushi, locale]
|
|
652
|
+
);
|
|
570
653
|
(0, import_react.useEffect)(() => {
|
|
571
654
|
if (visible) {
|
|
572
655
|
setScreenshotAttached(true);
|
|
@@ -577,28 +660,87 @@ var MushiBottomSheet = ({
|
|
|
577
660
|
(0, import_react.useEffect)(() => {
|
|
578
661
|
if (!visible || sheetTab !== "inbox" || inboxPollIntervalMs <= 0) return;
|
|
579
662
|
const timer = setInterval(() => {
|
|
580
|
-
void loadInbox();
|
|
663
|
+
void loadInbox({ silent: true });
|
|
581
664
|
}, inboxPollIntervalMs);
|
|
582
665
|
return () => clearInterval(timer);
|
|
583
666
|
}, [visible, sheetTab, inboxPollIntervalMs, loadInbox]);
|
|
584
|
-
const openThread = (0, import_react.useCallback)(
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
667
|
+
const openThread = (0, import_react.useCallback)(
|
|
668
|
+
async (reportId, opts = {}) => {
|
|
669
|
+
selectedRef.current = reportId;
|
|
670
|
+
setSelectedReportId(reportId);
|
|
671
|
+
if (!opts.silent) {
|
|
672
|
+
setThreadComments([]);
|
|
673
|
+
setThreadStatus("loading");
|
|
674
|
+
setReplyState("idle");
|
|
675
|
+
setFeedbackError(false);
|
|
676
|
+
}
|
|
677
|
+
const load = mushi?.loadMyThread ?? mushi?.listMyComments;
|
|
678
|
+
const comments = load ? await loadReporterThread(load, reportId) : null;
|
|
679
|
+
if (selectedRef.current !== reportId) return;
|
|
680
|
+
if (comments === null) {
|
|
681
|
+
setThreadStatus((prev) => opts.silent && prev === "ready" ? "ready" : "error");
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
setThreadComments(comments);
|
|
685
|
+
setThreadStatus("ready");
|
|
686
|
+
if (!opts.silent && mushi?.markReportRead) {
|
|
687
|
+
mushi.markReportRead(reportId).then((marked) => {
|
|
688
|
+
if (marked > 0) {
|
|
689
|
+
setInboxReports((rows) => rows.map((r) => r.id === reportId ? { ...r, unread_count: 0 } : r));
|
|
690
|
+
}
|
|
691
|
+
}).catch(() => void 0);
|
|
692
|
+
}
|
|
693
|
+
},
|
|
694
|
+
[mushi]
|
|
695
|
+
);
|
|
696
|
+
const closeThread = (0, import_react.useCallback)(() => {
|
|
697
|
+
selectedRef.current = null;
|
|
698
|
+
setSelectedReportId(null);
|
|
699
|
+
setThreadStatus("idle");
|
|
700
|
+
}, []);
|
|
590
701
|
const sendReply = (0, import_react.useCallback)(async () => {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
702
|
+
const body = replyText.trim();
|
|
703
|
+
const reportId = selectedReportId;
|
|
704
|
+
if (!mushi?.replyToReport || !reportId || !body || replyState === "sending") return;
|
|
705
|
+
setReplyState("sending");
|
|
706
|
+
try {
|
|
707
|
+
const comment = await settleWithin(mushi.replyToReport(reportId, body), THREAD_LOAD_TIMEOUT_MS);
|
|
708
|
+
if (!comment) {
|
|
709
|
+
setReplyState("failed");
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
setReplyText("");
|
|
713
|
+
setReplyState("idle");
|
|
714
|
+
if (selectedRef.current === reportId) {
|
|
715
|
+
setThreadComments((prev) => [...prev, comment]);
|
|
716
|
+
void openThread(reportId, { silent: true });
|
|
717
|
+
}
|
|
718
|
+
} catch {
|
|
719
|
+
setReplyState("failed");
|
|
720
|
+
}
|
|
721
|
+
}, [mushi, selectedReportId, replyText, replyState, openThread]);
|
|
722
|
+
const submitFeedback = (0, import_react.useCallback)(
|
|
723
|
+
async (signal) => {
|
|
724
|
+
const reportId = selectedReportId;
|
|
725
|
+
if (!mushi?.submitFeedbackSignal || !reportId || feedbackSending) return;
|
|
726
|
+
setFeedbackSending(true);
|
|
727
|
+
setFeedbackError(false);
|
|
728
|
+
try {
|
|
729
|
+
const outcome = await mushi.submitFeedbackSignal(reportId, signal);
|
|
730
|
+
if (!outcome) {
|
|
731
|
+
setFeedbackError(true);
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
await loadInbox({ silent: true });
|
|
735
|
+
await openThread(reportId, { silent: true });
|
|
736
|
+
} catch {
|
|
737
|
+
setFeedbackError(true);
|
|
738
|
+
} finally {
|
|
739
|
+
setFeedbackSending(false);
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
[mushi, selectedReportId, feedbackSending, loadInbox, openThread]
|
|
743
|
+
);
|
|
602
744
|
const sendAssistant = (0, import_react.useCallback)(async (message) => {
|
|
603
745
|
if (!mushi?.askAssistant || !message.trim() || assistantSending) return;
|
|
604
746
|
const trimmed = message.trim();
|
|
@@ -694,7 +836,7 @@ var MushiBottomSheet = ({
|
|
|
694
836
|
const handleSubmit = async () => {
|
|
695
837
|
if (!category || !description.trim() || !mushi) return;
|
|
696
838
|
const trimmed = description.trim();
|
|
697
|
-
if (trimmed.length <
|
|
839
|
+
if (trimmed.length < MIN_DESCRIPTION) {
|
|
698
840
|
setSubmitError("Please write at least 20 characters so we can understand the issue.");
|
|
699
841
|
return;
|
|
700
842
|
}
|
|
@@ -729,11 +871,181 @@ var MushiBottomSheet = ({
|
|
|
729
871
|
}
|
|
730
872
|
};
|
|
731
873
|
const activeScreenshot = screenshotDataUrl && screenshotAttached ? screenshotDataUrl : null;
|
|
732
|
-
const
|
|
733
|
-
const
|
|
874
|
+
const colors = resolveRNTheme(dark, theme);
|
|
875
|
+
const font = colors.fontFamily ? { fontFamily: colors.fontFamily } : null;
|
|
876
|
+
const radius = colors.radius;
|
|
734
877
|
const sheetTabs = ["report", "inbox", ...assistantEnabled ? ["assistant"] : []];
|
|
735
|
-
const canSubmit = !!category && description.trim().length >=
|
|
736
|
-
|
|
878
|
+
const canSubmit = !!category && description.trim().length >= MIN_DESCRIPTION && (phase === "form" || phase === "error");
|
|
879
|
+
const submitHint = canSubmit || phase === "sending" ? void 0 : !category ? t.step1.heading : rc.ui.addWords;
|
|
880
|
+
const selectedReport = selectedReportId ? inboxReports.find((r) => r.id === selectedReportId) ?? null : null;
|
|
881
|
+
const selectedView = selectedReport ? (0, import_reporter_ui.reporterStatus)(selectedReport, locale) : null;
|
|
882
|
+
const headerTitle = sheetTab === "assistant" ? assistantLabel : sheetTab === "inbox" ? t.flows.reports.title : t.widget.title;
|
|
883
|
+
const renderThread = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
885
|
+
import_react_native2.TouchableOpacity,
|
|
886
|
+
{
|
|
887
|
+
onPress: closeThread,
|
|
888
|
+
accessibilityRole: "button",
|
|
889
|
+
accessibilityLabel: t.widget.back,
|
|
890
|
+
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
891
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: [{ color: colors.accent, marginBottom: 8 }, font], children: [
|
|
892
|
+
"\u2190 ",
|
|
893
|
+
t.widget.back
|
|
894
|
+
] })
|
|
895
|
+
}
|
|
896
|
+
),
|
|
897
|
+
selectedReport && selectedView ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [s.headerCard, { backgroundColor: colors.surface, borderRadius: radius, borderColor: colors.border }], children: [
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.pill, { color: colors.fg, borderColor: colors.border }, font], children: selectedView.label }),
|
|
899
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted, fontSize: 12, marginTop: 4 }, font], children: selectedView.detail }),
|
|
900
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.fg, marginTop: 8 }, font], numberOfLines: 4, children: selectedReport.title ?? selectedReport.summary ?? selectedReport.description ?? "" })
|
|
901
|
+
] }) : null,
|
|
902
|
+
threadStatus === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { accessibilityLabel: t.flows.reports.loading, accessibilityLiveRegion: "polite", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [s.skeleton, { backgroundColor: colors.surface, width: `${90 - i * 18}%` }] }, i)) }) : threadStatus === "error" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.errorRow, accessibilityLiveRegion: "polite", children: [
|
|
903
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.error, flex: 1 }, font], accessibilityRole: "alert", children: rc.ui.loadError }),
|
|
904
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
905
|
+
import_react_native2.TouchableOpacity,
|
|
906
|
+
{
|
|
907
|
+
onPress: () => selectedReportId && void openThread(selectedReportId),
|
|
908
|
+
accessibilityRole: "button",
|
|
909
|
+
style: [s.retryBtn, { borderColor: colors.border, borderRadius: radius }],
|
|
910
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.fg, fontWeight: "600" }, font], children: rc.ui.retry })
|
|
911
|
+
}
|
|
912
|
+
)
|
|
913
|
+
] }) : threadComments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted, marginBottom: 8 }, font], children: rc.ui.noReplies }) : threadComments.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
914
|
+
import_react_native2.View,
|
|
915
|
+
{
|
|
916
|
+
style: [
|
|
917
|
+
s.threadBubble,
|
|
918
|
+
{
|
|
919
|
+
backgroundColor: colors.surface,
|
|
920
|
+
alignSelf: c.author_kind === "reporter" ? "flex-end" : "flex-start"
|
|
921
|
+
}
|
|
922
|
+
],
|
|
923
|
+
children: [
|
|
924
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted, fontSize: 11 }, font], children: c.author_kind === "reporter" ? rc.ui.you : rc.ui.developer }),
|
|
925
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.fg }, font], children: c.body })
|
|
926
|
+
]
|
|
927
|
+
},
|
|
928
|
+
c.id
|
|
929
|
+
)),
|
|
930
|
+
replyState === "sending" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [s.threadBubble, { backgroundColor: colors.surface, alignSelf: "flex-end", opacity: 0.7 }], children: [
|
|
931
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted, fontSize: 11 }, font], children: rc.ui.sending }),
|
|
932
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.fg }, font], children: replyText.trim() })
|
|
933
|
+
] }) : null,
|
|
934
|
+
selectedView?.canVerify ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.verifyRow, children: [
|
|
935
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
936
|
+
import_react_native2.TouchableOpacity,
|
|
937
|
+
{
|
|
938
|
+
style: [s.verifyBtn, { backgroundColor: colors.accent, borderRadius: radius }],
|
|
939
|
+
onPress: () => void submitFeedback("confirms"),
|
|
940
|
+
disabled: feedbackSending,
|
|
941
|
+
accessibilityRole: "button",
|
|
942
|
+
accessibilityState: { disabled: feedbackSending, busy: feedbackSending },
|
|
943
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.accentFg }, font], children: rc.ui.yes })
|
|
944
|
+
}
|
|
945
|
+
),
|
|
946
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
947
|
+
import_react_native2.TouchableOpacity,
|
|
948
|
+
{
|
|
949
|
+
style: [s.verifyBtn, { backgroundColor: colors.border, borderRadius: radius }],
|
|
950
|
+
onPress: () => void submitFeedback("not_fixed"),
|
|
951
|
+
disabled: feedbackSending,
|
|
952
|
+
accessibilityRole: "button",
|
|
953
|
+
accessibilityState: { disabled: feedbackSending, busy: feedbackSending },
|
|
954
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.fg }, font], children: rc.ui.notYet })
|
|
955
|
+
}
|
|
956
|
+
)
|
|
957
|
+
] }) : null,
|
|
958
|
+
feedbackError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.error, marginBottom: 8 }, font], accessibilityRole: "alert", children: rc.ui.sendFailed }) : null,
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.composer, children: [
|
|
960
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
961
|
+
import_react_native2.TextInput,
|
|
962
|
+
{
|
|
963
|
+
style: [
|
|
964
|
+
s.input,
|
|
965
|
+
s.composerInput,
|
|
966
|
+
{ backgroundColor: colors.surface, color: colors.fg, borderColor: colors.border, borderRadius: radius },
|
|
967
|
+
font
|
|
968
|
+
],
|
|
969
|
+
placeholder: t.flows.thread.replyPlaceholder,
|
|
970
|
+
placeholderTextColor: colors.muted,
|
|
971
|
+
value: replyText,
|
|
972
|
+
onChangeText: (text) => {
|
|
973
|
+
setReplyText(text.slice(0, 2e3));
|
|
974
|
+
if (replyState === "failed") setReplyState("idle");
|
|
975
|
+
},
|
|
976
|
+
multiline: true,
|
|
977
|
+
maxLength: 2e3,
|
|
978
|
+
editable: replyState !== "sending",
|
|
979
|
+
accessibilityLabel: t.flows.thread.replyPlaceholder
|
|
980
|
+
}
|
|
981
|
+
),
|
|
982
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
983
|
+
import_react_native2.TouchableOpacity,
|
|
984
|
+
{
|
|
985
|
+
style: [
|
|
986
|
+
s.sendBtn,
|
|
987
|
+
{
|
|
988
|
+
backgroundColor: replyText.trim() && replyState !== "sending" ? colors.accent : colors.disabled,
|
|
989
|
+
borderRadius: radius
|
|
990
|
+
}
|
|
991
|
+
],
|
|
992
|
+
onPress: () => void sendReply(),
|
|
993
|
+
disabled: !replyText.trim() || replyState === "sending",
|
|
994
|
+
accessibilityRole: "button",
|
|
995
|
+
accessibilityLabel: replyState === "failed" ? rc.ui.retry : t.flows.thread.send,
|
|
996
|
+
accessibilityState: { disabled: !replyText.trim() || replyState === "sending", busy: replyState === "sending" },
|
|
997
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
998
|
+
import_react_native2.Text,
|
|
999
|
+
{
|
|
1000
|
+
style: [
|
|
1001
|
+
s.submitText,
|
|
1002
|
+
{ color: replyText.trim() && replyState !== "sending" ? colors.accentFg : colors.disabledFg },
|
|
1003
|
+
font
|
|
1004
|
+
],
|
|
1005
|
+
children: replyState === "failed" ? rc.ui.retry : t.flows.thread.send
|
|
1006
|
+
}
|
|
1007
|
+
)
|
|
1008
|
+
}
|
|
1009
|
+
)
|
|
1010
|
+
] }),
|
|
1011
|
+
replyState === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: [{ color: colors.error, marginTop: 6, fontSize: 12 }, font], accessibilityRole: "alert", children: [
|
|
1012
|
+
rc.ui.sendFailed,
|
|
1013
|
+
" \xB7 ",
|
|
1014
|
+
rc.ui.retry
|
|
1015
|
+
] }) : null
|
|
1016
|
+
] });
|
|
1017
|
+
const renderInboxList = () => {
|
|
1018
|
+
if (inboxLoading && !inboxLoaded) {
|
|
1019
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted }, font], children: t.flows.reports.loading });
|
|
1020
|
+
}
|
|
1021
|
+
if (inboxReports.length === 0) {
|
|
1022
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted }, font], children: rc.ui.empty });
|
|
1023
|
+
}
|
|
1024
|
+
return inboxReports.map((r) => {
|
|
1025
|
+
const view = (0, import_reporter_ui.reporterStatus)(r, locale);
|
|
1026
|
+
const unread = (r.unread_count ?? 0) > 0;
|
|
1027
|
+
const title = (r.title ?? r.summary ?? r.description ?? "Report").slice(0, 80);
|
|
1028
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1029
|
+
import_react_native2.TouchableOpacity,
|
|
1030
|
+
{
|
|
1031
|
+
style: [s.inboxRow, { borderColor: colors.border }],
|
|
1032
|
+
onPress: () => void openThread(r.id),
|
|
1033
|
+
accessibilityRole: "button",
|
|
1034
|
+
accessibilityLabel: `${view.label}. ${title}${unread ? `. ${r.unread_count} new` : ""}`,
|
|
1035
|
+
children: [
|
|
1036
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.fg, fontWeight: unread ? "700" : "600" }, font], numberOfLines: 1, children: title }),
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.Text, { style: [{ color: unread ? colors.fg : colors.muted, fontSize: 12, marginTop: 2 }, font], numberOfLines: 1, children: [
|
|
1038
|
+
view.label,
|
|
1039
|
+
view.othersNote ? ` \xB7 ${view.othersNote}` : ""
|
|
1040
|
+
] }),
|
|
1041
|
+
unread && r.last_event_preview ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.fg, fontSize: 12, fontWeight: "700", marginTop: 2 }, font], numberOfLines: 1, children: r.last_event_preview }) : null
|
|
1042
|
+
]
|
|
1043
|
+
},
|
|
1044
|
+
r.id
|
|
1045
|
+
);
|
|
1046
|
+
});
|
|
1047
|
+
};
|
|
1048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Modal, { visible, transparent: true, animationType: "none", statusBarTranslucent: true, onRequestClose: handleClose, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
737
1049
|
import_react_native2.KeyboardAvoidingView,
|
|
738
1050
|
{
|
|
739
1051
|
style: s.flex,
|
|
@@ -744,44 +1056,69 @@ var MushiBottomSheet = ({
|
|
|
744
1056
|
import_react_native2.Animated.View,
|
|
745
1057
|
{
|
|
746
1058
|
style: [s.backdrop, { backgroundColor: colors.backdrop, opacity: backdropOpacity }],
|
|
747
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1059
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1060
|
+
import_react_native2.TouchableOpacity,
|
|
1061
|
+
{
|
|
1062
|
+
style: s.flex,
|
|
1063
|
+
activeOpacity: 1,
|
|
1064
|
+
onPress: handleClose,
|
|
1065
|
+
accessibilityRole: "button",
|
|
1066
|
+
accessibilityLabel: t.widget.close
|
|
1067
|
+
}
|
|
1068
|
+
)
|
|
748
1069
|
}
|
|
749
1070
|
),
|
|
750
1071
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
751
1072
|
import_react_native2.Animated.View,
|
|
752
1073
|
{
|
|
1074
|
+
accessibilityViewIsModal: true,
|
|
1075
|
+
onAccessibilityEscape: handleClose,
|
|
753
1076
|
style: [
|
|
754
1077
|
s.sheet,
|
|
755
1078
|
{ backgroundColor: colors.bg, transform: [{ translateY }] }
|
|
756
1079
|
],
|
|
757
1080
|
children: [
|
|
758
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
1081
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1082
|
+
import_react_native2.View,
|
|
1083
|
+
{
|
|
1084
|
+
...panResponder.panHandlers,
|
|
1085
|
+
style: s.handleArea,
|
|
1086
|
+
accessible: true,
|
|
1087
|
+
accessibilityRole: "adjustable",
|
|
1088
|
+
accessibilityLabel: t.widget.close,
|
|
1089
|
+
accessibilityActions: [{ name: "decrement", label: t.widget.close }, { name: "escape" }],
|
|
1090
|
+
onAccessibilityAction: (e) => {
|
|
1091
|
+
if (e.nativeEvent.actionName === "decrement" || e.nativeEvent.actionName === "escape") handleClose();
|
|
1092
|
+
},
|
|
1093
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [s.handle, { backgroundColor: colors.muted }] })
|
|
1094
|
+
}
|
|
1095
|
+
),
|
|
1096
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [s.header, { borderBottomColor: colors.border }], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { accessibilityRole: "header", style: [s.headerTitle, { color: colors.fg }, font], children: headerTitle }) }),
|
|
1097
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: [s.tabRow, { borderBottomColor: colors.border }], accessibilityRole: "tablist", children: sheetTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
764
1098
|
import_react_native2.TouchableOpacity,
|
|
765
1099
|
{
|
|
766
1100
|
onPress: () => {
|
|
767
1101
|
setSheetTab(tab);
|
|
768
|
-
if (tab === "inbox") void loadInbox();
|
|
769
|
-
else
|
|
1102
|
+
if (tab === "inbox") void loadInbox({ silent: inboxLoaded });
|
|
1103
|
+
else closeThread();
|
|
770
1104
|
},
|
|
771
1105
|
style: [s.tabBtn, sheetTab === tab && { borderBottomColor: colors.accent }],
|
|
772
|
-
|
|
1106
|
+
accessibilityRole: "tab",
|
|
1107
|
+
accessibilityState: { selected: sheetTab === tab },
|
|
1108
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.tabLabel, { color: sheetTab === tab ? colors.fg : colors.muted }, font], children: tab === "report" ? t.widget.trigger : tab === "inbox" ? t.flows.reports.title : assistantLabel })
|
|
773
1109
|
},
|
|
774
1110
|
tab
|
|
775
1111
|
)) }),
|
|
776
1112
|
sheetTab === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.ScrollView, { style: s.body, keyboardShouldPersistTaps: "handled", children: [
|
|
777
1113
|
assistantTurns.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
778
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.
|
|
1114
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted, marginBottom: 12, lineHeight: 20 }, font], children: greeting }),
|
|
779
1115
|
assistantSuggestions.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
780
1116
|
import_react_native2.TouchableOpacity,
|
|
781
1117
|
{
|
|
782
|
-
style: [s.assistantChip, { borderColor: colors.border, backgroundColor: colors.
|
|
1118
|
+
style: [s.assistantChip, { borderColor: colors.border, backgroundColor: colors.surface }],
|
|
783
1119
|
onPress: () => void sendAssistant(chip),
|
|
784
|
-
|
|
1120
|
+
accessibilityRole: "button",
|
|
1121
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.fg, fontSize: 13 }, font], children: chip })
|
|
785
1122
|
},
|
|
786
1123
|
chip
|
|
787
1124
|
))
|
|
@@ -792,25 +1129,34 @@ var MushiBottomSheet = ({
|
|
|
792
1129
|
s.assistantBubble,
|
|
793
1130
|
{
|
|
794
1131
|
alignSelf: turn.role === "user" ? "flex-end" : "flex-start",
|
|
795
|
-
backgroundColor: turn.role === "user" ? colors.accent : colors.
|
|
1132
|
+
backgroundColor: turn.role === "user" ? colors.accent : colors.surface
|
|
796
1133
|
}
|
|
797
1134
|
],
|
|
798
1135
|
children: [
|
|
799
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: turn.role === "user" ? colors.
|
|
800
|
-
turn.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1136
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: turn.role === "user" ? colors.accentFg : colors.fg }, font], children: turn.text }),
|
|
1137
|
+
turn.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1138
|
+
import_react_native2.TouchableOpacity,
|
|
1139
|
+
{
|
|
1140
|
+
onPress: () => void sendAssistant(opt),
|
|
1141
|
+
style: { marginTop: 8 },
|
|
1142
|
+
accessibilityRole: "button",
|
|
1143
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.accent, fontSize: 12 }, font], children: opt })
|
|
1144
|
+
},
|
|
1145
|
+
opt
|
|
1146
|
+
))
|
|
801
1147
|
]
|
|
802
1148
|
},
|
|
803
1149
|
`${turn.role}-${idx}`
|
|
804
1150
|
)),
|
|
805
|
-
assistantSending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.
|
|
806
|
-
assistantError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color:
|
|
1151
|
+
assistantSending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted, marginTop: 8 }, font], accessibilityLiveRegion: "polite", children: t.assistant.thinking }) : null,
|
|
1152
|
+
assistantError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.error, marginTop: 8 }, font], accessibilityRole: "alert", children: assistantError }) : null,
|
|
807
1153
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.assistantComposer, children: [
|
|
808
1154
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
809
1155
|
import_react_native2.TextInput,
|
|
810
1156
|
{
|
|
811
|
-
style: [s.input, { flex: 1, minHeight: 44, backgroundColor: colors.
|
|
1157
|
+
style: [s.input, { flex: 1, minHeight: 44, backgroundColor: colors.surface, color: colors.fg, borderColor: colors.border, borderRadius: radius }, font],
|
|
812
1158
|
placeholder: t.assistant.inputPlaceholder,
|
|
813
|
-
placeholderTextColor: colors.
|
|
1159
|
+
placeholderTextColor: colors.muted,
|
|
814
1160
|
value: assistantInput,
|
|
815
1161
|
onChangeText: setAssistantInput,
|
|
816
1162
|
editable: !assistantSending
|
|
@@ -819,45 +1165,19 @@ var MushiBottomSheet = ({
|
|
|
819
1165
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
820
1166
|
import_react_native2.TouchableOpacity,
|
|
821
1167
|
{
|
|
822
|
-
style: [s.submitBtn, { backgroundColor: colors.accent, paddingHorizontal: 16 }],
|
|
1168
|
+
style: [s.submitBtn, { backgroundColor: colors.accent, paddingHorizontal: 16, borderRadius: radius }],
|
|
823
1169
|
onPress: () => void sendAssistant(assistantInput),
|
|
824
1170
|
disabled: !assistantInput.trim() || assistantSending,
|
|
825
|
-
|
|
1171
|
+
accessibilityRole: "button",
|
|
1172
|
+
accessibilityLabel: t.flows.thread.send,
|
|
1173
|
+
accessibilityState: { disabled: !assistantInput.trim() || assistantSending, busy: assistantSending },
|
|
1174
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: colors.accentFg }], children: "\u2191" })
|
|
826
1175
|
}
|
|
827
1176
|
)
|
|
828
1177
|
] })
|
|
829
|
-
] }) : sheetTab === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.ScrollView, { style: s.body, keyboardShouldPersistTaps: "handled",
|
|
830
|
-
/* @__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: [
|
|
831
|
-
"\u2190 ",
|
|
832
|
-
t.widget.back
|
|
833
|
-
] }) }),
|
|
834
|
-
threadComments.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: [s.threadBubble, { backgroundColor: colors.card }], children: [
|
|
835
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, fontSize: 11 }, children: c.author_kind }),
|
|
836
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.text }, children: c.body })
|
|
837
|
-
] }, c.id)),
|
|
838
|
-
VERIFIABLE_STATUSES.has(
|
|
839
|
-
inboxReports.find((r) => r.id === selectedReportId)?.status ?? ""
|
|
840
|
-
) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.verifyRow, children: [
|
|
841
|
-
/* @__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 }) }),
|
|
842
|
-
/* @__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 }) })
|
|
843
|
-
] }),
|
|
844
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
845
|
-
import_react_native2.TextInput,
|
|
846
|
-
{
|
|
847
|
-
style: [s.input, { backgroundColor: colors.card, color: colors.text, borderColor: colors.border, minHeight: 48 }],
|
|
848
|
-
placeholder: t.flows.thread.replyPlaceholder,
|
|
849
|
-
placeholderTextColor: colors.sub,
|
|
850
|
-
value: replyText,
|
|
851
|
-
onChangeText: setReplyText
|
|
852
|
-
}
|
|
853
|
-
),
|
|
854
|
-
/* @__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 }) })
|
|
855
|
-
] }) : inboxReports.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.TouchableOpacity, { style: [s.inboxRow, { borderColor: colors.border }], onPress: () => openThread(r.id), children: [
|
|
856
|
-
/* @__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) }),
|
|
857
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.sub, fontSize: 11 }, children: reporterStatusShort(r.status) })
|
|
858
|
-
] }, r.id)) }) : phase === "sent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.sentWrap, children: [
|
|
1178
|
+
] }) : sheetTab === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.ScrollView, { style: s.body, keyboardShouldPersistTaps: "handled", contentContainerStyle: { paddingBottom: 24 }, children: selectedReportId ? renderThread() : renderInboxList() }) : phase === "sent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.sentWrap, accessibilityLiveRegion: "polite", children: [
|
|
859
1179
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.sentEmoji], children: "\u2705" }),
|
|
860
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.sentText, { color: colors.
|
|
1180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.sentText, { color: colors.fg }, font], children: t.widget.submitted })
|
|
861
1181
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
862
1182
|
import_react_native2.ScrollView,
|
|
863
1183
|
{
|
|
@@ -865,29 +1185,34 @@ var MushiBottomSheet = ({
|
|
|
865
1185
|
keyboardShouldPersistTaps: "handled",
|
|
866
1186
|
contentContainerStyle: { paddingBottom: 24 },
|
|
867
1187
|
children: [
|
|
868
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.stepLabel, { color: colors.
|
|
869
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: s.catRow, children: CATEGORY_KEYS.map((key) => {
|
|
1188
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.stepLabel, { color: colors.muted }, font], children: t.step1.heading }),
|
|
1189
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.View, { style: s.catRow, accessibilityRole: "radiogroup", children: CATEGORY_KEYS.map((key) => {
|
|
870
1190
|
const active = category === key;
|
|
871
1191
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
872
1192
|
import_react_native2.TouchableOpacity,
|
|
873
1193
|
{
|
|
874
1194
|
onPress: () => setCategory(key),
|
|
875
1195
|
activeOpacity: 0.7,
|
|
1196
|
+
accessibilityRole: "radio",
|
|
1197
|
+
accessibilityState: { selected: active, checked: active },
|
|
1198
|
+
accessibilityLabel: t.step1.categories[key],
|
|
876
1199
|
style: [
|
|
877
1200
|
s.catBtn,
|
|
878
1201
|
{
|
|
879
|
-
backgroundColor: active ? colors.accent : colors.
|
|
1202
|
+
backgroundColor: active ? colors.accent : colors.surface,
|
|
880
1203
|
borderColor: active ? colors.accent : colors.border
|
|
881
1204
|
}
|
|
882
1205
|
],
|
|
883
1206
|
children: [
|
|
884
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: s.catEmoji, children: CATEGORY_EMOJI[key] }),
|
|
1207
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: s.catEmoji, importantForAccessibility: "no", children: CATEGORY_EMOJI[key] }),
|
|
885
1208
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
886
1209
|
import_react_native2.Text,
|
|
887
1210
|
{
|
|
1211
|
+
numberOfLines: 1,
|
|
888
1212
|
style: [
|
|
889
1213
|
s.catLabel,
|
|
890
|
-
{ color: active ? colors.
|
|
1214
|
+
{ color: active ? colors.accentFg : colors.fg },
|
|
1215
|
+
font
|
|
891
1216
|
],
|
|
892
1217
|
children: t.step1.categories[key]
|
|
893
1218
|
}
|
|
@@ -903,13 +1228,16 @@ var MushiBottomSheet = ({
|
|
|
903
1228
|
style: [
|
|
904
1229
|
s.input,
|
|
905
1230
|
{
|
|
906
|
-
backgroundColor: colors.
|
|
907
|
-
color: colors.
|
|
908
|
-
borderColor: colors.border
|
|
909
|
-
|
|
1231
|
+
backgroundColor: colors.surface,
|
|
1232
|
+
color: colors.fg,
|
|
1233
|
+
borderColor: colors.border,
|
|
1234
|
+
borderRadius: radius
|
|
1235
|
+
},
|
|
1236
|
+
font
|
|
910
1237
|
],
|
|
911
1238
|
placeholder: t.step3.descriptionPlaceholder,
|
|
912
|
-
placeholderTextColor: colors.
|
|
1239
|
+
placeholderTextColor: colors.muted,
|
|
1240
|
+
accessibilityLabel: t.step3.descriptionPlaceholder,
|
|
913
1241
|
multiline: true,
|
|
914
1242
|
textAlignVertical: "top",
|
|
915
1243
|
value: description,
|
|
@@ -922,19 +1250,19 @@ var MushiBottomSheet = ({
|
|
|
922
1250
|
maxLength: 4e3
|
|
923
1251
|
}
|
|
924
1252
|
),
|
|
925
|
-
submitError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: { color: colors.
|
|
1253
|
+
submitError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.error, marginTop: 6, fontSize: 12 }, font], accessibilityRole: "alert", children: submitError }) : null,
|
|
926
1254
|
activeScreenshot ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.screenshotRow, children: [
|
|
927
1255
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
928
1256
|
import_react_native2.Image,
|
|
929
1257
|
{
|
|
930
1258
|
source: { uri: activeScreenshot },
|
|
931
|
-
style: [s.screenshotThumb, { backgroundColor: colors.
|
|
1259
|
+
style: [s.screenshotThumb, { backgroundColor: colors.fg }],
|
|
932
1260
|
accessibilityLabel: t.step3.screenshotPreviewAlt
|
|
933
1261
|
}
|
|
934
1262
|
),
|
|
935
1263
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native2.View, { style: s.screenshotMeta, children: [
|
|
936
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotLabel, { color: colors.
|
|
937
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotSub, { color: colors.
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotLabel, { color: colors.fg }, font], children: t.step3.screenshotAttached.replace(" \u2713", "") }),
|
|
1265
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotSub, { color: colors.muted }, font], children: screenshotSensitiveHint && screenshotSensitiveHint.trim() ? `\u26A0 ${screenshotSensitiveHint}` : t.step3.screenshotSensitiveHint.split("\u2014")[0]?.trim() ?? t.step3.screenshotSensitiveHint })
|
|
938
1266
|
] }),
|
|
939
1267
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
940
1268
|
import_react_native2.TouchableOpacity,
|
|
@@ -944,22 +1272,28 @@ var MushiBottomSheet = ({
|
|
|
944
1272
|
onClearScreenshot?.();
|
|
945
1273
|
},
|
|
946
1274
|
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
1275
|
+
accessibilityRole: "button",
|
|
947
1276
|
accessibilityLabel: t.widget.close,
|
|
948
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotRemove, { color: colors.
|
|
1277
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.screenshotRemove, { color: colors.muted }], children: "\u2715" })
|
|
949
1278
|
}
|
|
950
1279
|
)
|
|
951
1280
|
] }) : null,
|
|
1281
|
+
submitHint ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [{ color: colors.muted, fontSize: 12, marginBottom: 6 }, font], children: submitHint }) : null,
|
|
952
1282
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
953
1283
|
import_react_native2.TouchableOpacity,
|
|
954
1284
|
{
|
|
955
1285
|
onPress: handleSubmit,
|
|
956
1286
|
disabled: !canSubmit,
|
|
957
1287
|
activeOpacity: 0.8,
|
|
1288
|
+
accessibilityRole: "button",
|
|
1289
|
+
accessibilityLabel: phase === "sending" ? t.widget.submitting : t.widget.submit,
|
|
1290
|
+
accessibilityHint: submitHint,
|
|
1291
|
+
accessibilityState: { disabled: !canSubmit, busy: phase === "sending" },
|
|
958
1292
|
style: [
|
|
959
1293
|
s.submitBtn,
|
|
960
|
-
{ backgroundColor: canSubmit ? colors.accent : colors.disabled }
|
|
1294
|
+
{ backgroundColor: canSubmit ? colors.accent : colors.disabled, borderRadius: radius }
|
|
961
1295
|
],
|
|
962
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: canSubmit ? colors.
|
|
1296
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native2.Text, { style: [s.submitText, { color: canSubmit ? colors.accentFg : colors.disabledFg }, font], children: phase === "sending" ? t.widget.submitting : t.widget.submit })
|
|
963
1297
|
}
|
|
964
1298
|
)
|
|
965
1299
|
]
|
|
@@ -989,10 +1323,10 @@ var s = import_react_native2.StyleSheet.create({
|
|
|
989
1323
|
left: 0,
|
|
990
1324
|
right: 0,
|
|
991
1325
|
minHeight: SHEET_HEIGHT,
|
|
992
|
-
borderTopLeftRadius:
|
|
993
|
-
borderTopRightRadius:
|
|
994
|
-
paddingBottom: import_react_native2.Platform.OS === "ios" ? 34 :
|
|
995
|
-
shadowColor:
|
|
1326
|
+
borderTopLeftRadius: import_core4.MUSHI_RADIUS.sheet,
|
|
1327
|
+
borderTopRightRadius: import_core4.MUSHI_RADIUS.sheet,
|
|
1328
|
+
paddingBottom: import_react_native2.Platform.OS === "ios" ? 34 : import_core4.MUSHI_SPACING.roomy,
|
|
1329
|
+
shadowColor: import_core4.MUSHI_SHADOW_INK,
|
|
996
1330
|
shadowOffset: { width: 0, height: -3 },
|
|
997
1331
|
shadowOpacity: 0.12,
|
|
998
1332
|
shadowRadius: 8,
|
|
@@ -1000,88 +1334,72 @@ var s = import_react_native2.StyleSheet.create({
|
|
|
1000
1334
|
},
|
|
1001
1335
|
handleArea: {
|
|
1002
1336
|
alignItems: "center",
|
|
1003
|
-
paddingVertical:
|
|
1337
|
+
paddingVertical: import_core4.MUSHI_SPACING.comfy
|
|
1004
1338
|
},
|
|
1005
1339
|
handle: {
|
|
1006
1340
|
width: 40,
|
|
1007
1341
|
height: 5,
|
|
1008
|
-
borderRadius:
|
|
1342
|
+
borderRadius: import_core4.MUSHI_RADIUS.control,
|
|
1009
1343
|
opacity: 0.5
|
|
1010
1344
|
},
|
|
1011
|
-
|
|
1012
|
-
paddingHorizontal:
|
|
1013
|
-
|
|
1014
|
-
paddingBottom: import_core3.MUSHI_SPACING.comfy,
|
|
1015
|
-
borderBottomWidth: 1.5
|
|
1345
|
+
header: {
|
|
1346
|
+
paddingHorizontal: import_core4.MUSHI_SPACING.lounge,
|
|
1347
|
+
paddingBottom: import_core4.MUSHI_SPACING.comfy
|
|
1016
1348
|
},
|
|
1017
|
-
|
|
1018
|
-
fontSize: import_core3.MUSHI_TYPE.sizeLabel,
|
|
1019
|
-
fontWeight: "700",
|
|
1020
|
-
letterSpacing: 1.2,
|
|
1021
|
-
marginBottom: 2,
|
|
1022
|
-
opacity: 0.7
|
|
1023
|
-
},
|
|
1024
|
-
brandTitle: {
|
|
1349
|
+
headerTitle: {
|
|
1025
1350
|
fontSize: 18,
|
|
1026
|
-
fontWeight: "
|
|
1351
|
+
fontWeight: "700",
|
|
1027
1352
|
letterSpacing: -0.2
|
|
1028
1353
|
},
|
|
1029
1354
|
body: {
|
|
1030
|
-
paddingHorizontal:
|
|
1031
|
-
paddingTop:
|
|
1032
|
-
},
|
|
1033
|
-
title: {
|
|
1034
|
-
fontSize: 20,
|
|
1035
|
-
fontWeight: "700",
|
|
1036
|
-
marginBottom: import_core3.MUSHI_SPACING.roomy
|
|
1355
|
+
paddingHorizontal: import_core4.MUSHI_SPACING.lounge,
|
|
1356
|
+
paddingTop: import_core4.MUSHI_SPACING.tight
|
|
1037
1357
|
},
|
|
1038
1358
|
stepLabel: {
|
|
1039
|
-
fontSize:
|
|
1359
|
+
fontSize: import_core4.MUSHI_TYPE.sizeLabel,
|
|
1040
1360
|
fontWeight: "600",
|
|
1041
1361
|
letterSpacing: 0.2,
|
|
1042
|
-
marginTop:
|
|
1043
|
-
marginBottom:
|
|
1362
|
+
marginTop: import_core4.MUSHI_SPACING.snug,
|
|
1363
|
+
marginBottom: import_core4.MUSHI_SPACING.comfy,
|
|
1044
1364
|
textTransform: "uppercase"
|
|
1045
1365
|
},
|
|
1046
1366
|
catRow: {
|
|
1047
1367
|
flexDirection: "row",
|
|
1048
|
-
|
|
1049
|
-
|
|
1368
|
+
flexWrap: "wrap",
|
|
1369
|
+
gap: 8,
|
|
1370
|
+
marginBottom: import_core4.MUSHI_SPACING.roomy
|
|
1050
1371
|
},
|
|
1051
1372
|
catBtn: {
|
|
1373
|
+
flexDirection: "row",
|
|
1052
1374
|
alignItems: "center",
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1375
|
+
gap: 6,
|
|
1376
|
+
paddingVertical: 8,
|
|
1377
|
+
paddingHorizontal: 12,
|
|
1378
|
+
borderRadius: 999,
|
|
1056
1379
|
borderWidth: 1,
|
|
1057
|
-
flex: 1,
|
|
1058
|
-
marginHorizontal: 3,
|
|
1059
1380
|
minHeight: 44
|
|
1060
1381
|
},
|
|
1061
1382
|
catEmoji: {
|
|
1062
|
-
fontSize:
|
|
1063
|
-
marginBottom: import_core3.MUSHI_SPACING.tight
|
|
1383
|
+
fontSize: 16
|
|
1064
1384
|
},
|
|
1065
1385
|
catLabel: {
|
|
1066
|
-
fontSize:
|
|
1386
|
+
fontSize: 14,
|
|
1067
1387
|
fontWeight: "600"
|
|
1068
1388
|
},
|
|
1069
1389
|
input: {
|
|
1070
1390
|
borderWidth: 1,
|
|
1071
|
-
borderRadius: import_core3.MUSHI_RADIUS.card,
|
|
1072
1391
|
padding: 14,
|
|
1073
1392
|
fontSize: 15,
|
|
1074
1393
|
minHeight: 100,
|
|
1075
|
-
marginBottom:
|
|
1394
|
+
marginBottom: import_core4.MUSHI_SPACING.roomy
|
|
1076
1395
|
},
|
|
1077
1396
|
submitBtn: {
|
|
1078
|
-
borderRadius: import_core3.MUSHI_RADIUS.card,
|
|
1079
1397
|
paddingVertical: 14,
|
|
1080
1398
|
alignItems: "center",
|
|
1081
1399
|
minHeight: 44
|
|
1082
1400
|
},
|
|
1083
1401
|
submitText: {
|
|
1084
|
-
color:
|
|
1402
|
+
color: import_core4.MUSHI_INVERSE,
|
|
1085
1403
|
fontSize: 16,
|
|
1086
1404
|
fontWeight: "700"
|
|
1087
1405
|
},
|
|
@@ -1140,7 +1458,8 @@ var s = import_react_native2.StyleSheet.create({
|
|
|
1140
1458
|
alignItems: "center",
|
|
1141
1459
|
paddingVertical: 10,
|
|
1142
1460
|
borderBottomWidth: 2,
|
|
1143
|
-
borderBottomColor: "transparent"
|
|
1461
|
+
borderBottomColor: "transparent",
|
|
1462
|
+
minHeight: 44
|
|
1144
1463
|
},
|
|
1145
1464
|
tabLabel: {
|
|
1146
1465
|
fontSize: 14,
|
|
@@ -1148,12 +1467,47 @@ var s = import_react_native2.StyleSheet.create({
|
|
|
1148
1467
|
},
|
|
1149
1468
|
inboxRow: {
|
|
1150
1469
|
paddingVertical: 12,
|
|
1470
|
+
minHeight: 56,
|
|
1151
1471
|
borderBottomWidth: import_react_native2.StyleSheet.hairlineWidth
|
|
1152
1472
|
},
|
|
1473
|
+
headerCard: {
|
|
1474
|
+
borderWidth: import_react_native2.StyleSheet.hairlineWidth,
|
|
1475
|
+
padding: 12,
|
|
1476
|
+
marginBottom: 12
|
|
1477
|
+
},
|
|
1478
|
+
pill: {
|
|
1479
|
+
alignSelf: "flex-start",
|
|
1480
|
+
borderWidth: 1,
|
|
1481
|
+
borderRadius: 999,
|
|
1482
|
+
paddingHorizontal: 8,
|
|
1483
|
+
paddingVertical: 2,
|
|
1484
|
+
fontSize: 12,
|
|
1485
|
+
fontWeight: "600",
|
|
1486
|
+
overflow: "hidden"
|
|
1487
|
+
},
|
|
1488
|
+
skeleton: {
|
|
1489
|
+
height: 14,
|
|
1490
|
+
borderRadius: 6,
|
|
1491
|
+
marginBottom: 10
|
|
1492
|
+
},
|
|
1493
|
+
errorRow: {
|
|
1494
|
+
flexDirection: "row",
|
|
1495
|
+
alignItems: "center",
|
|
1496
|
+
gap: 8,
|
|
1497
|
+
marginBottom: 12
|
|
1498
|
+
},
|
|
1499
|
+
retryBtn: {
|
|
1500
|
+
borderWidth: 1,
|
|
1501
|
+
paddingHorizontal: 12,
|
|
1502
|
+
paddingVertical: 8,
|
|
1503
|
+
minHeight: 44,
|
|
1504
|
+
justifyContent: "center"
|
|
1505
|
+
},
|
|
1153
1506
|
threadBubble: {
|
|
1154
1507
|
borderRadius: 10,
|
|
1155
1508
|
padding: 10,
|
|
1156
|
-
marginBottom: 8
|
|
1509
|
+
marginBottom: 8,
|
|
1510
|
+
maxWidth: "88%"
|
|
1157
1511
|
},
|
|
1158
1512
|
verifyRow: {
|
|
1159
1513
|
flexDirection: "row",
|
|
@@ -1162,9 +1516,26 @@ var s = import_react_native2.StyleSheet.create({
|
|
|
1162
1516
|
},
|
|
1163
1517
|
verifyBtn: {
|
|
1164
1518
|
flex: 1,
|
|
1165
|
-
borderRadius: 10,
|
|
1166
1519
|
paddingVertical: 10,
|
|
1167
|
-
alignItems: "center"
|
|
1520
|
+
alignItems: "center",
|
|
1521
|
+
minHeight: 44
|
|
1522
|
+
},
|
|
1523
|
+
composer: {
|
|
1524
|
+
flexDirection: "row",
|
|
1525
|
+
alignItems: "flex-end",
|
|
1526
|
+
gap: 8
|
|
1527
|
+
},
|
|
1528
|
+
composerInput: {
|
|
1529
|
+
flex: 1,
|
|
1530
|
+
minHeight: 44,
|
|
1531
|
+
maxHeight: 120,
|
|
1532
|
+
marginBottom: 0
|
|
1533
|
+
},
|
|
1534
|
+
sendBtn: {
|
|
1535
|
+
paddingHorizontal: 16,
|
|
1536
|
+
paddingVertical: 12,
|
|
1537
|
+
minHeight: 44,
|
|
1538
|
+
justifyContent: "center"
|
|
1168
1539
|
},
|
|
1169
1540
|
assistantBubble: {
|
|
1170
1541
|
maxWidth: "88%",
|
|
@@ -1192,9 +1563,9 @@ var s = import_react_native2.StyleSheet.create({
|
|
|
1192
1563
|
// src/components/MushiFloatingButton.tsx
|
|
1193
1564
|
var import_react2 = require("react");
|
|
1194
1565
|
var import_react_native3 = require("react-native");
|
|
1195
|
-
var
|
|
1566
|
+
var import_core5 = require("@mushi-mushi/core");
|
|
1196
1567
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1197
|
-
var FAB_SIZE =
|
|
1568
|
+
var FAB_SIZE = import_core5.MUSHI_GEOMETRY.fabSize;
|
|
1198
1569
|
var EDGE_PADDING = 12;
|
|
1199
1570
|
function getScreenBounds() {
|
|
1200
1571
|
const { width, height } = import_react_native3.Dimensions.get("window");
|
|
@@ -1244,7 +1615,7 @@ var MushiFloatingButton = ({
|
|
|
1244
1615
|
const currentX = (0, import_react2.useRef)(baseX);
|
|
1245
1616
|
const currentY = (0, import_react2.useRef)(0);
|
|
1246
1617
|
const isDragging = (0, import_react2.useRef)(false);
|
|
1247
|
-
const pal = (0,
|
|
1618
|
+
const pal = (0, import_core5.mushiPalette)(dark ? "dark" : "light");
|
|
1248
1619
|
const accentColor = accent ?? pal.accent;
|
|
1249
1620
|
(0, import_react2.useEffect)(() => {
|
|
1250
1621
|
if (!persist) return;
|
|
@@ -1355,7 +1726,7 @@ var MushiFloatingButton = ({
|
|
|
1355
1726
|
onStartShouldSetResponder: () => !draggable,
|
|
1356
1727
|
onResponderGrant: handlePressIn,
|
|
1357
1728
|
onResponderRelease: handlePressOut,
|
|
1358
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Animated.Text, { style: s2.emoji, children:
|
|
1729
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native3.Animated.Text, { style: s2.emoji, children: import_core5.MUSHI_COPY.triggerText })
|
|
1359
1730
|
}
|
|
1360
1731
|
);
|
|
1361
1732
|
};
|
|
@@ -1381,14 +1752,14 @@ var s2 = import_react_native3.StyleSheet.create({
|
|
|
1381
1752
|
// src/components/MushiBanner.tsx
|
|
1382
1753
|
var import_react3 = require("react");
|
|
1383
1754
|
var import_react_native4 = require("react-native");
|
|
1384
|
-
var
|
|
1755
|
+
var import_core6 = require("@mushi-mushi/core");
|
|
1385
1756
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1386
|
-
var MUSHI_BANNER_DEFAULT_HEIGHT =
|
|
1757
|
+
var MUSHI_BANNER_DEFAULT_HEIGHT = import_core6.MUSHI_GEOMETRY.bannerHeight;
|
|
1387
1758
|
var MushiBanner = ({
|
|
1388
1759
|
onPress,
|
|
1389
1760
|
onDismiss,
|
|
1390
|
-
message =
|
|
1391
|
-
label =
|
|
1761
|
+
message = import_core6.MUSHI_COPY.bannerMessage,
|
|
1762
|
+
label = import_core6.MUSHI_COPY.bannerLabel,
|
|
1392
1763
|
onLayoutHeight
|
|
1393
1764
|
}) => {
|
|
1394
1765
|
const handleLayout = (0, import_react3.useCallback)(
|
|
@@ -1408,7 +1779,7 @@ var MushiBanner = ({
|
|
|
1408
1779
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.TouchableOpacity, { style: s3.main, onPress, activeOpacity: 0.85, children: [
|
|
1409
1780
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: s3.eyebrow, children: label.toUpperCase() }),
|
|
1410
1781
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: s3.message, numberOfLines: 2, children: message }),
|
|
1411
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: s3.cta, children:
|
|
1782
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.Text, { style: s3.cta, children: import_core6.MUSHI_COPY.bugCta })
|
|
1412
1783
|
] }),
|
|
1413
1784
|
onDismiss ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1414
1785
|
import_react_native4.TouchableOpacity,
|
|
@@ -1431,13 +1802,13 @@ var s3 = import_react_native4.StyleSheet.create({
|
|
|
1431
1802
|
left: 0,
|
|
1432
1803
|
right: 0,
|
|
1433
1804
|
bottom: 0,
|
|
1434
|
-
minHeight:
|
|
1805
|
+
minHeight: import_core6.MUSHI_GEOMETRY.bannerHeight,
|
|
1435
1806
|
flexDirection: "row",
|
|
1436
1807
|
alignItems: "stretch",
|
|
1437
|
-
backgroundColor:
|
|
1808
|
+
backgroundColor: import_core6.MUSHI_BANNER_NEON.bg,
|
|
1438
1809
|
borderTopWidth: 1,
|
|
1439
|
-
borderTopColor:
|
|
1440
|
-
zIndex:
|
|
1810
|
+
borderTopColor: import_core6.MUSHI_BANNER_NEON.border,
|
|
1811
|
+
zIndex: import_core6.MUSHI_Z.banner,
|
|
1441
1812
|
elevation: 8,
|
|
1442
1813
|
paddingBottom: import_react_native4.Platform.OS === "ios" ? 0 : 0
|
|
1443
1814
|
},
|
|
@@ -1445,27 +1816,27 @@ var s3 = import_react_native4.StyleSheet.create({
|
|
|
1445
1816
|
flex: 1,
|
|
1446
1817
|
flexDirection: "row",
|
|
1447
1818
|
alignItems: "center",
|
|
1448
|
-
gap:
|
|
1449
|
-
paddingHorizontal:
|
|
1450
|
-
paddingVertical:
|
|
1819
|
+
gap: import_core6.MUSHI_SPACING.snug,
|
|
1820
|
+
paddingHorizontal: import_core6.MUSHI_SPACING.comfy,
|
|
1821
|
+
paddingVertical: import_core6.MUSHI_SPACING.snug,
|
|
1451
1822
|
minHeight: 44
|
|
1452
1823
|
},
|
|
1453
1824
|
eyebrow: {
|
|
1454
|
-
fontSize:
|
|
1825
|
+
fontSize: import_core6.MUSHI_TYPE.sizeLabel,
|
|
1455
1826
|
fontWeight: "700",
|
|
1456
1827
|
letterSpacing: 1.2,
|
|
1457
|
-
color:
|
|
1828
|
+
color: import_core6.MUSHI_BANNER_NEON.fg
|
|
1458
1829
|
},
|
|
1459
1830
|
message: {
|
|
1460
1831
|
flex: 1,
|
|
1461
1832
|
fontSize: 12,
|
|
1462
1833
|
fontWeight: "500",
|
|
1463
|
-
color:
|
|
1834
|
+
color: import_core6.MUSHI_BANNER_NEON.fg
|
|
1464
1835
|
},
|
|
1465
1836
|
cta: {
|
|
1466
1837
|
fontSize: 12,
|
|
1467
1838
|
fontWeight: "700",
|
|
1468
|
-
color:
|
|
1839
|
+
color: import_core6.MUSHI_BANNER_NEON.fg,
|
|
1469
1840
|
textDecorationLine: "underline"
|
|
1470
1841
|
},
|
|
1471
1842
|
dismiss: {
|
|
@@ -1475,13 +1846,13 @@ var s3 = import_react_native4.StyleSheet.create({
|
|
|
1475
1846
|
dismissText: {
|
|
1476
1847
|
fontSize: 20,
|
|
1477
1848
|
lineHeight: 22,
|
|
1478
|
-
color:
|
|
1849
|
+
color: import_core6.MUSHI_BANNER_NEON.fg,
|
|
1479
1850
|
opacity: 0.7
|
|
1480
1851
|
}
|
|
1481
1852
|
});
|
|
1482
1853
|
|
|
1483
1854
|
// src/analytics/event-tracker.ts
|
|
1484
|
-
var
|
|
1855
|
+
var import_core7 = require("@mushi-mushi/core");
|
|
1485
1856
|
var CONSENT_BUFFER_MAX = 50;
|
|
1486
1857
|
var SPILL_MAX = 200;
|
|
1487
1858
|
var SPILL_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -1545,7 +1916,7 @@ function createRNEventTracker(opts) {
|
|
|
1545
1916
|
const client = resolveClient();
|
|
1546
1917
|
if (!client) return;
|
|
1547
1918
|
flushing = true;
|
|
1548
|
-
const batch = buffer.splice(0,
|
|
1919
|
+
const batch = buffer.splice(0, import_core7.EVENT_PROPERTY_LIMITS.maxServerBatch);
|
|
1549
1920
|
if (pendingIdentify) {
|
|
1550
1921
|
batch.unshift({ name: "identify", ts: (/* @__PURE__ */ new Date()).toISOString(), properties: {} });
|
|
1551
1922
|
pendingIdentify = false;
|
|
@@ -1569,7 +1940,7 @@ function createRNEventTracker(opts) {
|
|
|
1569
1940
|
} finally {
|
|
1570
1941
|
flushing = false;
|
|
1571
1942
|
}
|
|
1572
|
-
if (buffer.length >=
|
|
1943
|
+
if (buffer.length >= import_core7.EVENT_PROPERTY_LIMITS.maxClientBatch) void flushNow();
|
|
1573
1944
|
}
|
|
1574
1945
|
function enqueue(ev) {
|
|
1575
1946
|
if (consent === "denied") return;
|
|
@@ -1578,7 +1949,7 @@ function createRNEventTracker(opts) {
|
|
|
1578
1949
|
return;
|
|
1579
1950
|
}
|
|
1580
1951
|
buffer.push(ev);
|
|
1581
|
-
if (buffer.length >=
|
|
1952
|
+
if (buffer.length >= import_core7.EVENT_PROPERTY_LIMITS.maxClientBatch) void flushNow();
|
|
1582
1953
|
}
|
|
1583
1954
|
const ready = enabled ? (async () => {
|
|
1584
1955
|
storage = await loadStorage();
|
|
@@ -1618,17 +1989,17 @@ function createRNEventTracker(opts) {
|
|
|
1618
1989
|
ready,
|
|
1619
1990
|
track(name, properties, trackOpts) {
|
|
1620
1991
|
if (!enabled || destroyed) return false;
|
|
1621
|
-
if (!(0,
|
|
1622
|
-
const { properties: props } = (0,
|
|
1992
|
+
if (!(0, import_core7.isValidEventName)(name)) return false;
|
|
1993
|
+
const { properties: props } = (0, import_core7.sanitizeEventProperties)(properties, { allowlist, scrub: opts.scrub });
|
|
1623
1994
|
let merged = props;
|
|
1624
1995
|
if (trackOpts?.reserved) {
|
|
1625
|
-
const { properties: res } = (0,
|
|
1996
|
+
const { properties: res } = (0, import_core7.sanitizeEventProperties)(trackOpts.reserved, { allowReserved: true, scrub: opts.scrub });
|
|
1626
1997
|
merged = { ...props, ...res };
|
|
1627
1998
|
}
|
|
1628
1999
|
merged.$surface = SURFACE;
|
|
1629
2000
|
const route = opts.getRoute?.();
|
|
1630
2001
|
if (route && merged.$route === void 0) merged.$route = route;
|
|
1631
|
-
if (!(0,
|
|
2002
|
+
if (!(0, import_core7.propertiesWithinByteLimit)(merged)) return false;
|
|
1632
2003
|
enqueue({
|
|
1633
2004
|
name,
|
|
1634
2005
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1697,13 +2068,13 @@ function createRNEventTracker(opts) {
|
|
|
1697
2068
|
}
|
|
1698
2069
|
|
|
1699
2070
|
// src/analytics/session-tracker.ts
|
|
1700
|
-
var
|
|
2071
|
+
var import_core8 = require("@mushi-mushi/core");
|
|
1701
2072
|
var HEARTBEAT_INTERVAL_MS = 6e4;
|
|
1702
2073
|
var RESUME_WINDOW_MS = 30 * 6e4;
|
|
1703
2074
|
function createRNSessionTracker(opts) {
|
|
1704
2075
|
const clock = opts.now ?? Date.now;
|
|
1705
2076
|
const resolveClient = () => typeof opts.client === "function" ? opts.client() : opts.client;
|
|
1706
|
-
let sessionId = opts.sessionId ?? `sess_${(0,
|
|
2077
|
+
let sessionId = opts.sessionId ?? `sess_${(0, import_core8.newUuid)()}`;
|
|
1707
2078
|
let pageViewCount = 0;
|
|
1708
2079
|
let started = false;
|
|
1709
2080
|
let allowed = false;
|
|
@@ -1771,7 +2142,7 @@ function createRNSessionTracker(opts) {
|
|
|
1771
2142
|
backgroundedAt = null;
|
|
1772
2143
|
if (!allowed) return;
|
|
1773
2144
|
if (!started || away >= RESUME_WINDOW_MS) {
|
|
1774
|
-
sessionId = `sess_${(0,
|
|
2145
|
+
sessionId = `sess_${(0, import_core8.newUuid)()}`;
|
|
1775
2146
|
startSession();
|
|
1776
2147
|
} else {
|
|
1777
2148
|
send("session_heartbeat", { route: route() });
|
|
@@ -1800,7 +2171,7 @@ function createRNSessionTracker(opts) {
|
|
|
1800
2171
|
|
|
1801
2172
|
// src/version.ts
|
|
1802
2173
|
var MUSHI_SDK_PACKAGE = "@mushi-mushi/react-native";
|
|
1803
|
-
var MUSHI_SDK_VERSION = "0.
|
|
2174
|
+
var MUSHI_SDK_VERSION = "0.23.0" ? "0.23.0" : "0.17.0";
|
|
1804
2175
|
|
|
1805
2176
|
// src/provider.tsx
|
|
1806
2177
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -1852,9 +2223,9 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1852
2223
|
const networkRef = (0, import_react4.useRef)(null);
|
|
1853
2224
|
const queueRef = (0, import_react4.useRef)(null);
|
|
1854
2225
|
const apiClientRef = (0, import_react4.useRef)(null);
|
|
1855
|
-
const sessionIdRef = (0, import_react4.useRef)(`sess_${(0,
|
|
2226
|
+
const sessionIdRef = (0, import_react4.useRef)(`sess_${(0, import_core9.newUuid)()}`);
|
|
1856
2227
|
const breadcrumbsRef = (0, import_react4.useRef)(
|
|
1857
|
-
(0,
|
|
2228
|
+
(0, import_core9.createBreadcrumbBuffer)({ max: config.capture?.maxBreadcrumbs ?? 50 })
|
|
1858
2229
|
);
|
|
1859
2230
|
const [sheetVisible, setSheetVisible] = (0, import_react4.useState)(false);
|
|
1860
2231
|
const [sheetPreferredTab, setSheetPreferredTab] = (0, import_react4.useState)("report");
|
|
@@ -1879,7 +2250,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1879
2250
|
if (config.endpoint && !config.apiEndpoint && __DEV__) {
|
|
1880
2251
|
console.warn("[MushiProvider] `endpoint` is deprecated \u2014 use `apiEndpoint` instead.");
|
|
1881
2252
|
}
|
|
1882
|
-
const apiEndpoint = rawEndpoint ??
|
|
2253
|
+
const apiEndpoint = rawEndpoint ?? import_core9.DEFAULT_API_ENDPOINT;
|
|
1883
2254
|
(0, import_react4.useEffect)(() => {
|
|
1884
2255
|
if (config.capture?.console !== false) {
|
|
1885
2256
|
consoleRef.current = setupConsoleCapture(config.capture?.maxConsoleEntries);
|
|
@@ -1887,7 +2258,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1887
2258
|
if (config.capture?.network !== false) {
|
|
1888
2259
|
networkRef.current = setupNetworkCapture(config.capture?.maxNetworkEntries, apiEndpoint);
|
|
1889
2260
|
}
|
|
1890
|
-
apiClientRef.current = (0,
|
|
2261
|
+
apiClientRef.current = (0, import_core9.createApiClient)({
|
|
1891
2262
|
projectId: config.projectId,
|
|
1892
2263
|
apiKey: config.apiKey,
|
|
1893
2264
|
apiEndpoint,
|
|
@@ -1924,14 +2295,14 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
1924
2295
|
if (existing && existing.startsWith("mushi_")) {
|
|
1925
2296
|
reporterTokenRef.current = existing;
|
|
1926
2297
|
} else {
|
|
1927
|
-
const fresh = `mushi_${(0,
|
|
2298
|
+
const fresh = `mushi_${(0, import_core9.newUuid)()}`;
|
|
1928
2299
|
reporterTokenRef.current = fresh;
|
|
1929
2300
|
await saveReporterToken(fresh, secureStorage);
|
|
1930
2301
|
}
|
|
1931
2302
|
resolveReporterTokenReady();
|
|
1932
2303
|
} catch {
|
|
1933
2304
|
if (reporterTokenRef.current === `rn-${config.projectId}-anon`) {
|
|
1934
|
-
reporterTokenRef.current = `mushi_${(0,
|
|
2305
|
+
reporterTokenRef.current = `mushi_${(0, import_core9.newUuid)()}`;
|
|
1935
2306
|
}
|
|
1936
2307
|
resolveReporterTokenReady();
|
|
1937
2308
|
}
|
|
@@ -2051,7 +2422,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2051
2422
|
const merged = Object.keys(metadataRef.current).length > 0 ? { ...contextMeta, ...metadataRef.current } : Object.keys(contextMeta).length > 0 ? contextMeta : void 0;
|
|
2052
2423
|
const breadcrumbs = breadcrumbsRef.current.getAll().map((c) => ({
|
|
2053
2424
|
...c,
|
|
2054
|
-
message: (0,
|
|
2425
|
+
message: (0, import_core9.scrubPii)(c.message)
|
|
2055
2426
|
}));
|
|
2056
2427
|
const timeline = breadcrumbs.map((c) => ({
|
|
2057
2428
|
ts: c.timestamp,
|
|
@@ -2060,10 +2431,10 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2060
2431
|
}));
|
|
2061
2432
|
const fingerprintHash = getDeviceFingerprintHash(deviceInfo);
|
|
2062
2433
|
const report = {
|
|
2063
|
-
id: (0,
|
|
2434
|
+
id: (0, import_core9.newUuid)(),
|
|
2064
2435
|
projectId: config.projectId,
|
|
2065
2436
|
category: data.category,
|
|
2066
|
-
description: (0,
|
|
2437
|
+
description: (0, import_core9.scrubPii)(data.description),
|
|
2067
2438
|
environment: {
|
|
2068
2439
|
userAgent: deviceInfo.systemName ?? "ReactNative",
|
|
2069
2440
|
platform: deviceInfo.platform ?? "mobile",
|
|
@@ -2076,7 +2447,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2076
2447
|
},
|
|
2077
2448
|
consoleLogs: (consoleRef.current?.getEntries() ?? []).map((entry) => ({
|
|
2078
2449
|
...entry,
|
|
2079
|
-
message: (0,
|
|
2450
|
+
message: (0, import_core9.scrubPii)(entry.message)
|
|
2080
2451
|
})),
|
|
2081
2452
|
networkLogs: networkRef.current?.getEntries().map((entry) => ({
|
|
2082
2453
|
...entry,
|
|
@@ -2106,7 +2477,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2106
2477
|
const code = result.error?.code ?? "";
|
|
2107
2478
|
const isCredentialError = code === "HTTP_401" || code === "HTTP_403" || code.includes("UNAUTHORIZED") || code.includes("FORBIDDEN") || code.includes("INVALID_API_KEY");
|
|
2108
2479
|
if (isCredentialError) {
|
|
2109
|
-
const where = apiEndpoint.replace(/\/$/, "") ===
|
|
2480
|
+
const where = apiEndpoint.replace(/\/$/, "") === import_core9.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.";
|
|
2110
2481
|
console.error(
|
|
2111
2482
|
'[Mushi] Credentials rejected. Check your projectId and apiKey (must have "report:write" scope). ' + where
|
|
2112
2483
|
);
|
|
@@ -2167,7 +2538,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2167
2538
|
getRoute,
|
|
2168
2539
|
sdkVersion: MUSHI_SDK_VERSION,
|
|
2169
2540
|
config: config.analytics,
|
|
2170
|
-
scrub:
|
|
2541
|
+
scrub: import_core9.scrubPii
|
|
2171
2542
|
});
|
|
2172
2543
|
eventTrackerRef.current = tracker;
|
|
2173
2544
|
const sessions = config.trackSessions === false ? null : createRNSessionTracker({
|
|
@@ -2240,7 +2611,7 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2240
2611
|
identifyWithToken(token) {
|
|
2241
2612
|
userTokenRef.current = token && typeof token === "string" ? token : null;
|
|
2242
2613
|
if (userTokenRef.current) {
|
|
2243
|
-
const claims = (0,
|
|
2614
|
+
const claims = (0, import_core9.parseIdentityToken)(userTokenRef.current);
|
|
2244
2615
|
if (claims?.sub) {
|
|
2245
2616
|
userRef.current = {
|
|
2246
2617
|
id: claims.sub,
|
|
@@ -2295,6 +2666,23 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2295
2666
|
const res = await client.listReporterComments(reportId, reporterTokenRef.current);
|
|
2296
2667
|
return res.ok ? res.data.comments ?? [] : [];
|
|
2297
2668
|
},
|
|
2669
|
+
async loadMyThread(reportId) {
|
|
2670
|
+
const client = apiClientRef.current;
|
|
2671
|
+
if (!client) return null;
|
|
2672
|
+
try {
|
|
2673
|
+
await reporterTokenReadyRef.current;
|
|
2674
|
+
const res = await client.listReporterComments(reportId, reporterTokenRef.current);
|
|
2675
|
+
return res.ok ? res.data?.comments ?? [] : null;
|
|
2676
|
+
} catch {
|
|
2677
|
+
return null;
|
|
2678
|
+
}
|
|
2679
|
+
},
|
|
2680
|
+
async markReportRead(reportId) {
|
|
2681
|
+
const client = apiClientRef.current;
|
|
2682
|
+
if (!client) return 0;
|
|
2683
|
+
await reporterTokenReadyRef.current;
|
|
2684
|
+
return markReporterReportRead(client, reporterTokenRef.current, reportId);
|
|
2685
|
+
},
|
|
2298
2686
|
async replyToReport(reportId, body) {
|
|
2299
2687
|
const client = apiClientRef.current;
|
|
2300
2688
|
if (!client) return null;
|
|
@@ -2402,7 +2790,8 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2402
2790
|
assistantLabel: config.assistant?.label,
|
|
2403
2791
|
assistantGreeting: config.assistant?.greeting,
|
|
2404
2792
|
assistantSuggestions: config.assistant?.suggestions,
|
|
2405
|
-
inboxPollIntervalMs: config.widget?.inboxPollIntervalMs ?? 0
|
|
2793
|
+
inboxPollIntervalMs: config.widget?.inboxPollIntervalMs ?? 0,
|
|
2794
|
+
theme: config.widget?.theme
|
|
2406
2795
|
}
|
|
2407
2796
|
)
|
|
2408
2797
|
] });
|