@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.js
CHANGED
|
@@ -476,41 +476,105 @@ import {
|
|
|
476
476
|
useColorScheme
|
|
477
477
|
} from "react-native";
|
|
478
478
|
import {
|
|
479
|
-
mushiPalette,
|
|
480
|
-
MUSHI_BANNER_NEON,
|
|
481
479
|
MUSHI_COPY,
|
|
482
|
-
MUSHI_CONTROL_DISABLED,
|
|
483
480
|
MUSHI_INVERSE,
|
|
484
|
-
MUSHI_RADIUS,
|
|
481
|
+
MUSHI_RADIUS as MUSHI_RADIUS2,
|
|
485
482
|
MUSHI_SHADOW_INK,
|
|
486
483
|
MUSHI_SPACING,
|
|
487
484
|
MUSHI_TYPE
|
|
488
485
|
} from "@mushi-mushi/core";
|
|
486
|
+
import { reporterCopy, reporterStatus, resolveReporterLocale } from "@mushi-mushi/core/reporter-ui";
|
|
489
487
|
import { getLocale } from "@mushi-mushi/web/i18n";
|
|
490
488
|
|
|
491
|
-
// src/
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
489
|
+
// src/theme.ts
|
|
490
|
+
import { mushiPalette, MUSHI_CONTROL_DISABLED, MUSHI_RADIUS } from "@mushi-mushi/core";
|
|
491
|
+
function hexToRgb(hex) {
|
|
492
|
+
const m = /^#([0-9a-f]{3}|[0-9a-f]{6})([0-9a-f]{2})?$/i.exec(hex.trim());
|
|
493
|
+
if (!m) return null;
|
|
494
|
+
const h = m[1].length === 3 ? m[1].split("").map((c) => c + c).join("") : m[1];
|
|
495
|
+
return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16));
|
|
496
|
+
}
|
|
497
|
+
function luminance([r, g, b]) {
|
|
498
|
+
const lin = (c) => {
|
|
499
|
+
const s4 = c / 255;
|
|
500
|
+
return s4 <= 0.03928 ? s4 / 12.92 : ((s4 + 0.055) / 1.055) ** 2.4;
|
|
501
|
+
};
|
|
502
|
+
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
|
|
503
|
+
}
|
|
504
|
+
function contrastingText(bg, fallback) {
|
|
505
|
+
const rgb = hexToRgb(bg);
|
|
506
|
+
if (!rgb) return fallback;
|
|
507
|
+
const l = luminance(rgb);
|
|
508
|
+
return 1.05 / (l + 0.05) >= (l + 0.05) / 0.05 ? "#FFFFFF" : "#000000";
|
|
509
|
+
}
|
|
510
|
+
function resolveRNTheme(dark, override = {}) {
|
|
511
|
+
const pal = mushiPalette(dark ? "dark" : "light");
|
|
512
|
+
const base = {
|
|
513
|
+
bg: dark ? pal.paper : pal.paperRaised,
|
|
514
|
+
fg: pal.ink,
|
|
515
|
+
muted: pal.inkMuted,
|
|
516
|
+
surface: dark ? pal.paperRaised : pal.paper,
|
|
517
|
+
border: pal.ruleStrong,
|
|
518
|
+
accent: pal.ink,
|
|
519
|
+
accentFg: dark ? pal.paper : pal.paperRaised,
|
|
520
|
+
success: pal.ok,
|
|
521
|
+
error: pal.danger,
|
|
522
|
+
fontFamily: void 0,
|
|
523
|
+
radius: MUSHI_RADIUS.card
|
|
524
|
+
};
|
|
525
|
+
const defined = Object.fromEntries(
|
|
526
|
+
Object.entries(override).filter(([, v]) => v !== void 0 && v !== null && v !== "")
|
|
527
|
+
);
|
|
528
|
+
const merged = { ...base, ...defined };
|
|
529
|
+
if (defined.accent && !defined.accentFg) merged.accentFg = contrastingText(defined.accent, base.accentFg);
|
|
530
|
+
return {
|
|
531
|
+
...merged,
|
|
532
|
+
backdrop: dark ? "rgba(0,0,0,0.6)" : "rgba(0,0,0,0.35)",
|
|
533
|
+
disabled: dark ? MUSHI_CONTROL_DISABLED.dark : MUSHI_CONTROL_DISABLED.light,
|
|
534
|
+
disabledFg: pal.inkFaint
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// src/reporter-thread.ts
|
|
539
|
+
var THREAD_LOAD_TIMEOUT_MS = 12e3;
|
|
540
|
+
function settleWithin(p, ms) {
|
|
541
|
+
return new Promise((resolve) => {
|
|
542
|
+
const timer = setTimeout(() => resolve(null), ms);
|
|
543
|
+
p.then(
|
|
544
|
+
(value) => {
|
|
545
|
+
clearTimeout(timer);
|
|
546
|
+
resolve(value);
|
|
547
|
+
},
|
|
548
|
+
() => {
|
|
549
|
+
clearTimeout(timer);
|
|
550
|
+
resolve(null);
|
|
551
|
+
}
|
|
552
|
+
);
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
function loadReporterThread(load, reportId, timeoutMs = THREAD_LOAD_TIMEOUT_MS) {
|
|
556
|
+
let started;
|
|
557
|
+
try {
|
|
558
|
+
started = load(reportId);
|
|
559
|
+
} catch {
|
|
560
|
+
return Promise.resolve(null);
|
|
561
|
+
}
|
|
562
|
+
return settleWithin(started, timeoutMs);
|
|
563
|
+
}
|
|
564
|
+
async function markReporterReportRead(client, reporterToken, reportId) {
|
|
565
|
+
try {
|
|
566
|
+
const res = await client.listNotifications(reporterToken, { limit: 100 });
|
|
567
|
+
if (!res.ok) return 0;
|
|
568
|
+
const rows = res.data?.notifications ?? [];
|
|
569
|
+
const ids = rows.filter((n) => !n.read_at && n.payload?.reportId === reportId).map((n) => String(n.id));
|
|
570
|
+
let marked = 0;
|
|
571
|
+
for (const id of ids) {
|
|
572
|
+
const r = await client.markNotificationRead(id, reporterToken);
|
|
573
|
+
if (r.ok) marked++;
|
|
574
|
+
}
|
|
575
|
+
return marked;
|
|
576
|
+
} catch {
|
|
577
|
+
return 0;
|
|
514
578
|
}
|
|
515
579
|
}
|
|
516
580
|
|
|
@@ -519,6 +583,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
519
583
|
var { height: SCREEN_HEIGHT } = Dimensions2.get("window");
|
|
520
584
|
var SHEET_HEIGHT = SCREEN_HEIGHT * 0.55;
|
|
521
585
|
var DISMISS_THRESHOLD = 80;
|
|
586
|
+
var MIN_DESCRIPTION = 20;
|
|
522
587
|
var CATEGORY_KEYS = ["bug", "slow", "visual", "confusing", "other"];
|
|
523
588
|
var CATEGORY_EMOJI = {
|
|
524
589
|
bug: "\u{1F41B}",
|
|
@@ -527,7 +592,6 @@ var CATEGORY_EMOJI = {
|
|
|
527
592
|
confusing: "\u{1F615}",
|
|
528
593
|
other: "\u{1F4AC}"
|
|
529
594
|
};
|
|
530
|
-
var VERIFIABLE_STATUSES = /* @__PURE__ */ new Set(["fixed", "resolved", "verified"]);
|
|
531
595
|
var MushiBottomSheet = ({
|
|
532
596
|
visible,
|
|
533
597
|
onClose,
|
|
@@ -539,10 +603,15 @@ var MushiBottomSheet = ({
|
|
|
539
603
|
assistantLabel = MUSHI_COPY.assistantTab,
|
|
540
604
|
assistantGreeting,
|
|
541
605
|
assistantSuggestions = [],
|
|
542
|
-
inboxPollIntervalMs = 0
|
|
606
|
+
inboxPollIntervalMs = 0,
|
|
607
|
+
theme
|
|
543
608
|
}) => {
|
|
544
609
|
const mushi = useMushiContext();
|
|
545
610
|
const t = getLocale();
|
|
611
|
+
const locale = resolveReporterLocale(
|
|
612
|
+
typeof navigator !== "undefined" ? navigator.language : void 0
|
|
613
|
+
);
|
|
614
|
+
const rc = reporterCopy(locale);
|
|
546
615
|
const greeting = assistantGreeting ?? t.assistant.defaultGreeting;
|
|
547
616
|
const scheme = useColorScheme();
|
|
548
617
|
const dark = scheme === "dark";
|
|
@@ -554,26 +623,37 @@ var MushiBottomSheet = ({
|
|
|
554
623
|
const [submitError, setSubmitError] = useState(null);
|
|
555
624
|
const [sheetTab, setSheetTab] = useState("report");
|
|
556
625
|
const [inboxReports, setInboxReports] = useState([]);
|
|
626
|
+
const [inboxLoaded, setInboxLoaded] = useState(false);
|
|
557
627
|
const [inboxLoading, setInboxLoading] = useState(false);
|
|
558
628
|
const [selectedReportId, setSelectedReportId] = useState(null);
|
|
629
|
+
const selectedRef = useRef(null);
|
|
559
630
|
const [threadComments, setThreadComments] = useState([]);
|
|
631
|
+
const [threadStatus, setThreadStatus] = useState("idle");
|
|
560
632
|
const [replyText, setReplyText] = useState("");
|
|
633
|
+
const [replyState, setReplyState] = useState("idle");
|
|
634
|
+
const [feedbackSending, setFeedbackSending] = useState(false);
|
|
635
|
+
const [feedbackError, setFeedbackError] = useState(false);
|
|
561
636
|
const [assistantInput, setAssistantInput] = useState("");
|
|
562
637
|
const [assistantThreadId, setAssistantThreadId] = useState(null);
|
|
563
638
|
const [assistantSending, setAssistantSending] = useState(false);
|
|
564
639
|
const [assistantError, setAssistantError] = useState(null);
|
|
565
640
|
const [assistantTurns, setAssistantTurns] = useState([]);
|
|
566
641
|
const [screenshotAttached, setScreenshotAttached] = useState(true);
|
|
567
|
-
const loadInbox = useCallback(
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
642
|
+
const loadInbox = useCallback(
|
|
643
|
+
async (opts = {}) => {
|
|
644
|
+
if (!mushi?.listMyReports) return;
|
|
645
|
+
if (!opts.silent) setInboxLoading(true);
|
|
646
|
+
try {
|
|
647
|
+
const rows = await mushi.listMyReports();
|
|
648
|
+
setInboxReports(rows.filter((r) => !reporterStatus(r, locale).hidden));
|
|
649
|
+
setInboxLoaded(true);
|
|
650
|
+
} catch {
|
|
651
|
+
} finally {
|
|
652
|
+
if (!opts.silent) setInboxLoading(false);
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
[mushi, locale]
|
|
656
|
+
);
|
|
577
657
|
useEffect(() => {
|
|
578
658
|
if (visible) {
|
|
579
659
|
setScreenshotAttached(true);
|
|
@@ -584,28 +664,87 @@ var MushiBottomSheet = ({
|
|
|
584
664
|
useEffect(() => {
|
|
585
665
|
if (!visible || sheetTab !== "inbox" || inboxPollIntervalMs <= 0) return;
|
|
586
666
|
const timer = setInterval(() => {
|
|
587
|
-
void loadInbox();
|
|
667
|
+
void loadInbox({ silent: true });
|
|
588
668
|
}, inboxPollIntervalMs);
|
|
589
669
|
return () => clearInterval(timer);
|
|
590
670
|
}, [visible, sheetTab, inboxPollIntervalMs, loadInbox]);
|
|
591
|
-
const openThread = useCallback(
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
671
|
+
const openThread = useCallback(
|
|
672
|
+
async (reportId, opts = {}) => {
|
|
673
|
+
selectedRef.current = reportId;
|
|
674
|
+
setSelectedReportId(reportId);
|
|
675
|
+
if (!opts.silent) {
|
|
676
|
+
setThreadComments([]);
|
|
677
|
+
setThreadStatus("loading");
|
|
678
|
+
setReplyState("idle");
|
|
679
|
+
setFeedbackError(false);
|
|
680
|
+
}
|
|
681
|
+
const load = mushi?.loadMyThread ?? mushi?.listMyComments;
|
|
682
|
+
const comments = load ? await loadReporterThread(load, reportId) : null;
|
|
683
|
+
if (selectedRef.current !== reportId) return;
|
|
684
|
+
if (comments === null) {
|
|
685
|
+
setThreadStatus((prev) => opts.silent && prev === "ready" ? "ready" : "error");
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
setThreadComments(comments);
|
|
689
|
+
setThreadStatus("ready");
|
|
690
|
+
if (!opts.silent && mushi?.markReportRead) {
|
|
691
|
+
mushi.markReportRead(reportId).then((marked) => {
|
|
692
|
+
if (marked > 0) {
|
|
693
|
+
setInboxReports((rows) => rows.map((r) => r.id === reportId ? { ...r, unread_count: 0 } : r));
|
|
694
|
+
}
|
|
695
|
+
}).catch(() => void 0);
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
[mushi]
|
|
699
|
+
);
|
|
700
|
+
const closeThread = useCallback(() => {
|
|
701
|
+
selectedRef.current = null;
|
|
702
|
+
setSelectedReportId(null);
|
|
703
|
+
setThreadStatus("idle");
|
|
704
|
+
}, []);
|
|
597
705
|
const sendReply = useCallback(async () => {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
706
|
+
const body = replyText.trim();
|
|
707
|
+
const reportId = selectedReportId;
|
|
708
|
+
if (!mushi?.replyToReport || !reportId || !body || replyState === "sending") return;
|
|
709
|
+
setReplyState("sending");
|
|
710
|
+
try {
|
|
711
|
+
const comment = await settleWithin(mushi.replyToReport(reportId, body), THREAD_LOAD_TIMEOUT_MS);
|
|
712
|
+
if (!comment) {
|
|
713
|
+
setReplyState("failed");
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
setReplyText("");
|
|
717
|
+
setReplyState("idle");
|
|
718
|
+
if (selectedRef.current === reportId) {
|
|
719
|
+
setThreadComments((prev) => [...prev, comment]);
|
|
720
|
+
void openThread(reportId, { silent: true });
|
|
721
|
+
}
|
|
722
|
+
} catch {
|
|
723
|
+
setReplyState("failed");
|
|
724
|
+
}
|
|
725
|
+
}, [mushi, selectedReportId, replyText, replyState, openThread]);
|
|
726
|
+
const submitFeedback = useCallback(
|
|
727
|
+
async (signal) => {
|
|
728
|
+
const reportId = selectedReportId;
|
|
729
|
+
if (!mushi?.submitFeedbackSignal || !reportId || feedbackSending) return;
|
|
730
|
+
setFeedbackSending(true);
|
|
731
|
+
setFeedbackError(false);
|
|
732
|
+
try {
|
|
733
|
+
const outcome = await mushi.submitFeedbackSignal(reportId, signal);
|
|
734
|
+
if (!outcome) {
|
|
735
|
+
setFeedbackError(true);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
await loadInbox({ silent: true });
|
|
739
|
+
await openThread(reportId, { silent: true });
|
|
740
|
+
} catch {
|
|
741
|
+
setFeedbackError(true);
|
|
742
|
+
} finally {
|
|
743
|
+
setFeedbackSending(false);
|
|
744
|
+
}
|
|
745
|
+
},
|
|
746
|
+
[mushi, selectedReportId, feedbackSending, loadInbox, openThread]
|
|
747
|
+
);
|
|
609
748
|
const sendAssistant = useCallback(async (message) => {
|
|
610
749
|
if (!mushi?.askAssistant || !message.trim() || assistantSending) return;
|
|
611
750
|
const trimmed = message.trim();
|
|
@@ -701,7 +840,7 @@ var MushiBottomSheet = ({
|
|
|
701
840
|
const handleSubmit = async () => {
|
|
702
841
|
if (!category || !description.trim() || !mushi) return;
|
|
703
842
|
const trimmed = description.trim();
|
|
704
|
-
if (trimmed.length <
|
|
843
|
+
if (trimmed.length < MIN_DESCRIPTION) {
|
|
705
844
|
setSubmitError("Please write at least 20 characters so we can understand the issue.");
|
|
706
845
|
return;
|
|
707
846
|
}
|
|
@@ -736,11 +875,181 @@ var MushiBottomSheet = ({
|
|
|
736
875
|
}
|
|
737
876
|
};
|
|
738
877
|
const activeScreenshot = screenshotDataUrl && screenshotAttached ? screenshotDataUrl : null;
|
|
739
|
-
const
|
|
740
|
-
const
|
|
878
|
+
const colors = resolveRNTheme(dark, theme);
|
|
879
|
+
const font = colors.fontFamily ? { fontFamily: colors.fontFamily } : null;
|
|
880
|
+
const radius = colors.radius;
|
|
741
881
|
const sheetTabs = ["report", "inbox", ...assistantEnabled ? ["assistant"] : []];
|
|
742
|
-
const canSubmit = !!category && description.trim().length >=
|
|
743
|
-
|
|
882
|
+
const canSubmit = !!category && description.trim().length >= MIN_DESCRIPTION && (phase === "form" || phase === "error");
|
|
883
|
+
const submitHint = canSubmit || phase === "sending" ? void 0 : !category ? t.step1.heading : rc.ui.addWords;
|
|
884
|
+
const selectedReport = selectedReportId ? inboxReports.find((r) => r.id === selectedReportId) ?? null : null;
|
|
885
|
+
const selectedView = selectedReport ? reporterStatus(selectedReport, locale) : null;
|
|
886
|
+
const headerTitle = sheetTab === "assistant" ? assistantLabel : sheetTab === "inbox" ? t.flows.reports.title : t.widget.title;
|
|
887
|
+
const renderThread = () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
888
|
+
/* @__PURE__ */ jsx(
|
|
889
|
+
TouchableOpacity,
|
|
890
|
+
{
|
|
891
|
+
onPress: closeThread,
|
|
892
|
+
accessibilityRole: "button",
|
|
893
|
+
accessibilityLabel: t.widget.back,
|
|
894
|
+
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
895
|
+
children: /* @__PURE__ */ jsxs(Text, { style: [{ color: colors.accent, marginBottom: 8 }, font], children: [
|
|
896
|
+
"\u2190 ",
|
|
897
|
+
t.widget.back
|
|
898
|
+
] })
|
|
899
|
+
}
|
|
900
|
+
),
|
|
901
|
+
selectedReport && selectedView ? /* @__PURE__ */ jsxs(View, { style: [s.headerCard, { backgroundColor: colors.surface, borderRadius: radius, borderColor: colors.border }], children: [
|
|
902
|
+
/* @__PURE__ */ jsx(Text, { style: [s.pill, { color: colors.fg, borderColor: colors.border }, font], children: selectedView.label }),
|
|
903
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted, fontSize: 12, marginTop: 4 }, font], children: selectedView.detail }),
|
|
904
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.fg, marginTop: 8 }, font], numberOfLines: 4, children: selectedReport.title ?? selectedReport.summary ?? selectedReport.description ?? "" })
|
|
905
|
+
] }) : null,
|
|
906
|
+
threadStatus === "loading" ? /* @__PURE__ */ jsx(View, { accessibilityLabel: t.flows.reports.loading, accessibilityLiveRegion: "polite", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx(View, { style: [s.skeleton, { backgroundColor: colors.surface, width: `${90 - i * 18}%` }] }, i)) }) : threadStatus === "error" ? /* @__PURE__ */ jsxs(View, { style: s.errorRow, accessibilityLiveRegion: "polite", children: [
|
|
907
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.error, flex: 1 }, font], accessibilityRole: "alert", children: rc.ui.loadError }),
|
|
908
|
+
/* @__PURE__ */ jsx(
|
|
909
|
+
TouchableOpacity,
|
|
910
|
+
{
|
|
911
|
+
onPress: () => selectedReportId && void openThread(selectedReportId),
|
|
912
|
+
accessibilityRole: "button",
|
|
913
|
+
style: [s.retryBtn, { borderColor: colors.border, borderRadius: radius }],
|
|
914
|
+
children: /* @__PURE__ */ jsx(Text, { style: [{ color: colors.fg, fontWeight: "600" }, font], children: rc.ui.retry })
|
|
915
|
+
}
|
|
916
|
+
)
|
|
917
|
+
] }) : threadComments.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted, marginBottom: 8 }, font], children: rc.ui.noReplies }) : threadComments.map((c) => /* @__PURE__ */ jsxs(
|
|
918
|
+
View,
|
|
919
|
+
{
|
|
920
|
+
style: [
|
|
921
|
+
s.threadBubble,
|
|
922
|
+
{
|
|
923
|
+
backgroundColor: colors.surface,
|
|
924
|
+
alignSelf: c.author_kind === "reporter" ? "flex-end" : "flex-start"
|
|
925
|
+
}
|
|
926
|
+
],
|
|
927
|
+
children: [
|
|
928
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted, fontSize: 11 }, font], children: c.author_kind === "reporter" ? rc.ui.you : rc.ui.developer }),
|
|
929
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.fg }, font], children: c.body })
|
|
930
|
+
]
|
|
931
|
+
},
|
|
932
|
+
c.id
|
|
933
|
+
)),
|
|
934
|
+
replyState === "sending" ? /* @__PURE__ */ jsxs(View, { style: [s.threadBubble, { backgroundColor: colors.surface, alignSelf: "flex-end", opacity: 0.7 }], children: [
|
|
935
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted, fontSize: 11 }, font], children: rc.ui.sending }),
|
|
936
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.fg }, font], children: replyText.trim() })
|
|
937
|
+
] }) : null,
|
|
938
|
+
selectedView?.canVerify ? /* @__PURE__ */ jsxs(View, { style: s.verifyRow, children: [
|
|
939
|
+
/* @__PURE__ */ jsx(
|
|
940
|
+
TouchableOpacity,
|
|
941
|
+
{
|
|
942
|
+
style: [s.verifyBtn, { backgroundColor: colors.accent, borderRadius: radius }],
|
|
943
|
+
onPress: () => void submitFeedback("confirms"),
|
|
944
|
+
disabled: feedbackSending,
|
|
945
|
+
accessibilityRole: "button",
|
|
946
|
+
accessibilityState: { disabled: feedbackSending, busy: feedbackSending },
|
|
947
|
+
children: /* @__PURE__ */ jsx(Text, { style: [s.submitText, { color: colors.accentFg }, font], children: rc.ui.yes })
|
|
948
|
+
}
|
|
949
|
+
),
|
|
950
|
+
/* @__PURE__ */ jsx(
|
|
951
|
+
TouchableOpacity,
|
|
952
|
+
{
|
|
953
|
+
style: [s.verifyBtn, { backgroundColor: colors.border, borderRadius: radius }],
|
|
954
|
+
onPress: () => void submitFeedback("not_fixed"),
|
|
955
|
+
disabled: feedbackSending,
|
|
956
|
+
accessibilityRole: "button",
|
|
957
|
+
accessibilityState: { disabled: feedbackSending, busy: feedbackSending },
|
|
958
|
+
children: /* @__PURE__ */ jsx(Text, { style: [s.submitText, { color: colors.fg }, font], children: rc.ui.notYet })
|
|
959
|
+
}
|
|
960
|
+
)
|
|
961
|
+
] }) : null,
|
|
962
|
+
feedbackError ? /* @__PURE__ */ jsx(Text, { style: [{ color: colors.error, marginBottom: 8 }, font], accessibilityRole: "alert", children: rc.ui.sendFailed }) : null,
|
|
963
|
+
/* @__PURE__ */ jsxs(View, { style: s.composer, children: [
|
|
964
|
+
/* @__PURE__ */ jsx(
|
|
965
|
+
TextInput,
|
|
966
|
+
{
|
|
967
|
+
style: [
|
|
968
|
+
s.input,
|
|
969
|
+
s.composerInput,
|
|
970
|
+
{ backgroundColor: colors.surface, color: colors.fg, borderColor: colors.border, borderRadius: radius },
|
|
971
|
+
font
|
|
972
|
+
],
|
|
973
|
+
placeholder: t.flows.thread.replyPlaceholder,
|
|
974
|
+
placeholderTextColor: colors.muted,
|
|
975
|
+
value: replyText,
|
|
976
|
+
onChangeText: (text) => {
|
|
977
|
+
setReplyText(text.slice(0, 2e3));
|
|
978
|
+
if (replyState === "failed") setReplyState("idle");
|
|
979
|
+
},
|
|
980
|
+
multiline: true,
|
|
981
|
+
maxLength: 2e3,
|
|
982
|
+
editable: replyState !== "sending",
|
|
983
|
+
accessibilityLabel: t.flows.thread.replyPlaceholder
|
|
984
|
+
}
|
|
985
|
+
),
|
|
986
|
+
/* @__PURE__ */ jsx(
|
|
987
|
+
TouchableOpacity,
|
|
988
|
+
{
|
|
989
|
+
style: [
|
|
990
|
+
s.sendBtn,
|
|
991
|
+
{
|
|
992
|
+
backgroundColor: replyText.trim() && replyState !== "sending" ? colors.accent : colors.disabled,
|
|
993
|
+
borderRadius: radius
|
|
994
|
+
}
|
|
995
|
+
],
|
|
996
|
+
onPress: () => void sendReply(),
|
|
997
|
+
disabled: !replyText.trim() || replyState === "sending",
|
|
998
|
+
accessibilityRole: "button",
|
|
999
|
+
accessibilityLabel: replyState === "failed" ? rc.ui.retry : t.flows.thread.send,
|
|
1000
|
+
accessibilityState: { disabled: !replyText.trim() || replyState === "sending", busy: replyState === "sending" },
|
|
1001
|
+
children: /* @__PURE__ */ jsx(
|
|
1002
|
+
Text,
|
|
1003
|
+
{
|
|
1004
|
+
style: [
|
|
1005
|
+
s.submitText,
|
|
1006
|
+
{ color: replyText.trim() && replyState !== "sending" ? colors.accentFg : colors.disabledFg },
|
|
1007
|
+
font
|
|
1008
|
+
],
|
|
1009
|
+
children: replyState === "failed" ? rc.ui.retry : t.flows.thread.send
|
|
1010
|
+
}
|
|
1011
|
+
)
|
|
1012
|
+
}
|
|
1013
|
+
)
|
|
1014
|
+
] }),
|
|
1015
|
+
replyState === "failed" ? /* @__PURE__ */ jsxs(Text, { style: [{ color: colors.error, marginTop: 6, fontSize: 12 }, font], accessibilityRole: "alert", children: [
|
|
1016
|
+
rc.ui.sendFailed,
|
|
1017
|
+
" \xB7 ",
|
|
1018
|
+
rc.ui.retry
|
|
1019
|
+
] }) : null
|
|
1020
|
+
] });
|
|
1021
|
+
const renderInboxList = () => {
|
|
1022
|
+
if (inboxLoading && !inboxLoaded) {
|
|
1023
|
+
return /* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted }, font], children: t.flows.reports.loading });
|
|
1024
|
+
}
|
|
1025
|
+
if (inboxReports.length === 0) {
|
|
1026
|
+
return /* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted }, font], children: rc.ui.empty });
|
|
1027
|
+
}
|
|
1028
|
+
return inboxReports.map((r) => {
|
|
1029
|
+
const view = reporterStatus(r, locale);
|
|
1030
|
+
const unread = (r.unread_count ?? 0) > 0;
|
|
1031
|
+
const title = (r.title ?? r.summary ?? r.description ?? "Report").slice(0, 80);
|
|
1032
|
+
return /* @__PURE__ */ jsxs(
|
|
1033
|
+
TouchableOpacity,
|
|
1034
|
+
{
|
|
1035
|
+
style: [s.inboxRow, { borderColor: colors.border }],
|
|
1036
|
+
onPress: () => void openThread(r.id),
|
|
1037
|
+
accessibilityRole: "button",
|
|
1038
|
+
accessibilityLabel: `${view.label}. ${title}${unread ? `. ${r.unread_count} new` : ""}`,
|
|
1039
|
+
children: [
|
|
1040
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.fg, fontWeight: unread ? "700" : "600" }, font], numberOfLines: 1, children: title }),
|
|
1041
|
+
/* @__PURE__ */ jsxs(Text, { style: [{ color: unread ? colors.fg : colors.muted, fontSize: 12, marginTop: 2 }, font], numberOfLines: 1, children: [
|
|
1042
|
+
view.label,
|
|
1043
|
+
view.othersNote ? ` \xB7 ${view.othersNote}` : ""
|
|
1044
|
+
] }),
|
|
1045
|
+
unread && r.last_event_preview ? /* @__PURE__ */ jsx(Text, { style: [{ color: colors.fg, fontSize: 12, fontWeight: "700", marginTop: 2 }, font], numberOfLines: 1, children: r.last_event_preview }) : null
|
|
1046
|
+
]
|
|
1047
|
+
},
|
|
1048
|
+
r.id
|
|
1049
|
+
);
|
|
1050
|
+
});
|
|
1051
|
+
};
|
|
1052
|
+
return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "none", statusBarTranslucent: true, onRequestClose: handleClose, children: /* @__PURE__ */ jsxs(
|
|
744
1053
|
KeyboardAvoidingView,
|
|
745
1054
|
{
|
|
746
1055
|
style: s.flex,
|
|
@@ -751,44 +1060,69 @@ var MushiBottomSheet = ({
|
|
|
751
1060
|
Animated.View,
|
|
752
1061
|
{
|
|
753
1062
|
style: [s.backdrop, { backgroundColor: colors.backdrop, opacity: backdropOpacity }],
|
|
754
|
-
children: /* @__PURE__ */ jsx(
|
|
1063
|
+
children: /* @__PURE__ */ jsx(
|
|
1064
|
+
TouchableOpacity,
|
|
1065
|
+
{
|
|
1066
|
+
style: s.flex,
|
|
1067
|
+
activeOpacity: 1,
|
|
1068
|
+
onPress: handleClose,
|
|
1069
|
+
accessibilityRole: "button",
|
|
1070
|
+
accessibilityLabel: t.widget.close
|
|
1071
|
+
}
|
|
1072
|
+
)
|
|
755
1073
|
}
|
|
756
1074
|
),
|
|
757
1075
|
/* @__PURE__ */ jsxs(
|
|
758
1076
|
Animated.View,
|
|
759
1077
|
{
|
|
1078
|
+
accessibilityViewIsModal: true,
|
|
1079
|
+
onAccessibilityEscape: handleClose,
|
|
760
1080
|
style: [
|
|
761
1081
|
s.sheet,
|
|
762
1082
|
{ backgroundColor: colors.bg, transform: [{ translateY }] }
|
|
763
1083
|
],
|
|
764
1084
|
children: [
|
|
765
|
-
/* @__PURE__ */ jsx(
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
1085
|
+
/* @__PURE__ */ jsx(
|
|
1086
|
+
View,
|
|
1087
|
+
{
|
|
1088
|
+
...panResponder.panHandlers,
|
|
1089
|
+
style: s.handleArea,
|
|
1090
|
+
accessible: true,
|
|
1091
|
+
accessibilityRole: "adjustable",
|
|
1092
|
+
accessibilityLabel: t.widget.close,
|
|
1093
|
+
accessibilityActions: [{ name: "decrement", label: t.widget.close }, { name: "escape" }],
|
|
1094
|
+
onAccessibilityAction: (e) => {
|
|
1095
|
+
if (e.nativeEvent.actionName === "decrement" || e.nativeEvent.actionName === "escape") handleClose();
|
|
1096
|
+
},
|
|
1097
|
+
children: /* @__PURE__ */ jsx(View, { style: [s.handle, { backgroundColor: colors.muted }] })
|
|
1098
|
+
}
|
|
1099
|
+
),
|
|
1100
|
+
/* @__PURE__ */ jsx(View, { style: [s.header, { borderBottomColor: colors.border }], children: /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: [s.headerTitle, { color: colors.fg }, font], children: headerTitle }) }),
|
|
1101
|
+
/* @__PURE__ */ jsx(View, { style: [s.tabRow, { borderBottomColor: colors.border }], accessibilityRole: "tablist", children: sheetTabs.map((tab) => /* @__PURE__ */ jsx(
|
|
771
1102
|
TouchableOpacity,
|
|
772
1103
|
{
|
|
773
1104
|
onPress: () => {
|
|
774
1105
|
setSheetTab(tab);
|
|
775
|
-
if (tab === "inbox") void loadInbox();
|
|
776
|
-
else
|
|
1106
|
+
if (tab === "inbox") void loadInbox({ silent: inboxLoaded });
|
|
1107
|
+
else closeThread();
|
|
777
1108
|
},
|
|
778
1109
|
style: [s.tabBtn, sheetTab === tab && { borderBottomColor: colors.accent }],
|
|
779
|
-
|
|
1110
|
+
accessibilityRole: "tab",
|
|
1111
|
+
accessibilityState: { selected: sheetTab === tab },
|
|
1112
|
+
children: /* @__PURE__ */ jsx(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 })
|
|
780
1113
|
},
|
|
781
1114
|
tab
|
|
782
1115
|
)) }),
|
|
783
1116
|
sheetTab === "assistant" ? /* @__PURE__ */ jsxs(ScrollView, { style: s.body, keyboardShouldPersistTaps: "handled", children: [
|
|
784
1117
|
assistantTurns.length === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
785
|
-
/* @__PURE__ */ jsx(Text, { style: { color: colors.
|
|
1118
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted, marginBottom: 12, lineHeight: 20 }, font], children: greeting }),
|
|
786
1119
|
assistantSuggestions.map((chip) => /* @__PURE__ */ jsx(
|
|
787
1120
|
TouchableOpacity,
|
|
788
1121
|
{
|
|
789
|
-
style: [s.assistantChip, { borderColor: colors.border, backgroundColor: colors.
|
|
1122
|
+
style: [s.assistantChip, { borderColor: colors.border, backgroundColor: colors.surface }],
|
|
790
1123
|
onPress: () => void sendAssistant(chip),
|
|
791
|
-
|
|
1124
|
+
accessibilityRole: "button",
|
|
1125
|
+
children: /* @__PURE__ */ jsx(Text, { style: [{ color: colors.fg, fontSize: 13 }, font], children: chip })
|
|
792
1126
|
},
|
|
793
1127
|
chip
|
|
794
1128
|
))
|
|
@@ -799,25 +1133,34 @@ var MushiBottomSheet = ({
|
|
|
799
1133
|
s.assistantBubble,
|
|
800
1134
|
{
|
|
801
1135
|
alignSelf: turn.role === "user" ? "flex-end" : "flex-start",
|
|
802
|
-
backgroundColor: turn.role === "user" ? colors.accent : colors.
|
|
1136
|
+
backgroundColor: turn.role === "user" ? colors.accent : colors.surface
|
|
803
1137
|
}
|
|
804
1138
|
],
|
|
805
1139
|
children: [
|
|
806
|
-
/* @__PURE__ */ jsx(Text, { style: { color: turn.role === "user" ? colors.
|
|
807
|
-
turn.options?.map((opt) => /* @__PURE__ */ jsx(
|
|
1140
|
+
/* @__PURE__ */ jsx(Text, { style: [{ color: turn.role === "user" ? colors.accentFg : colors.fg }, font], children: turn.text }),
|
|
1141
|
+
turn.options?.map((opt) => /* @__PURE__ */ jsx(
|
|
1142
|
+
TouchableOpacity,
|
|
1143
|
+
{
|
|
1144
|
+
onPress: () => void sendAssistant(opt),
|
|
1145
|
+
style: { marginTop: 8 },
|
|
1146
|
+
accessibilityRole: "button",
|
|
1147
|
+
children: /* @__PURE__ */ jsx(Text, { style: [{ color: colors.accent, fontSize: 12 }, font], children: opt })
|
|
1148
|
+
},
|
|
1149
|
+
opt
|
|
1150
|
+
))
|
|
808
1151
|
]
|
|
809
1152
|
},
|
|
810
1153
|
`${turn.role}-${idx}`
|
|
811
1154
|
)),
|
|
812
|
-
assistantSending ? /* @__PURE__ */ jsx(Text, { style: { color: colors.
|
|
813
|
-
assistantError ? /* @__PURE__ */ jsx(Text, { style: { color:
|
|
1155
|
+
assistantSending ? /* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted, marginTop: 8 }, font], accessibilityLiveRegion: "polite", children: t.assistant.thinking }) : null,
|
|
1156
|
+
assistantError ? /* @__PURE__ */ jsx(Text, { style: [{ color: colors.error, marginTop: 8 }, font], accessibilityRole: "alert", children: assistantError }) : null,
|
|
814
1157
|
/* @__PURE__ */ jsxs(View, { style: s.assistantComposer, children: [
|
|
815
1158
|
/* @__PURE__ */ jsx(
|
|
816
1159
|
TextInput,
|
|
817
1160
|
{
|
|
818
|
-
style: [s.input, { flex: 1, minHeight: 44, backgroundColor: colors.
|
|
1161
|
+
style: [s.input, { flex: 1, minHeight: 44, backgroundColor: colors.surface, color: colors.fg, borderColor: colors.border, borderRadius: radius }, font],
|
|
819
1162
|
placeholder: t.assistant.inputPlaceholder,
|
|
820
|
-
placeholderTextColor: colors.
|
|
1163
|
+
placeholderTextColor: colors.muted,
|
|
821
1164
|
value: assistantInput,
|
|
822
1165
|
onChangeText: setAssistantInput,
|
|
823
1166
|
editable: !assistantSending
|
|
@@ -826,45 +1169,19 @@ var MushiBottomSheet = ({
|
|
|
826
1169
|
/* @__PURE__ */ jsx(
|
|
827
1170
|
TouchableOpacity,
|
|
828
1171
|
{
|
|
829
|
-
style: [s.submitBtn, { backgroundColor: colors.accent, paddingHorizontal: 16 }],
|
|
1172
|
+
style: [s.submitBtn, { backgroundColor: colors.accent, paddingHorizontal: 16, borderRadius: radius }],
|
|
830
1173
|
onPress: () => void sendAssistant(assistantInput),
|
|
831
1174
|
disabled: !assistantInput.trim() || assistantSending,
|
|
832
|
-
|
|
1175
|
+
accessibilityRole: "button",
|
|
1176
|
+
accessibilityLabel: t.flows.thread.send,
|
|
1177
|
+
accessibilityState: { disabled: !assistantInput.trim() || assistantSending, busy: assistantSending },
|
|
1178
|
+
children: /* @__PURE__ */ jsx(Text, { style: [s.submitText, { color: colors.accentFg }], children: "\u2191" })
|
|
833
1179
|
}
|
|
834
1180
|
)
|
|
835
1181
|
] })
|
|
836
|
-
] }) : sheetTab === "inbox" ? /* @__PURE__ */ jsx(ScrollView, { style: s.body, keyboardShouldPersistTaps: "handled",
|
|
837
|
-
/* @__PURE__ */ jsx(TouchableOpacity, { onPress: () => setSelectedReportId(null), children: /* @__PURE__ */ jsxs(Text, { style: { color: colors.accent, marginBottom: 8 }, children: [
|
|
838
|
-
"\u2190 ",
|
|
839
|
-
t.widget.back
|
|
840
|
-
] }) }),
|
|
841
|
-
threadComments.map((c) => /* @__PURE__ */ jsxs(View, { style: [s.threadBubble, { backgroundColor: colors.card }], children: [
|
|
842
|
-
/* @__PURE__ */ jsx(Text, { style: { color: colors.sub, fontSize: 11 }, children: c.author_kind }),
|
|
843
|
-
/* @__PURE__ */ jsx(Text, { style: { color: colors.text }, children: c.body })
|
|
844
|
-
] }, c.id)),
|
|
845
|
-
VERIFIABLE_STATUSES.has(
|
|
846
|
-
inboxReports.find((r) => r.id === selectedReportId)?.status ?? ""
|
|
847
|
-
) && /* @__PURE__ */ jsxs(View, { style: s.verifyRow, children: [
|
|
848
|
-
/* @__PURE__ */ jsx(TouchableOpacity, { style: [s.verifyBtn, { backgroundColor: colors.accent }], onPress: () => submitFeedback("confirms"), children: /* @__PURE__ */ jsx(Text, { style: [s.submitText, { color: colors.accentInk }], children: t.flows.thread.confirmFixed }) }),
|
|
849
|
-
/* @__PURE__ */ jsx(TouchableOpacity, { style: [s.verifyBtn, { backgroundColor: colors.border }], onPress: () => submitFeedback("not_fixed"), children: /* @__PURE__ */ jsx(Text, { style: [s.submitText, { color: colors.text }], children: t.flows.thread.notFixed }) })
|
|
850
|
-
] }),
|
|
851
|
-
/* @__PURE__ */ jsx(
|
|
852
|
-
TextInput,
|
|
853
|
-
{
|
|
854
|
-
style: [s.input, { backgroundColor: colors.card, color: colors.text, borderColor: colors.border, minHeight: 48 }],
|
|
855
|
-
placeholder: t.flows.thread.replyPlaceholder,
|
|
856
|
-
placeholderTextColor: colors.sub,
|
|
857
|
-
value: replyText,
|
|
858
|
-
onChangeText: setReplyText
|
|
859
|
-
}
|
|
860
|
-
),
|
|
861
|
-
/* @__PURE__ */ jsx(TouchableOpacity, { style: [s.submitBtn, { backgroundColor: colors.accent }], onPress: sendReply, children: /* @__PURE__ */ jsx(Text, { style: [s.submitText, { color: colors.accentInk }], children: t.flows.thread.send }) })
|
|
862
|
-
] }) : inboxReports.map((r) => /* @__PURE__ */ jsxs(TouchableOpacity, { style: [s.inboxRow, { borderColor: colors.border }], onPress: () => openThread(r.id), children: [
|
|
863
|
-
/* @__PURE__ */ jsx(Text, { style: { color: colors.text, fontWeight: "600" }, numberOfLines: 1, children: (r.summary ?? r.description ?? "Report").slice(0, 60) }),
|
|
864
|
-
/* @__PURE__ */ jsx(Text, { style: { color: colors.sub, fontSize: 11 }, children: reporterStatusShort(r.status) })
|
|
865
|
-
] }, r.id)) }) : phase === "sent" ? /* @__PURE__ */ jsxs(View, { style: s.sentWrap, children: [
|
|
1182
|
+
] }) : sheetTab === "inbox" ? /* @__PURE__ */ jsx(ScrollView, { style: s.body, keyboardShouldPersistTaps: "handled", contentContainerStyle: { paddingBottom: 24 }, children: selectedReportId ? renderThread() : renderInboxList() }) : phase === "sent" ? /* @__PURE__ */ jsxs(View, { style: s.sentWrap, accessibilityLiveRegion: "polite", children: [
|
|
866
1183
|
/* @__PURE__ */ jsx(Text, { style: [s.sentEmoji], children: "\u2705" }),
|
|
867
|
-
/* @__PURE__ */ jsx(Text, { style: [s.sentText, { color: colors.
|
|
1184
|
+
/* @__PURE__ */ jsx(Text, { style: [s.sentText, { color: colors.fg }, font], children: t.widget.submitted })
|
|
868
1185
|
] }) : /* @__PURE__ */ jsxs(
|
|
869
1186
|
ScrollView,
|
|
870
1187
|
{
|
|
@@ -872,29 +1189,34 @@ var MushiBottomSheet = ({
|
|
|
872
1189
|
keyboardShouldPersistTaps: "handled",
|
|
873
1190
|
contentContainerStyle: { paddingBottom: 24 },
|
|
874
1191
|
children: [
|
|
875
|
-
/* @__PURE__ */ jsx(Text, { style: [s.stepLabel, { color: colors.
|
|
876
|
-
/* @__PURE__ */ jsx(View, { style: s.catRow, children: CATEGORY_KEYS.map((key) => {
|
|
1192
|
+
/* @__PURE__ */ jsx(Text, { style: [s.stepLabel, { color: colors.muted }, font], children: t.step1.heading }),
|
|
1193
|
+
/* @__PURE__ */ jsx(View, { style: s.catRow, accessibilityRole: "radiogroup", children: CATEGORY_KEYS.map((key) => {
|
|
877
1194
|
const active = category === key;
|
|
878
1195
|
return /* @__PURE__ */ jsxs(
|
|
879
1196
|
TouchableOpacity,
|
|
880
1197
|
{
|
|
881
1198
|
onPress: () => setCategory(key),
|
|
882
1199
|
activeOpacity: 0.7,
|
|
1200
|
+
accessibilityRole: "radio",
|
|
1201
|
+
accessibilityState: { selected: active, checked: active },
|
|
1202
|
+
accessibilityLabel: t.step1.categories[key],
|
|
883
1203
|
style: [
|
|
884
1204
|
s.catBtn,
|
|
885
1205
|
{
|
|
886
|
-
backgroundColor: active ? colors.accent : colors.
|
|
1206
|
+
backgroundColor: active ? colors.accent : colors.surface,
|
|
887
1207
|
borderColor: active ? colors.accent : colors.border
|
|
888
1208
|
}
|
|
889
1209
|
],
|
|
890
1210
|
children: [
|
|
891
|
-
/* @__PURE__ */ jsx(Text, { style: s.catEmoji, children: CATEGORY_EMOJI[key] }),
|
|
1211
|
+
/* @__PURE__ */ jsx(Text, { style: s.catEmoji, importantForAccessibility: "no", children: CATEGORY_EMOJI[key] }),
|
|
892
1212
|
/* @__PURE__ */ jsx(
|
|
893
1213
|
Text,
|
|
894
1214
|
{
|
|
1215
|
+
numberOfLines: 1,
|
|
895
1216
|
style: [
|
|
896
1217
|
s.catLabel,
|
|
897
|
-
{ color: active ? colors.
|
|
1218
|
+
{ color: active ? colors.accentFg : colors.fg },
|
|
1219
|
+
font
|
|
898
1220
|
],
|
|
899
1221
|
children: t.step1.categories[key]
|
|
900
1222
|
}
|
|
@@ -910,13 +1232,16 @@ var MushiBottomSheet = ({
|
|
|
910
1232
|
style: [
|
|
911
1233
|
s.input,
|
|
912
1234
|
{
|
|
913
|
-
backgroundColor: colors.
|
|
914
|
-
color: colors.
|
|
915
|
-
borderColor: colors.border
|
|
916
|
-
|
|
1235
|
+
backgroundColor: colors.surface,
|
|
1236
|
+
color: colors.fg,
|
|
1237
|
+
borderColor: colors.border,
|
|
1238
|
+
borderRadius: radius
|
|
1239
|
+
},
|
|
1240
|
+
font
|
|
917
1241
|
],
|
|
918
1242
|
placeholder: t.step3.descriptionPlaceholder,
|
|
919
|
-
placeholderTextColor: colors.
|
|
1243
|
+
placeholderTextColor: colors.muted,
|
|
1244
|
+
accessibilityLabel: t.step3.descriptionPlaceholder,
|
|
920
1245
|
multiline: true,
|
|
921
1246
|
textAlignVertical: "top",
|
|
922
1247
|
value: description,
|
|
@@ -929,19 +1254,19 @@ var MushiBottomSheet = ({
|
|
|
929
1254
|
maxLength: 4e3
|
|
930
1255
|
}
|
|
931
1256
|
),
|
|
932
|
-
submitError ? /* @__PURE__ */ jsx(Text, { style: { color: colors.
|
|
1257
|
+
submitError ? /* @__PURE__ */ jsx(Text, { style: [{ color: colors.error, marginTop: 6, fontSize: 12 }, font], accessibilityRole: "alert", children: submitError }) : null,
|
|
933
1258
|
activeScreenshot ? /* @__PURE__ */ jsxs(View, { style: s.screenshotRow, children: [
|
|
934
1259
|
/* @__PURE__ */ jsx(
|
|
935
1260
|
Image,
|
|
936
1261
|
{
|
|
937
1262
|
source: { uri: activeScreenshot },
|
|
938
|
-
style: [s.screenshotThumb, { backgroundColor: colors.
|
|
1263
|
+
style: [s.screenshotThumb, { backgroundColor: colors.fg }],
|
|
939
1264
|
accessibilityLabel: t.step3.screenshotPreviewAlt
|
|
940
1265
|
}
|
|
941
1266
|
),
|
|
942
1267
|
/* @__PURE__ */ jsxs(View, { style: s.screenshotMeta, children: [
|
|
943
|
-
/* @__PURE__ */ jsx(Text, { style: [s.screenshotLabel, { color: colors.
|
|
944
|
-
/* @__PURE__ */ jsx(Text, { style: [s.screenshotSub, { color: colors.
|
|
1268
|
+
/* @__PURE__ */ jsx(Text, { style: [s.screenshotLabel, { color: colors.fg }, font], children: t.step3.screenshotAttached.replace(" \u2713", "") }),
|
|
1269
|
+
/* @__PURE__ */ jsx(Text, { style: [s.screenshotSub, { color: colors.muted }, font], children: screenshotSensitiveHint && screenshotSensitiveHint.trim() ? `\u26A0 ${screenshotSensitiveHint}` : t.step3.screenshotSensitiveHint.split("\u2014")[0]?.trim() ?? t.step3.screenshotSensitiveHint })
|
|
945
1270
|
] }),
|
|
946
1271
|
/* @__PURE__ */ jsx(
|
|
947
1272
|
TouchableOpacity,
|
|
@@ -951,22 +1276,28 @@ var MushiBottomSheet = ({
|
|
|
951
1276
|
onClearScreenshot?.();
|
|
952
1277
|
},
|
|
953
1278
|
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
1279
|
+
accessibilityRole: "button",
|
|
954
1280
|
accessibilityLabel: t.widget.close,
|
|
955
|
-
children: /* @__PURE__ */ jsx(Text, { style: [s.screenshotRemove, { color: colors.
|
|
1281
|
+
children: /* @__PURE__ */ jsx(Text, { style: [s.screenshotRemove, { color: colors.muted }], children: "\u2715" })
|
|
956
1282
|
}
|
|
957
1283
|
)
|
|
958
1284
|
] }) : null,
|
|
1285
|
+
submitHint ? /* @__PURE__ */ jsx(Text, { style: [{ color: colors.muted, fontSize: 12, marginBottom: 6 }, font], children: submitHint }) : null,
|
|
959
1286
|
/* @__PURE__ */ jsx(
|
|
960
1287
|
TouchableOpacity,
|
|
961
1288
|
{
|
|
962
1289
|
onPress: handleSubmit,
|
|
963
1290
|
disabled: !canSubmit,
|
|
964
1291
|
activeOpacity: 0.8,
|
|
1292
|
+
accessibilityRole: "button",
|
|
1293
|
+
accessibilityLabel: phase === "sending" ? t.widget.submitting : t.widget.submit,
|
|
1294
|
+
accessibilityHint: submitHint,
|
|
1295
|
+
accessibilityState: { disabled: !canSubmit, busy: phase === "sending" },
|
|
965
1296
|
style: [
|
|
966
1297
|
s.submitBtn,
|
|
967
|
-
{ backgroundColor: canSubmit ? colors.accent : colors.disabled }
|
|
1298
|
+
{ backgroundColor: canSubmit ? colors.accent : colors.disabled, borderRadius: radius }
|
|
968
1299
|
],
|
|
969
|
-
children: /* @__PURE__ */ jsx(Text, { style: [s.submitText, { color: canSubmit ? colors.
|
|
1300
|
+
children: /* @__PURE__ */ jsx(Text, { style: [s.submitText, { color: canSubmit ? colors.accentFg : colors.disabledFg }, font], children: phase === "sending" ? t.widget.submitting : t.widget.submit })
|
|
970
1301
|
}
|
|
971
1302
|
)
|
|
972
1303
|
]
|
|
@@ -996,8 +1327,8 @@ var s = StyleSheet.create({
|
|
|
996
1327
|
left: 0,
|
|
997
1328
|
right: 0,
|
|
998
1329
|
minHeight: SHEET_HEIGHT,
|
|
999
|
-
borderTopLeftRadius:
|
|
1000
|
-
borderTopRightRadius:
|
|
1330
|
+
borderTopLeftRadius: MUSHI_RADIUS2.sheet,
|
|
1331
|
+
borderTopRightRadius: MUSHI_RADIUS2.sheet,
|
|
1001
1332
|
paddingBottom: Platform2.OS === "ios" ? 34 : MUSHI_SPACING.roomy,
|
|
1002
1333
|
shadowColor: MUSHI_SHADOW_INK,
|
|
1003
1334
|
shadowOffset: { width: 0, height: -3 },
|
|
@@ -1012,36 +1343,22 @@ var s = StyleSheet.create({
|
|
|
1012
1343
|
handle: {
|
|
1013
1344
|
width: 40,
|
|
1014
1345
|
height: 5,
|
|
1015
|
-
borderRadius:
|
|
1346
|
+
borderRadius: MUSHI_RADIUS2.control,
|
|
1016
1347
|
opacity: 0.5
|
|
1017
1348
|
},
|
|
1018
|
-
|
|
1349
|
+
header: {
|
|
1019
1350
|
paddingHorizontal: MUSHI_SPACING.lounge,
|
|
1020
|
-
|
|
1021
|
-
paddingBottom: MUSHI_SPACING.comfy,
|
|
1022
|
-
borderBottomWidth: 1.5
|
|
1023
|
-
},
|
|
1024
|
-
brandEyebrow: {
|
|
1025
|
-
fontSize: MUSHI_TYPE.sizeLabel,
|
|
1026
|
-
fontWeight: "700",
|
|
1027
|
-
letterSpacing: 1.2,
|
|
1028
|
-
marginBottom: 2,
|
|
1029
|
-
opacity: 0.7
|
|
1351
|
+
paddingBottom: MUSHI_SPACING.comfy
|
|
1030
1352
|
},
|
|
1031
|
-
|
|
1353
|
+
headerTitle: {
|
|
1032
1354
|
fontSize: 18,
|
|
1033
|
-
fontWeight: "
|
|
1355
|
+
fontWeight: "700",
|
|
1034
1356
|
letterSpacing: -0.2
|
|
1035
1357
|
},
|
|
1036
1358
|
body: {
|
|
1037
1359
|
paddingHorizontal: MUSHI_SPACING.lounge,
|
|
1038
1360
|
paddingTop: MUSHI_SPACING.tight
|
|
1039
1361
|
},
|
|
1040
|
-
title: {
|
|
1041
|
-
fontSize: 20,
|
|
1042
|
-
fontWeight: "700",
|
|
1043
|
-
marginBottom: MUSHI_SPACING.roomy
|
|
1044
|
-
},
|
|
1045
1362
|
stepLabel: {
|
|
1046
1363
|
fontSize: MUSHI_TYPE.sizeLabel,
|
|
1047
1364
|
fontWeight: "600",
|
|
@@ -1052,37 +1369,35 @@ var s = StyleSheet.create({
|
|
|
1052
1369
|
},
|
|
1053
1370
|
catRow: {
|
|
1054
1371
|
flexDirection: "row",
|
|
1055
|
-
|
|
1372
|
+
flexWrap: "wrap",
|
|
1373
|
+
gap: 8,
|
|
1056
1374
|
marginBottom: MUSHI_SPACING.roomy
|
|
1057
1375
|
},
|
|
1058
1376
|
catBtn: {
|
|
1377
|
+
flexDirection: "row",
|
|
1059
1378
|
alignItems: "center",
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1379
|
+
gap: 6,
|
|
1380
|
+
paddingVertical: 8,
|
|
1381
|
+
paddingHorizontal: 12,
|
|
1382
|
+
borderRadius: 999,
|
|
1063
1383
|
borderWidth: 1,
|
|
1064
|
-
flex: 1,
|
|
1065
|
-
marginHorizontal: 3,
|
|
1066
1384
|
minHeight: 44
|
|
1067
1385
|
},
|
|
1068
1386
|
catEmoji: {
|
|
1069
|
-
fontSize:
|
|
1070
|
-
marginBottom: MUSHI_SPACING.tight
|
|
1387
|
+
fontSize: 16
|
|
1071
1388
|
},
|
|
1072
1389
|
catLabel: {
|
|
1073
|
-
fontSize:
|
|
1390
|
+
fontSize: 14,
|
|
1074
1391
|
fontWeight: "600"
|
|
1075
1392
|
},
|
|
1076
1393
|
input: {
|
|
1077
1394
|
borderWidth: 1,
|
|
1078
|
-
borderRadius: MUSHI_RADIUS.card,
|
|
1079
1395
|
padding: 14,
|
|
1080
1396
|
fontSize: 15,
|
|
1081
1397
|
minHeight: 100,
|
|
1082
1398
|
marginBottom: MUSHI_SPACING.roomy
|
|
1083
1399
|
},
|
|
1084
1400
|
submitBtn: {
|
|
1085
|
-
borderRadius: MUSHI_RADIUS.card,
|
|
1086
1401
|
paddingVertical: 14,
|
|
1087
1402
|
alignItems: "center",
|
|
1088
1403
|
minHeight: 44
|
|
@@ -1147,7 +1462,8 @@ var s = StyleSheet.create({
|
|
|
1147
1462
|
alignItems: "center",
|
|
1148
1463
|
paddingVertical: 10,
|
|
1149
1464
|
borderBottomWidth: 2,
|
|
1150
|
-
borderBottomColor: "transparent"
|
|
1465
|
+
borderBottomColor: "transparent",
|
|
1466
|
+
minHeight: 44
|
|
1151
1467
|
},
|
|
1152
1468
|
tabLabel: {
|
|
1153
1469
|
fontSize: 14,
|
|
@@ -1155,12 +1471,47 @@ var s = StyleSheet.create({
|
|
|
1155
1471
|
},
|
|
1156
1472
|
inboxRow: {
|
|
1157
1473
|
paddingVertical: 12,
|
|
1474
|
+
minHeight: 56,
|
|
1158
1475
|
borderBottomWidth: StyleSheet.hairlineWidth
|
|
1159
1476
|
},
|
|
1477
|
+
headerCard: {
|
|
1478
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
1479
|
+
padding: 12,
|
|
1480
|
+
marginBottom: 12
|
|
1481
|
+
},
|
|
1482
|
+
pill: {
|
|
1483
|
+
alignSelf: "flex-start",
|
|
1484
|
+
borderWidth: 1,
|
|
1485
|
+
borderRadius: 999,
|
|
1486
|
+
paddingHorizontal: 8,
|
|
1487
|
+
paddingVertical: 2,
|
|
1488
|
+
fontSize: 12,
|
|
1489
|
+
fontWeight: "600",
|
|
1490
|
+
overflow: "hidden"
|
|
1491
|
+
},
|
|
1492
|
+
skeleton: {
|
|
1493
|
+
height: 14,
|
|
1494
|
+
borderRadius: 6,
|
|
1495
|
+
marginBottom: 10
|
|
1496
|
+
},
|
|
1497
|
+
errorRow: {
|
|
1498
|
+
flexDirection: "row",
|
|
1499
|
+
alignItems: "center",
|
|
1500
|
+
gap: 8,
|
|
1501
|
+
marginBottom: 12
|
|
1502
|
+
},
|
|
1503
|
+
retryBtn: {
|
|
1504
|
+
borderWidth: 1,
|
|
1505
|
+
paddingHorizontal: 12,
|
|
1506
|
+
paddingVertical: 8,
|
|
1507
|
+
minHeight: 44,
|
|
1508
|
+
justifyContent: "center"
|
|
1509
|
+
},
|
|
1160
1510
|
threadBubble: {
|
|
1161
1511
|
borderRadius: 10,
|
|
1162
1512
|
padding: 10,
|
|
1163
|
-
marginBottom: 8
|
|
1513
|
+
marginBottom: 8,
|
|
1514
|
+
maxWidth: "88%"
|
|
1164
1515
|
},
|
|
1165
1516
|
verifyRow: {
|
|
1166
1517
|
flexDirection: "row",
|
|
@@ -1169,9 +1520,26 @@ var s = StyleSheet.create({
|
|
|
1169
1520
|
},
|
|
1170
1521
|
verifyBtn: {
|
|
1171
1522
|
flex: 1,
|
|
1172
|
-
borderRadius: 10,
|
|
1173
1523
|
paddingVertical: 10,
|
|
1174
|
-
alignItems: "center"
|
|
1524
|
+
alignItems: "center",
|
|
1525
|
+
minHeight: 44
|
|
1526
|
+
},
|
|
1527
|
+
composer: {
|
|
1528
|
+
flexDirection: "row",
|
|
1529
|
+
alignItems: "flex-end",
|
|
1530
|
+
gap: 8
|
|
1531
|
+
},
|
|
1532
|
+
composerInput: {
|
|
1533
|
+
flex: 1,
|
|
1534
|
+
minHeight: 44,
|
|
1535
|
+
maxHeight: 120,
|
|
1536
|
+
marginBottom: 0
|
|
1537
|
+
},
|
|
1538
|
+
sendBtn: {
|
|
1539
|
+
paddingHorizontal: 16,
|
|
1540
|
+
paddingVertical: 12,
|
|
1541
|
+
minHeight: 44,
|
|
1542
|
+
justifyContent: "center"
|
|
1175
1543
|
},
|
|
1176
1544
|
assistantBubble: {
|
|
1177
1545
|
maxWidth: "88%",
|
|
@@ -1401,7 +1769,7 @@ import {
|
|
|
1401
1769
|
StyleSheet as StyleSheet3,
|
|
1402
1770
|
Platform as Platform4
|
|
1403
1771
|
} from "react-native";
|
|
1404
|
-
import { MUSHI_BANNER_NEON
|
|
1772
|
+
import { MUSHI_BANNER_NEON, MUSHI_COPY as MUSHI_COPY3, MUSHI_GEOMETRY as MUSHI_GEOMETRY2, MUSHI_SPACING as MUSHI_SPACING2, MUSHI_TYPE as MUSHI_TYPE2, MUSHI_Z } from "@mushi-mushi/core";
|
|
1405
1773
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1406
1774
|
var MUSHI_BANNER_DEFAULT_HEIGHT = MUSHI_GEOMETRY2.bannerHeight;
|
|
1407
1775
|
var MushiBanner = ({
|
|
@@ -1454,9 +1822,9 @@ var s3 = StyleSheet3.create({
|
|
|
1454
1822
|
minHeight: MUSHI_GEOMETRY2.bannerHeight,
|
|
1455
1823
|
flexDirection: "row",
|
|
1456
1824
|
alignItems: "stretch",
|
|
1457
|
-
backgroundColor:
|
|
1825
|
+
backgroundColor: MUSHI_BANNER_NEON.bg,
|
|
1458
1826
|
borderTopWidth: 1,
|
|
1459
|
-
borderTopColor:
|
|
1827
|
+
borderTopColor: MUSHI_BANNER_NEON.border,
|
|
1460
1828
|
zIndex: MUSHI_Z.banner,
|
|
1461
1829
|
elevation: 8,
|
|
1462
1830
|
paddingBottom: Platform4.OS === "ios" ? 0 : 0
|
|
@@ -1474,18 +1842,18 @@ var s3 = StyleSheet3.create({
|
|
|
1474
1842
|
fontSize: MUSHI_TYPE2.sizeLabel,
|
|
1475
1843
|
fontWeight: "700",
|
|
1476
1844
|
letterSpacing: 1.2,
|
|
1477
|
-
color:
|
|
1845
|
+
color: MUSHI_BANNER_NEON.fg
|
|
1478
1846
|
},
|
|
1479
1847
|
message: {
|
|
1480
1848
|
flex: 1,
|
|
1481
1849
|
fontSize: 12,
|
|
1482
1850
|
fontWeight: "500",
|
|
1483
|
-
color:
|
|
1851
|
+
color: MUSHI_BANNER_NEON.fg
|
|
1484
1852
|
},
|
|
1485
1853
|
cta: {
|
|
1486
1854
|
fontSize: 12,
|
|
1487
1855
|
fontWeight: "700",
|
|
1488
|
-
color:
|
|
1856
|
+
color: MUSHI_BANNER_NEON.fg,
|
|
1489
1857
|
textDecorationLine: "underline"
|
|
1490
1858
|
},
|
|
1491
1859
|
dismiss: {
|
|
@@ -1495,7 +1863,7 @@ var s3 = StyleSheet3.create({
|
|
|
1495
1863
|
dismissText: {
|
|
1496
1864
|
fontSize: 20,
|
|
1497
1865
|
lineHeight: 22,
|
|
1498
|
-
color:
|
|
1866
|
+
color: MUSHI_BANNER_NEON.fg,
|
|
1499
1867
|
opacity: 0.7
|
|
1500
1868
|
}
|
|
1501
1869
|
});
|
|
@@ -1825,7 +2193,7 @@ function createRNSessionTracker(opts) {
|
|
|
1825
2193
|
|
|
1826
2194
|
// src/version.ts
|
|
1827
2195
|
var MUSHI_SDK_PACKAGE = "@mushi-mushi/react-native";
|
|
1828
|
-
var MUSHI_SDK_VERSION = "0.
|
|
2196
|
+
var MUSHI_SDK_VERSION = "0.23.0" ? "0.23.0" : "0.17.0";
|
|
1829
2197
|
|
|
1830
2198
|
// src/provider.tsx
|
|
1831
2199
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -2320,6 +2688,23 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2320
2688
|
const res = await client.listReporterComments(reportId, reporterTokenRef.current);
|
|
2321
2689
|
return res.ok ? res.data.comments ?? [] : [];
|
|
2322
2690
|
},
|
|
2691
|
+
async loadMyThread(reportId) {
|
|
2692
|
+
const client = apiClientRef.current;
|
|
2693
|
+
if (!client) return null;
|
|
2694
|
+
try {
|
|
2695
|
+
await reporterTokenReadyRef.current;
|
|
2696
|
+
const res = await client.listReporterComments(reportId, reporterTokenRef.current);
|
|
2697
|
+
return res.ok ? res.data?.comments ?? [] : null;
|
|
2698
|
+
} catch {
|
|
2699
|
+
return null;
|
|
2700
|
+
}
|
|
2701
|
+
},
|
|
2702
|
+
async markReportRead(reportId) {
|
|
2703
|
+
const client = apiClientRef.current;
|
|
2704
|
+
if (!client) return 0;
|
|
2705
|
+
await reporterTokenReadyRef.current;
|
|
2706
|
+
return markReporterReportRead(client, reporterTokenRef.current, reportId);
|
|
2707
|
+
},
|
|
2323
2708
|
async replyToReport(reportId, body) {
|
|
2324
2709
|
const client = apiClientRef.current;
|
|
2325
2710
|
if (!client) return null;
|
|
@@ -2427,7 +2812,8 @@ function MushiProvider({ children, config: configProp, ...barePropConfig }) {
|
|
|
2427
2812
|
assistantLabel: config.assistant?.label,
|
|
2428
2813
|
assistantGreeting: config.assistant?.greeting,
|
|
2429
2814
|
assistantSuggestions: config.assistant?.suggestions,
|
|
2430
|
-
inboxPollIntervalMs: config.widget?.inboxPollIntervalMs ?? 0
|
|
2815
|
+
inboxPollIntervalMs: config.widget?.inboxPollIntervalMs ?? 0,
|
|
2816
|
+
theme: config.widget?.theme
|
|
2431
2817
|
}
|
|
2432
2818
|
)
|
|
2433
2819
|
] });
|