@mushi-mushi/react-native 0.1.0 → 0.2.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 +23 -4
- package/dist/index.cjs +454 -40
- package/dist/index.d.cts +71 -4
- package/dist/index.d.ts +71 -4
- package/dist/index.js +482 -38
- package/package.json +76 -73
package/dist/index.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
// src/provider.tsx
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
createContext,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect as useEffect2,
|
|
6
|
+
useRef as useRef3,
|
|
7
|
+
useState as useState2,
|
|
8
|
+
useCallback as useCallback3,
|
|
9
|
+
useMemo
|
|
10
|
+
} from "react";
|
|
11
|
+
import { createApiClient, DEFAULT_API_ENDPOINT } from "@mushi-mushi/core";
|
|
3
12
|
|
|
4
13
|
// src/capture/console-capture.ts
|
|
5
14
|
function setupConsoleCapture(maxEntries = 100) {
|
|
@@ -174,60 +183,493 @@ var AsyncStorageQueue = class {
|
|
|
174
183
|
}
|
|
175
184
|
};
|
|
176
185
|
|
|
186
|
+
// src/components/MushiBottomSheet.tsx
|
|
187
|
+
import {
|
|
188
|
+
useRef,
|
|
189
|
+
useState,
|
|
190
|
+
useEffect,
|
|
191
|
+
useCallback
|
|
192
|
+
} from "react";
|
|
193
|
+
import {
|
|
194
|
+
Modal,
|
|
195
|
+
View,
|
|
196
|
+
Text,
|
|
197
|
+
TextInput,
|
|
198
|
+
TouchableOpacity,
|
|
199
|
+
Animated,
|
|
200
|
+
PanResponder,
|
|
201
|
+
StyleSheet,
|
|
202
|
+
Dimensions as Dimensions2,
|
|
203
|
+
Platform as Platform2,
|
|
204
|
+
KeyboardAvoidingView,
|
|
205
|
+
useColorScheme
|
|
206
|
+
} from "react-native";
|
|
207
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
208
|
+
var { height: SCREEN_HEIGHT } = Dimensions2.get("window");
|
|
209
|
+
var SHEET_HEIGHT = SCREEN_HEIGHT * 0.55;
|
|
210
|
+
var DISMISS_THRESHOLD = 80;
|
|
211
|
+
var CATEGORIES = [
|
|
212
|
+
{ key: "bug", emoji: "\u{1F41B}", label: "Bug" },
|
|
213
|
+
{ key: "slow", emoji: "\u{1F422}", label: "Slow" },
|
|
214
|
+
{ key: "visual", emoji: "\u{1F3A8}", label: "Visual" },
|
|
215
|
+
{ key: "confusing", emoji: "\u{1F615}", label: "Confusing" },
|
|
216
|
+
{ key: "other", emoji: "\u{1F4AC}", label: "Other" }
|
|
217
|
+
];
|
|
218
|
+
var MushiBottomSheet = ({ visible, onClose }) => {
|
|
219
|
+
const mushi = useMushiContext();
|
|
220
|
+
const scheme = useColorScheme();
|
|
221
|
+
const dark = scheme === "dark";
|
|
222
|
+
const translateY = useRef(new Animated.Value(SHEET_HEIGHT)).current;
|
|
223
|
+
const backdropOpacity = useRef(new Animated.Value(0)).current;
|
|
224
|
+
const [category, setCategory] = useState(null);
|
|
225
|
+
const [description, setDescription] = useState("");
|
|
226
|
+
const [phase, setPhase] = useState("form");
|
|
227
|
+
const resetForm = useCallback(() => {
|
|
228
|
+
setCategory(null);
|
|
229
|
+
setDescription("");
|
|
230
|
+
setPhase("form");
|
|
231
|
+
}, []);
|
|
232
|
+
const animateIn = useCallback(() => {
|
|
233
|
+
Animated.parallel([
|
|
234
|
+
Animated.spring(translateY, {
|
|
235
|
+
toValue: 0,
|
|
236
|
+
useNativeDriver: true,
|
|
237
|
+
damping: 20,
|
|
238
|
+
stiffness: 200
|
|
239
|
+
}),
|
|
240
|
+
Animated.timing(backdropOpacity, {
|
|
241
|
+
toValue: 1,
|
|
242
|
+
duration: 250,
|
|
243
|
+
useNativeDriver: true
|
|
244
|
+
})
|
|
245
|
+
]).start();
|
|
246
|
+
}, [translateY, backdropOpacity]);
|
|
247
|
+
const animateOut = useCallback(
|
|
248
|
+
(cb) => {
|
|
249
|
+
Animated.parallel([
|
|
250
|
+
Animated.timing(translateY, {
|
|
251
|
+
toValue: SHEET_HEIGHT,
|
|
252
|
+
duration: 220,
|
|
253
|
+
useNativeDriver: true
|
|
254
|
+
}),
|
|
255
|
+
Animated.timing(backdropOpacity, {
|
|
256
|
+
toValue: 0,
|
|
257
|
+
duration: 200,
|
|
258
|
+
useNativeDriver: true
|
|
259
|
+
})
|
|
260
|
+
]).start(() => {
|
|
261
|
+
resetForm();
|
|
262
|
+
cb?.();
|
|
263
|
+
});
|
|
264
|
+
},
|
|
265
|
+
[translateY, backdropOpacity, resetForm]
|
|
266
|
+
);
|
|
267
|
+
useEffect(() => {
|
|
268
|
+
if (visible) animateIn();
|
|
269
|
+
}, [visible, animateIn]);
|
|
270
|
+
const handleClose = useCallback(() => {
|
|
271
|
+
animateOut(onClose);
|
|
272
|
+
}, [animateOut, onClose]);
|
|
273
|
+
const panResponder = useRef(
|
|
274
|
+
PanResponder.create({
|
|
275
|
+
onStartShouldSetPanResponder: () => true,
|
|
276
|
+
onMoveShouldSetPanResponder: (_, g) => g.dy > 4,
|
|
277
|
+
onPanResponderMove: (_, g) => {
|
|
278
|
+
if (g.dy > 0) translateY.setValue(g.dy);
|
|
279
|
+
},
|
|
280
|
+
onPanResponderRelease: (_, g) => {
|
|
281
|
+
if (g.dy > DISMISS_THRESHOLD) {
|
|
282
|
+
handleClose();
|
|
283
|
+
} else {
|
|
284
|
+
Animated.spring(translateY, {
|
|
285
|
+
toValue: 0,
|
|
286
|
+
useNativeDriver: true,
|
|
287
|
+
damping: 20,
|
|
288
|
+
stiffness: 200
|
|
289
|
+
}).start();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
).current;
|
|
294
|
+
const handleSubmit = async () => {
|
|
295
|
+
if (!category || !description.trim() || !mushi) return;
|
|
296
|
+
setPhase("sending");
|
|
297
|
+
try {
|
|
298
|
+
await mushi.submitReport({ category, description: description.trim() });
|
|
299
|
+
setPhase("sent");
|
|
300
|
+
setTimeout(handleClose, 1400);
|
|
301
|
+
} catch {
|
|
302
|
+
setPhase("form");
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
const colors = dark ? { bg: "#1c1c1e", text: "#f2f2f7", sub: "#8e8e93", card: "#2c2c2e", accent: "#0a84ff", border: "#38383a", backdrop: "rgba(0,0,0,0.6)" } : { bg: "#ffffff", text: "#1c1c1e", sub: "#8e8e93", card: "#f2f2f7", accent: "#007aff", border: "#e5e5ea", backdrop: "rgba(0,0,0,0.35)" };
|
|
306
|
+
const canSubmit = !!category && description.trim().length > 0 && phase === "form";
|
|
307
|
+
return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "none", statusBarTranslucent: true, children: /* @__PURE__ */ jsxs(
|
|
308
|
+
KeyboardAvoidingView,
|
|
309
|
+
{
|
|
310
|
+
style: s.flex,
|
|
311
|
+
behavior: Platform2.OS === "ios" ? "padding" : void 0,
|
|
312
|
+
children: [
|
|
313
|
+
/* @__PURE__ */ jsx(
|
|
314
|
+
Animated.View,
|
|
315
|
+
{
|
|
316
|
+
style: [s.backdrop, { backgroundColor: colors.backdrop, opacity: backdropOpacity }],
|
|
317
|
+
children: /* @__PURE__ */ jsx(TouchableOpacity, { style: s.flex, activeOpacity: 1, onPress: handleClose })
|
|
318
|
+
}
|
|
319
|
+
),
|
|
320
|
+
/* @__PURE__ */ jsxs(
|
|
321
|
+
Animated.View,
|
|
322
|
+
{
|
|
323
|
+
style: [
|
|
324
|
+
s.sheet,
|
|
325
|
+
{ backgroundColor: colors.bg, transform: [{ translateY }] }
|
|
326
|
+
],
|
|
327
|
+
children: [
|
|
328
|
+
/* @__PURE__ */ jsx(View, { ...panResponder.panHandlers, style: s.handleArea, children: /* @__PURE__ */ jsx(View, { style: [s.handle, { backgroundColor: colors.sub }] }) }),
|
|
329
|
+
phase === "sent" ? /* @__PURE__ */ jsxs(View, { style: s.sentWrap, children: [
|
|
330
|
+
/* @__PURE__ */ jsx(Text, { style: [s.sentEmoji], children: "\u2705" }),
|
|
331
|
+
/* @__PURE__ */ jsx(Text, { style: [s.sentText, { color: colors.text }], children: "Report sent!" })
|
|
332
|
+
] }) : /* @__PURE__ */ jsxs(View, { style: s.body, children: [
|
|
333
|
+
/* @__PURE__ */ jsx(Text, { style: [s.title, { color: colors.text }], children: "Report an issue" }),
|
|
334
|
+
/* @__PURE__ */ jsx(View, { style: s.catRow, children: CATEGORIES.map((c) => {
|
|
335
|
+
const active = category === c.key;
|
|
336
|
+
return /* @__PURE__ */ jsxs(
|
|
337
|
+
TouchableOpacity,
|
|
338
|
+
{
|
|
339
|
+
onPress: () => setCategory(c.key),
|
|
340
|
+
activeOpacity: 0.7,
|
|
341
|
+
style: [
|
|
342
|
+
s.catBtn,
|
|
343
|
+
{
|
|
344
|
+
backgroundColor: active ? colors.accent : colors.card,
|
|
345
|
+
borderColor: active ? colors.accent : colors.border
|
|
346
|
+
}
|
|
347
|
+
],
|
|
348
|
+
children: [
|
|
349
|
+
/* @__PURE__ */ jsx(Text, { style: s.catEmoji, children: c.emoji }),
|
|
350
|
+
/* @__PURE__ */ jsx(
|
|
351
|
+
Text,
|
|
352
|
+
{
|
|
353
|
+
style: [
|
|
354
|
+
s.catLabel,
|
|
355
|
+
{ color: active ? "#fff" : colors.text }
|
|
356
|
+
],
|
|
357
|
+
children: c.label
|
|
358
|
+
}
|
|
359
|
+
)
|
|
360
|
+
]
|
|
361
|
+
},
|
|
362
|
+
c.key
|
|
363
|
+
);
|
|
364
|
+
}) }),
|
|
365
|
+
/* @__PURE__ */ jsx(
|
|
366
|
+
TextInput,
|
|
367
|
+
{
|
|
368
|
+
style: [
|
|
369
|
+
s.input,
|
|
370
|
+
{
|
|
371
|
+
backgroundColor: colors.card,
|
|
372
|
+
color: colors.text,
|
|
373
|
+
borderColor: colors.border
|
|
374
|
+
}
|
|
375
|
+
],
|
|
376
|
+
placeholder: "What happened?",
|
|
377
|
+
placeholderTextColor: colors.sub,
|
|
378
|
+
multiline: true,
|
|
379
|
+
textAlignVertical: "top",
|
|
380
|
+
value: description,
|
|
381
|
+
onChangeText: setDescription,
|
|
382
|
+
editable: phase === "form"
|
|
383
|
+
}
|
|
384
|
+
),
|
|
385
|
+
/* @__PURE__ */ jsx(
|
|
386
|
+
TouchableOpacity,
|
|
387
|
+
{
|
|
388
|
+
onPress: handleSubmit,
|
|
389
|
+
disabled: !canSubmit,
|
|
390
|
+
activeOpacity: 0.8,
|
|
391
|
+
style: [
|
|
392
|
+
s.submitBtn,
|
|
393
|
+
{ backgroundColor: canSubmit ? colors.accent : colors.border }
|
|
394
|
+
],
|
|
395
|
+
children: /* @__PURE__ */ jsx(Text, { style: s.submitText, children: phase === "sending" ? "Sending\u2026" : "Submit" })
|
|
396
|
+
}
|
|
397
|
+
)
|
|
398
|
+
] })
|
|
399
|
+
]
|
|
400
|
+
}
|
|
401
|
+
)
|
|
402
|
+
]
|
|
403
|
+
}
|
|
404
|
+
) });
|
|
405
|
+
};
|
|
406
|
+
var s = StyleSheet.create({
|
|
407
|
+
flex: { flex: 1 },
|
|
408
|
+
backdrop: {
|
|
409
|
+
...StyleSheet.absoluteFillObject
|
|
410
|
+
},
|
|
411
|
+
sheet: {
|
|
412
|
+
position: "absolute",
|
|
413
|
+
bottom: 0,
|
|
414
|
+
left: 0,
|
|
415
|
+
right: 0,
|
|
416
|
+
minHeight: SHEET_HEIGHT,
|
|
417
|
+
borderTopLeftRadius: 20,
|
|
418
|
+
borderTopRightRadius: 20,
|
|
419
|
+
paddingBottom: Platform2.OS === "ios" ? 34 : 16,
|
|
420
|
+
shadowColor: "#000",
|
|
421
|
+
shadowOffset: { width: 0, height: -3 },
|
|
422
|
+
shadowOpacity: 0.12,
|
|
423
|
+
shadowRadius: 8,
|
|
424
|
+
elevation: 24
|
|
425
|
+
},
|
|
426
|
+
handleArea: {
|
|
427
|
+
alignItems: "center",
|
|
428
|
+
paddingVertical: 10
|
|
429
|
+
},
|
|
430
|
+
handle: {
|
|
431
|
+
width: 40,
|
|
432
|
+
height: 5,
|
|
433
|
+
borderRadius: 3,
|
|
434
|
+
opacity: 0.5
|
|
435
|
+
},
|
|
436
|
+
body: {
|
|
437
|
+
paddingHorizontal: 20,
|
|
438
|
+
paddingTop: 4
|
|
439
|
+
},
|
|
440
|
+
title: {
|
|
441
|
+
fontSize: 20,
|
|
442
|
+
fontWeight: "700",
|
|
443
|
+
marginBottom: 16
|
|
444
|
+
},
|
|
445
|
+
catRow: {
|
|
446
|
+
flexDirection: "row",
|
|
447
|
+
justifyContent: "space-between",
|
|
448
|
+
marginBottom: 16
|
|
449
|
+
},
|
|
450
|
+
catBtn: {
|
|
451
|
+
alignItems: "center",
|
|
452
|
+
paddingVertical: 10,
|
|
453
|
+
paddingHorizontal: 6,
|
|
454
|
+
borderRadius: 12,
|
|
455
|
+
borderWidth: 1,
|
|
456
|
+
flex: 1,
|
|
457
|
+
marginHorizontal: 3
|
|
458
|
+
},
|
|
459
|
+
catEmoji: {
|
|
460
|
+
fontSize: 22,
|
|
461
|
+
marginBottom: 4
|
|
462
|
+
},
|
|
463
|
+
catLabel: {
|
|
464
|
+
fontSize: 11,
|
|
465
|
+
fontWeight: "600"
|
|
466
|
+
},
|
|
467
|
+
input: {
|
|
468
|
+
borderWidth: 1,
|
|
469
|
+
borderRadius: 12,
|
|
470
|
+
padding: 14,
|
|
471
|
+
fontSize: 15,
|
|
472
|
+
minHeight: 100,
|
|
473
|
+
marginBottom: 16
|
|
474
|
+
},
|
|
475
|
+
submitBtn: {
|
|
476
|
+
borderRadius: 12,
|
|
477
|
+
paddingVertical: 14,
|
|
478
|
+
alignItems: "center"
|
|
479
|
+
},
|
|
480
|
+
submitText: {
|
|
481
|
+
color: "#fff",
|
|
482
|
+
fontSize: 16,
|
|
483
|
+
fontWeight: "700"
|
|
484
|
+
},
|
|
485
|
+
sentWrap: {
|
|
486
|
+
alignItems: "center",
|
|
487
|
+
justifyContent: "center",
|
|
488
|
+
paddingVertical: 60
|
|
489
|
+
},
|
|
490
|
+
sentEmoji: {
|
|
491
|
+
fontSize: 48,
|
|
492
|
+
marginBottom: 12
|
|
493
|
+
},
|
|
494
|
+
sentText: {
|
|
495
|
+
fontSize: 20,
|
|
496
|
+
fontWeight: "600"
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
// src/components/MushiFloatingButton.tsx
|
|
501
|
+
import { useRef as useRef2, useCallback as useCallback2 } from "react";
|
|
502
|
+
import {
|
|
503
|
+
Animated as Animated2,
|
|
504
|
+
TouchableWithoutFeedback,
|
|
505
|
+
StyleSheet as StyleSheet2,
|
|
506
|
+
Platform as Platform3,
|
|
507
|
+
useColorScheme as useColorScheme2
|
|
508
|
+
} from "react-native";
|
|
509
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
510
|
+
var MushiFloatingButton = ({
|
|
511
|
+
onPress,
|
|
512
|
+
position = "bottom-right"
|
|
513
|
+
}) => {
|
|
514
|
+
const scheme = useColorScheme2();
|
|
515
|
+
const dark = scheme === "dark";
|
|
516
|
+
const scale = useRef2(new Animated2.Value(1)).current;
|
|
517
|
+
const handlePressIn = useCallback2(() => {
|
|
518
|
+
Animated2.spring(scale, {
|
|
519
|
+
toValue: 0.85,
|
|
520
|
+
useNativeDriver: true,
|
|
521
|
+
damping: 15,
|
|
522
|
+
stiffness: 300
|
|
523
|
+
}).start();
|
|
524
|
+
}, [scale]);
|
|
525
|
+
const handlePressOut = useCallback2(() => {
|
|
526
|
+
Animated2.spring(scale, {
|
|
527
|
+
toValue: 1,
|
|
528
|
+
useNativeDriver: true,
|
|
529
|
+
damping: 10,
|
|
530
|
+
stiffness: 250
|
|
531
|
+
}).start();
|
|
532
|
+
}, [scale]);
|
|
533
|
+
const positionStyle = position === "bottom-left" ? { left: 20 } : { right: 20 };
|
|
534
|
+
return /* @__PURE__ */ jsx2(
|
|
535
|
+
TouchableWithoutFeedback,
|
|
536
|
+
{
|
|
537
|
+
onPress,
|
|
538
|
+
onPressIn: handlePressIn,
|
|
539
|
+
onPressOut: handlePressOut,
|
|
540
|
+
children: /* @__PURE__ */ jsx2(
|
|
541
|
+
Animated2.View,
|
|
542
|
+
{
|
|
543
|
+
style: [
|
|
544
|
+
s2.fab,
|
|
545
|
+
positionStyle,
|
|
546
|
+
{
|
|
547
|
+
backgroundColor: dark ? "#0a84ff" : "#007aff",
|
|
548
|
+
transform: [{ scale }],
|
|
549
|
+
shadowColor: dark ? "#0a84ff" : "#000"
|
|
550
|
+
}
|
|
551
|
+
],
|
|
552
|
+
children: /* @__PURE__ */ jsx2(Animated2.Text, { style: s2.emoji, children: "\u{1F41B}" })
|
|
553
|
+
}
|
|
554
|
+
)
|
|
555
|
+
}
|
|
556
|
+
);
|
|
557
|
+
};
|
|
558
|
+
var s2 = StyleSheet2.create({
|
|
559
|
+
fab: {
|
|
560
|
+
position: "absolute",
|
|
561
|
+
bottom: Platform3.OS === "ios" ? 50 : 28,
|
|
562
|
+
width: 56,
|
|
563
|
+
height: 56,
|
|
564
|
+
borderRadius: 28,
|
|
565
|
+
alignItems: "center",
|
|
566
|
+
justifyContent: "center",
|
|
567
|
+
zIndex: 9999,
|
|
568
|
+
elevation: 8,
|
|
569
|
+
shadowOffset: { width: 0, height: 4 },
|
|
570
|
+
shadowOpacity: 0.3,
|
|
571
|
+
shadowRadius: 6
|
|
572
|
+
},
|
|
573
|
+
emoji: {
|
|
574
|
+
fontSize: 26
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
|
|
177
578
|
// src/provider.tsx
|
|
178
|
-
import { jsx } from "react/jsx-runtime";
|
|
579
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
179
580
|
var MushiContext = createContext(null);
|
|
180
581
|
function MushiProvider({ children, ...config }) {
|
|
181
|
-
const consoleRef =
|
|
182
|
-
const networkRef =
|
|
183
|
-
const queueRef =
|
|
184
|
-
const
|
|
185
|
-
|
|
582
|
+
const consoleRef = useRef3(null);
|
|
583
|
+
const networkRef = useRef3(null);
|
|
584
|
+
const queueRef = useRef3(null);
|
|
585
|
+
const apiClientRef = useRef3(null);
|
|
586
|
+
const [sheetVisible, setSheetVisible] = useState2(false);
|
|
587
|
+
const apiEndpoint = config.endpoint ?? DEFAULT_API_ENDPOINT;
|
|
588
|
+
useEffect2(() => {
|
|
186
589
|
if (config.capture?.console !== false) {
|
|
187
590
|
consoleRef.current = setupConsoleCapture(config.capture?.maxConsoleEntries);
|
|
188
591
|
}
|
|
189
592
|
if (config.capture?.network !== false) {
|
|
190
593
|
networkRef.current = setupNetworkCapture(config.capture?.maxNetworkEntries, apiEndpoint);
|
|
191
594
|
}
|
|
595
|
+
apiClientRef.current = createApiClient({
|
|
596
|
+
projectId: config.projectId,
|
|
597
|
+
apiKey: config.apiKey,
|
|
598
|
+
apiEndpoint
|
|
599
|
+
});
|
|
192
600
|
queueRef.current = new AsyncStorageQueue({
|
|
193
601
|
maxSize: config.storage?.maxQueueSize,
|
|
194
602
|
apiEndpoint,
|
|
195
603
|
apiKey: config.apiKey
|
|
196
604
|
});
|
|
605
|
+
queueRef.current.flush().catch(() => {
|
|
606
|
+
});
|
|
197
607
|
return () => {
|
|
198
608
|
consoleRef.current?.restore();
|
|
199
609
|
networkRef.current?.restore();
|
|
200
610
|
};
|
|
201
611
|
}, []);
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
submitReport: async (data) => {
|
|
612
|
+
const open = useCallback3(() => setSheetVisible(true), []);
|
|
613
|
+
const close = useCallback3(() => setSheetVisible(false), []);
|
|
614
|
+
const submitReport = useCallback3(
|
|
615
|
+
async (data) => {
|
|
616
|
+
const deviceInfo = getDeviceInfo();
|
|
208
617
|
const report = {
|
|
618
|
+
id: `rn-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
209
619
|
projectId: config.projectId,
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
620
|
+
category: data.category,
|
|
621
|
+
description: data.description,
|
|
622
|
+
environment: {
|
|
623
|
+
userAgent: deviceInfo.systemName ?? "ReactNative",
|
|
624
|
+
platform: deviceInfo.platform ?? "mobile",
|
|
625
|
+
language: deviceInfo.locale ?? "en",
|
|
626
|
+
viewport: { width: deviceInfo.screenWidth ?? 0, height: deviceInfo.screenHeight ?? 0 },
|
|
627
|
+
url: "",
|
|
628
|
+
referrer: "",
|
|
629
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
630
|
+
timezone: deviceInfo.timezone ?? "UTC"
|
|
631
|
+
},
|
|
632
|
+
consoleLogs: consoleRef.current?.getEntries() ?? [],
|
|
633
|
+
networkLogs: networkRef.current?.getEntries().map((entry) => ({
|
|
634
|
+
...entry,
|
|
635
|
+
status: entry.status ?? 0
|
|
636
|
+
})) ?? [],
|
|
637
|
+
reporterToken: `rn-${config.projectId}-anon`,
|
|
638
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
214
639
|
};
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
body: JSON.stringify(report)
|
|
220
|
-
});
|
|
221
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
222
|
-
} catch {
|
|
640
|
+
const client = apiClientRef.current;
|
|
641
|
+
if (!client) return;
|
|
642
|
+
const result = await client.submitReport(report);
|
|
643
|
+
if (!result.ok) {
|
|
223
644
|
await queueRef.current?.enqueue(report);
|
|
224
645
|
}
|
|
225
646
|
},
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
647
|
+
[config.projectId, config.apiKey, apiEndpoint]
|
|
648
|
+
);
|
|
649
|
+
const instance = useMemo(
|
|
650
|
+
() => ({
|
|
651
|
+
open,
|
|
652
|
+
close,
|
|
653
|
+
submitReport,
|
|
654
|
+
getDeviceInfo,
|
|
655
|
+
getConsoleEntries: () => consoleRef.current?.getEntries() ?? [],
|
|
656
|
+
getNetworkEntries: () => networkRef.current?.getEntries() ?? []
|
|
657
|
+
}),
|
|
658
|
+
[open, close, submitReport]
|
|
659
|
+
);
|
|
660
|
+
const trigger = config.widget?.trigger ?? "button";
|
|
661
|
+
const showFab = trigger === "button" || trigger === "both";
|
|
662
|
+
return /* @__PURE__ */ jsxs2(MushiContext.Provider, { value: instance, children: [
|
|
663
|
+
children,
|
|
664
|
+
showFab && /* @__PURE__ */ jsx3(
|
|
665
|
+
MushiFloatingButton,
|
|
666
|
+
{
|
|
667
|
+
onPress: open,
|
|
668
|
+
position: config.widget?.buttonPosition
|
|
669
|
+
}
|
|
670
|
+
),
|
|
671
|
+
/* @__PURE__ */ jsx3(MushiBottomSheet, { visible: sheetVisible, onClose: close })
|
|
672
|
+
] });
|
|
231
673
|
}
|
|
232
674
|
function useMushiContext() {
|
|
233
675
|
return useContext(MushiContext);
|
|
@@ -239,10 +681,10 @@ function useMushi() {
|
|
|
239
681
|
}
|
|
240
682
|
|
|
241
683
|
// src/hooks/useMushiReport.ts
|
|
242
|
-
import { useCallback } from "react";
|
|
684
|
+
import { useCallback as useCallback4 } from "react";
|
|
243
685
|
function useMushiReport() {
|
|
244
686
|
const mushi = useMushiContext();
|
|
245
|
-
const submitReport =
|
|
687
|
+
const submitReport = useCallback4(
|
|
246
688
|
async (data) => {
|
|
247
689
|
if (!mushi) throw new Error("MushiProvider not found");
|
|
248
690
|
await mushi.submitReport(data);
|
|
@@ -253,20 +695,20 @@ function useMushiReport() {
|
|
|
253
695
|
}
|
|
254
696
|
|
|
255
697
|
// src/hooks/useMushiWidget.ts
|
|
256
|
-
import { useCallback as
|
|
698
|
+
import { useCallback as useCallback5 } from "react";
|
|
257
699
|
function useMushiWidget() {
|
|
258
700
|
const mushi = useMushiContext();
|
|
259
701
|
return {
|
|
260
|
-
open:
|
|
261
|
-
close:
|
|
702
|
+
open: useCallback5(() => mushi?.open(), [mushi]),
|
|
703
|
+
close: useCallback5(() => mushi?.close(), [mushi])
|
|
262
704
|
};
|
|
263
705
|
}
|
|
264
706
|
|
|
265
707
|
// src/capture/navigation-capture.ts
|
|
266
|
-
import { useEffect as
|
|
708
|
+
import { useEffect as useEffect3, useRef as useRef4 } from "react";
|
|
267
709
|
function useNavigationCapture(navigationRef) {
|
|
268
|
-
const historyRef =
|
|
269
|
-
|
|
710
|
+
const historyRef = useRef4([]);
|
|
711
|
+
useEffect3(() => {
|
|
270
712
|
if (!navigationRef?.addListener || !navigationRef?.getCurrentRoute) return;
|
|
271
713
|
const unsubscribe = navigationRef.addListener("state", () => {
|
|
272
714
|
const route = navigationRef.getCurrentRoute?.();
|
|
@@ -281,6 +723,8 @@ function useNavigationCapture(navigationRef) {
|
|
|
281
723
|
}
|
|
282
724
|
export {
|
|
283
725
|
AsyncStorageQueue,
|
|
726
|
+
MushiBottomSheet,
|
|
727
|
+
MushiFloatingButton,
|
|
284
728
|
MushiProvider,
|
|
285
729
|
getDeviceInfo,
|
|
286
730
|
setupConsoleCapture,
|