@robono/messaging-react-native 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/README.md +84 -7
- package/SBOM.spdx.json +1295 -239
- package/dist/account.d.ts +15 -0
- package/dist/account.js +27 -0
- package/dist/call-message.js +7 -1
- package/dist/calling.js +5 -9
- package/dist/conversation-details.d.ts +24 -0
- package/dist/conversation-details.js +83 -0
- package/dist/emoji-text.d.ts +2 -0
- package/dist/emoji-text.js +8 -0
- package/dist/expo-history.d.ts +3 -0
- package/dist/expo-history.js +59 -0
- package/dist/expo-media.d.ts +1 -0
- package/dist/expo-media.js +46 -43
- package/dist/expo-messenger.d.ts +35 -0
- package/dist/expo-messenger.js +39 -0
- package/dist/expo-notifications.d.ts +31 -0
- package/dist/expo-notifications.js +92 -0
- package/dist/expo-outbox.js +2 -1
- package/dist/expo-privacy.d.ts +4 -0
- package/dist/expo-privacy.js +7 -0
- package/dist/expo-screen.d.ts +42 -0
- package/dist/expo-screen.js +557 -0
- package/dist/expo.d.ts +2 -42
- package/dist/expo.js +2 -549
- package/dist/extras-lifecycle.d.ts +2 -0
- package/dist/extras-lifecycle.js +27 -0
- package/dist/extras.d.ts +49 -0
- package/dist/extras.js +49 -0
- package/dist/forward.js +4 -3
- package/dist/group-editor.d.ts +18 -0
- package/dist/group-editor.js +98 -0
- package/dist/header-calls.d.ts +18 -0
- package/dist/header-calls.js +45 -0
- package/dist/inbox-search.d.ts +11 -0
- package/dist/inbox-search.js +42 -0
- package/dist/inbox.d.ts +5 -2
- package/dist/inbox.js +19 -15
- package/dist/index.d.ts +33 -3
- package/dist/index.js +347 -129
- package/dist/media-controller.d.ts +3 -0
- package/dist/media-controller.js +39 -0
- package/dist/media-ui.d.ts +14 -3
- package/dist/media-ui.js +90 -28
- package/dist/message-menu.d.ts +28 -0
- package/dist/message-menu.js +24 -0
- package/dist/message-order.d.ts +3 -0
- package/dist/message-order.js +10 -0
- package/dist/messenger-video-view.d.ts +8 -0
- package/dist/messenger-video-view.js +46 -0
- package/dist/native-outbox.d.ts +8 -2
- package/dist/native-outbox.js +3 -1
- package/dist/photo-gesture.d.ts +20 -0
- package/dist/photo-gesture.js +52 -0
- package/dist/polls.d.ts +2 -1
- package/dist/polls.js +19 -17
- package/dist/popup.d.ts +43 -1
- package/dist/popup.js +72 -6
- package/dist/quick-send.d.ts +15 -0
- package/dist/quick-send.js +26 -0
- package/dist/safety.d.ts +9 -1
- package/dist/safety.js +21 -6
- package/dist/saved.d.ts +1 -1
- package/dist/saved.js +9 -4
- package/dist/search.d.ts +2 -2
- package/dist/search.js +32 -14
- package/dist/social.d.ts +9 -3
- package/dist/social.js +11 -15
- package/dist/translation-settings.d.ts +12 -0
- package/dist/translation-settings.js +16 -0
- package/dist/use-quote-gesture.d.ts +5 -1
- package/dist/use-quote-gesture.js +35 -17
- package/dist/visual/WeatherArtwork.d.ts +9 -0
- package/dist/visual/WeatherArtwork.js +43 -0
- package/dist/visual/weather-artwork.d.ts +17 -0
- package/dist/visual/weather-artwork.js +86 -0
- package/dist/visual/weather-conditions.d.ts +5 -0
- package/dist/visual/weather-conditions.js +2 -0
- package/dist/voice-waveform.d.ts +2 -0
- package/dist/voice-waveform.js +21 -0
- package/package.json +24 -4
package/dist/social.js
CHANGED
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
|
-
import { ActivityIndicator, AppState, Linking,
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useImperativeHandle, useEffect, useState } from 'react';
|
|
3
|
+
import { ActivityIndicator, AppState, Linking, Pressable, Text, View } from 'react-native';
|
|
4
4
|
import { socialShare } from '@robono/messaging';
|
|
5
5
|
import { MessagingPopup } from './popup.js';
|
|
6
|
-
import { MessageIcon
|
|
6
|
+
import { MessageIcon } from './icons.js';
|
|
7
7
|
import { messageLinks } from './message-links.js';
|
|
8
|
-
export function SocialMessagePreview({ message, client, Player, origin, accent, foreground, background }) {
|
|
8
|
+
export const SocialMessagePreview = forwardRef(function SocialMessagePreview({ message, client, Player, origin, accent, foreground, background, onLongPress, renderMessage }, ref) {
|
|
9
9
|
const share = messageLinks(message.text ?? '').map(link => link.url ? socialShare(link.url, origin) : null).find(Boolean);
|
|
10
10
|
const [opened, setOpened] = useState(null);
|
|
11
|
+
useImperativeHandle(ref, () => ({ open: () => { if (share && !message.deleted)
|
|
12
|
+
setOpened({ client, message }); } }), [share, client, message]);
|
|
11
13
|
const open = opened?.client === client && opened.message.id === message.id && opened.message.conversationId === message.conversationId && opened.message.text === message.text && opened.message.revision === message.revision;
|
|
12
14
|
useEffect(() => { const sub = AppState.addEventListener('change', state => { if (state !== 'active')
|
|
13
15
|
setOpened(null); }); return () => sub.remove(); }, []);
|
|
14
16
|
if (!share || message.deleted)
|
|
15
17
|
return null;
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
+
const action = _jsx(Pressable, { testID: "social-preview-action", hitSlop: 6, accessibilityRole: "button", accessibilityLabel: `Play ${share.provider} preview`, onLongPress: onLongPress, onPress: event => { event.stopPropagation(); setOpened({ client, message }); }, style: ({ pressed }) => ({ flexShrink: 0, width: 32, height: 32, borderRadius: 16, borderWidth: 1, borderColor: accent + '70', backgroundColor: accent + (pressed ? '30' : '0d'), flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }), children: _jsx(MessageIcon, { name: "play", color: accent, size: 16 }) });
|
|
19
|
+
return _jsxs(_Fragment, { children: [renderMessage ? renderMessage(action) : action, open && _jsx(SocialPreviewPopup, { message: message, client: client, Player: Player, origin: origin, provider: share.provider, url: share.url, accent: accent, foreground: foreground, background: background, onClose: () => setOpened(null) }, message.id)] });
|
|
20
|
+
});
|
|
18
21
|
function SocialPreviewPopup({ message, client, Player, origin, provider, url, accent, foreground, background, onClose }) {
|
|
19
22
|
const [preview, setPreview] = useState(null), [busy, setBusy] = useState(true), [error, setError] = useState('');
|
|
20
|
-
const { height } = useWindowDimensions();
|
|
21
|
-
useEffect(() => { if (Platform.OS !== 'web')
|
|
22
|
-
return; const escape = (event) => { if (event.key === 'Escape') {
|
|
23
|
-
event.preventDefault();
|
|
24
|
-
event.stopPropagation();
|
|
25
|
-
onClose();
|
|
26
|
-
} }; document.addEventListener('keydown', escape, true); return () => document.removeEventListener('keydown', escape, true); }, [onClose]);
|
|
27
23
|
useEffect(() => { let active = true; void client.socialPreview(message.id, origin).then(result => { if (active) {
|
|
28
24
|
setPreview(result);
|
|
29
25
|
if (!result.html)
|
|
@@ -31,5 +27,5 @@ function SocialPreviewPopup({ message, client, Player, origin, provider, url, ac
|
|
|
31
27
|
} }).catch(() => { if (active)
|
|
32
28
|
setError('This preview could not be loaded. Open the original below.'); }).finally(() => { if (active)
|
|
33
29
|
setBusy(false); }); return () => { active = false; }; }, [client, message.id, origin]);
|
|
34
|
-
return _jsxs(MessagingPopup, {
|
|
30
|
+
return _jsxs(MessagingPopup, { expanded: true, bottomPadding: 4, background: "#000000", title: provider, foreground: "#ffffff", closeLabel: "Close social preview", onClose: onClose, children: [busy && _jsx(View, { style: { flex: 1, alignItems: 'center', justifyContent: 'center' }, children: _jsx(ActivityIndicator, { accessibilityLabel: "Loading social preview", color: accent }) }), !!preview?.html && _jsx(View, { testID: "social-preview-player", style: { flex: 1, minHeight: 0, overflow: 'hidden', borderRadius: 10 }, children: _jsx(Player, { html: preview.html, frame: preview.frame, origin: origin, provider: provider, onClose: onClose, onError: () => setError('This preview is unavailable. Open the original below.') }) }), !!error && _jsx(Text, { accessibilityRole: "alert", style: { color: '#ffffff', fontSize: 13, paddingVertical: 8 }, children: error }), _jsx(Pressable, { accessibilityRole: "link", accessibilityLabel: `Open ${provider}`, onPress: () => { void Linking.openURL(url).catch(() => setError('This link could not be opened.')); }, style: { minHeight: 44, justifyContent: 'center' }, children: _jsxs(Text, { style: { color: accent, fontWeight: '600' }, children: ["Open ", provider] }) })] });
|
|
35
31
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type TranslationPreference, type MessagingClient, type MessagingAppearance } from '@robono/messaging';
|
|
3
|
+
/** The choice belongs to the conversation, never to an individual message. */
|
|
4
|
+
export declare function TranslationSettings({ client, appearance, preference, language, sourceLanguage, voiceAvailable, onSaved }: {
|
|
5
|
+
client: MessagingClient;
|
|
6
|
+
appearance: MessagingAppearance;
|
|
7
|
+
preference?: TranslationPreference;
|
|
8
|
+
language?: string;
|
|
9
|
+
sourceLanguage?: string;
|
|
10
|
+
voiceAvailable: boolean;
|
|
11
|
+
onSaved: () => void;
|
|
12
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { MessageIcon } from './icons.js';
|
|
3
|
+
import { messagingPopupColors } from './popup.js';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { Pressable, ScrollView, Text, View } from 'react-native';
|
|
6
|
+
import { normalizeLanguageCode, supportedLanguages, supportedLanguageLabel } from '@robono/messaging';
|
|
7
|
+
/** The choice belongs to the conversation, never to an individual message. */
|
|
8
|
+
export function TranslationSettings({ client, appearance, preference, language, sourceLanguage, voiceAvailable, onSaved }) {
|
|
9
|
+
const [value, setValue] = useState(() => preference ?? { mode: 'off', language: normalizeLanguageCode(language ?? Intl.DateTimeFormat().resolvedOptions().locale) ?? 'en', sourceLanguage: normalizeLanguageCode(sourceLanguage) });
|
|
10
|
+
const [choosing, setChoosing] = useState(null), [busy, setBusy] = useState(false), [error, setError] = useState('');
|
|
11
|
+
const c = { ...appearance.colors, ...messagingPopupColors };
|
|
12
|
+
return _jsxs(View, { style: { gap: 8 }, children: [_jsx(Text, { style: { fontSize: 13, fontWeight: '600', color: c.secondary, paddingHorizontal: 4 }, children: "Translation" }), _jsxs(View, { style: { backgroundColor: '#111111', borderRadius: 12, borderWidth: 1, borderColor: '#ffffff14', padding: 12, gap: 4 }, children: [_jsx(View, { accessibilityRole: "radiogroup", style: { flexDirection: 'row', borderWidth: 1, borderColor: '#ffffff14', borderRadius: 9, overflow: 'hidden', padding: 3, gap: 3 }, children: ['off', 'text', 'voice'].map(mode => _jsx(Pressable, { accessibilityRole: "radio", accessibilityLabel: 'Translation ' + mode, accessibilityState: { checked: value.mode === mode, disabled: busy || mode === 'voice' && !voiceAvailable }, disabled: busy || mode === 'voice' && !voiceAvailable, onPress: () => setValue(v => ({ ...v, mode })), style: { flex: 1, minHeight: 36, borderRadius: 6, alignItems: 'center', justifyContent: 'center', backgroundColor: value.mode === mode ? c.accent + '25' : 'transparent', opacity: mode === 'voice' && !voiceAvailable ? .4 : 1 }, children: _jsx(Text, { style: { color: value.mode === mode ? c.accent : c.secondary, fontSize: 14, fontWeight: '600' }, children: mode === 'off' ? 'Off' : mode === 'text' ? 'Text' : 'Voice' }) }, mode)) }), ['sourceLanguage', 'language'].map(field => _jsxs(View, { children: [_jsxs(Pressable, { accessibilityRole: "button", accessibilityLabel: field === 'language' ? 'Translation language' : 'Incoming language', disabled: busy, onPress: () => setChoosing(choosing === field ? null : field), style: { minHeight: 48, flexDirection: 'row', alignItems: 'center', gap: 10, borderBottomWidth: field === 'sourceLanguage' ? 1 : 0, borderBottomColor: '#ffffff14' }, children: [_jsx(Text, { style: { flex: 1, color: c.secondary, fontSize: 14 }, children: field === 'language' ? 'Translate into' : 'Messages in' }), _jsx(Text, { style: { color: c.accent, fontSize: 15, flexShrink: 1, textAlign: 'right' }, children: value[field] ? supportedLanguageLabel(value[field]) : 'Choose language' }), _jsx(MessageIcon, { name: choosing === field ? 'chevron-up' : 'chevron-down', color: c.secondary, size: 16 })] }), choosing === field && _jsx(ScrollView, { style: { maxHeight: 180 }, keyboardShouldPersistTaps: "handled", children: supportedLanguages.map(item => _jsx(Pressable, { accessibilityRole: "button", accessibilityLabel: 'Choose ' + item.name, onPress: () => { setValue(v => ({ ...v, [field]: item.code })); setChoosing(null); }, style: { minHeight: 40, paddingHorizontal: 8, justifyContent: 'center' }, children: _jsx(Text, { style: { color: c.foreground }, children: item.name }) }, item.code)) })] }, field)), !!error && _jsx(Text, { accessibilityRole: "alert", style: { color: c.foreground }, children: error }), _jsx(Pressable, { accessibilityRole: "button", accessibilityLabel: "Save translation preference", disabled: busy, onPress: () => { if (value.mode !== 'off' && !value.sourceLanguage) {
|
|
13
|
+
setError('Choose the incoming language once for this conversation.');
|
|
14
|
+
return;
|
|
15
|
+
} setError(''); setBusy(true); void client.setTranslationPreference(value).then(onSaved).catch(() => setError('The translation preference could not be saved. Try again.')).finally(() => setBusy(false)); }, style: { minHeight: 40, minWidth: 96, paddingHorizontal: 18, marginTop: 8, alignSelf: 'flex-end', alignItems: 'center', justifyContent: 'center', borderRadius: 9, backgroundColor: c.accent, opacity: busy ? 0.5 : 1 }, children: _jsx(Text, { style: { color: '#111111', fontSize: 14, fontWeight: '600' }, children: busy ? 'Saving…' : 'Save' }) })] })] });
|
|
16
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { Animated } from 'react-native';
|
|
2
|
-
export declare
|
|
2
|
+
export declare const messageInfoRevealWidth = 176;
|
|
3
|
+
export declare const messageReplyRevealWidth = 104;
|
|
4
|
+
export declare function useQuoteGesture(enabled: boolean, outgoing: boolean, quote: (() => void) | undefined, details?: () => void): {
|
|
3
5
|
offset: number | Animated.Value;
|
|
4
6
|
webRef: import("react").RefObject<HTMLElement | null> | undefined;
|
|
7
|
+
infoLoaded: boolean;
|
|
8
|
+
infoOpacity: number | Animated.AnimatedInterpolation<string | number>;
|
|
5
9
|
revealOpacity: number | Animated.AnimatedInterpolation<string | number>;
|
|
6
10
|
revealWebStyle: {
|
|
7
11
|
transitionProperty: string;
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { Animated, PanResponder, Platform } from 'react-native';
|
|
3
|
-
|
|
4
|
-
export
|
|
2
|
+
import { Animated, Easing, I18nManager, PanResponder, Platform } from 'react-native';
|
|
3
|
+
// Same travel, trigger and return timing as Messenger's MessageSwipeReveal.
|
|
4
|
+
export const messageInfoRevealWidth = 176;
|
|
5
|
+
export const messageReplyRevealWidth = 104;
|
|
6
|
+
const threshold = 82;
|
|
7
|
+
export function useQuoteGesture(enabled, outgoing, quote, details) {
|
|
5
8
|
const offset = useRef(new Animated.Value(0)).current;
|
|
6
9
|
const [webOffset, setWebOffset] = useState(0);
|
|
7
10
|
const [webDragging, setWebDragging] = useState(false);
|
|
8
|
-
const
|
|
9
|
-
|
|
11
|
+
const direction = (outgoing !== !!I18nManager.isRTL) ? -1 : 1;
|
|
12
|
+
const [infoLoaded, setInfoLoaded] = useState(false);
|
|
13
|
+
const current = useRef({ enabled, direction, quote, details });
|
|
14
|
+
current.current = { enabled, direction, quote, details };
|
|
10
15
|
const suppressUntil = useRef(0);
|
|
11
16
|
const reset = () => {
|
|
12
17
|
if (Platform.OS === 'web') {
|
|
@@ -14,13 +19,21 @@ export function useQuoteGesture(enabled, outgoing, quote) {
|
|
|
14
19
|
setWebOffset(0);
|
|
15
20
|
}
|
|
16
21
|
else
|
|
17
|
-
Animated.
|
|
22
|
+
Animated.timing(offset, { toValue: 0, duration: 150, easing: Easing.out(Easing.cubic), useNativeDriver: true }).start();
|
|
23
|
+
};
|
|
24
|
+
const accepts = (dx, dy) => {
|
|
25
|
+
const { enabled, direction, quote } = current.current;
|
|
26
|
+
return enabled && Math.abs(dx) >= (Platform.OS === 'ios' ? 10 : 8) &&
|
|
27
|
+
Math.abs(dx) >= Math.abs(dy) * (Platform.OS === 'ios' ? .55 : 1.15) &&
|
|
28
|
+
(dx * direction < 0 || !!quote && dx * direction > 0);
|
|
18
29
|
};
|
|
19
|
-
const accepts = (dx, dy) => current.current.enabled &&
|
|
20
|
-
dx * current.current.direction > 10 && Math.abs(dx) > Math.abs(dy) * 1.5;
|
|
21
30
|
const move = (dx) => {
|
|
22
31
|
suppressUntil.current = Date.now() + 400;
|
|
23
|
-
const
|
|
32
|
+
const info = dx * current.current.direction < 0;
|
|
33
|
+
if (info)
|
|
34
|
+
setInfoLoaded(true);
|
|
35
|
+
const limit = info ? messageInfoRevealWidth : current.current.quote ? messageReplyRevealWidth : 0;
|
|
36
|
+
const value = Math.sign(dx) * Math.min(limit, Math.abs(dx));
|
|
24
37
|
if (Platform.OS === 'web') {
|
|
25
38
|
setWebDragging(true);
|
|
26
39
|
setWebOffset(value);
|
|
@@ -29,20 +42,23 @@ export function useQuoteGesture(enabled, outgoing, quote) {
|
|
|
29
42
|
offset.setValue(value);
|
|
30
43
|
};
|
|
31
44
|
const finish = (dx, cancelled = false) => {
|
|
45
|
+
suppressUntil.current = Date.now() + 400;
|
|
32
46
|
if (!cancelled && current.current.enabled && dx * current.current.direction >= threshold)
|
|
33
|
-
current.current.quote();
|
|
47
|
+
current.current.quote?.();
|
|
48
|
+
else if (!cancelled && current.current.enabled && dx * current.current.direction <= -threshold)
|
|
49
|
+
current.current.details?.();
|
|
34
50
|
reset();
|
|
35
51
|
};
|
|
36
52
|
const responder = useRef(PanResponder.create({
|
|
37
53
|
onStartShouldSetPanResponder: () => { suppressUntil.current = 0; return false; },
|
|
38
54
|
onStartShouldSetPanResponderCapture: () => { suppressUntil.current = 0; return false; },
|
|
39
|
-
onMoveShouldSetPanResponderCapture: (_, gesture) => gesture.numberActiveTouches === 1 && accepts(gesture.dx, gesture.dy),
|
|
55
|
+
onMoveShouldSetPanResponderCapture: (_, gesture) => Platform.OS === 'ios' && gesture.numberActiveTouches === 1 && accepts(gesture.dx, gesture.dy),
|
|
40
56
|
onMoveShouldSetPanResponder: (_, gesture) => accepts(gesture.dx, gesture.dy),
|
|
41
57
|
onPanResponderGrant: () => offset.stopAnimation(),
|
|
42
58
|
onPanResponderMove: (_, gesture) => move(gesture.dx),
|
|
43
59
|
onPanResponderRelease: (_, gesture) => finish(gesture.dx),
|
|
44
60
|
onPanResponderTerminate: () => finish(0, true),
|
|
45
|
-
onPanResponderTerminationRequest: () =>
|
|
61
|
+
onPanResponderTerminationRequest: () => Platform.OS !== 'ios',
|
|
46
62
|
})).current;
|
|
47
63
|
const pointer = useRef(null);
|
|
48
64
|
const webHandlers = {
|
|
@@ -67,7 +83,7 @@ export function useQuoteGesture(enabled, outgoing, quote) {
|
|
|
67
83
|
event.preventDefault();
|
|
68
84
|
move(dx);
|
|
69
85
|
}
|
|
70
|
-
else if (Math.abs(dy) > 10 || dx * current.current.direction
|
|
86
|
+
else if (Math.abs(dy) > 10 || !current.current.quote && dx * current.current.direction > 10)
|
|
71
87
|
pointer.current = null;
|
|
72
88
|
},
|
|
73
89
|
onPointerUp: (event) => {
|
|
@@ -118,10 +134,12 @@ export function useQuoteGesture(enabled, outgoing, quote) {
|
|
|
118
134
|
}, []);
|
|
119
135
|
return { offset: Platform.OS === 'web' ? webOffset : offset,
|
|
120
136
|
webRef: Platform.OS === 'web' ? webRef : undefined,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
137
|
+
infoLoaded,
|
|
138
|
+
infoOpacity: Platform.OS === 'web' ? Math.min(1, Math.max(0, -webOffset * direction) / 24) : offset.interpolate({ inputRange: direction === 1 ? [-24, -8, 0] : [0, 8, 24], outputRange: direction === 1 ? [1, .35, 0] : [0, .35, 1], extrapolate: 'clamp' }),
|
|
139
|
+
revealOpacity: Platform.OS === 'web' ? Math.min(1, Math.max(0, webOffset * direction) / messageReplyRevealWidth)
|
|
140
|
+
: offset.interpolate({ inputRange: direction === -1 ? [-messageReplyRevealWidth, -18, 0] : [0, 18, messageReplyRevealWidth], outputRange: direction === -1 ? [1, .35, 0] : [0, .35, 1], extrapolate: 'clamp' }),
|
|
141
|
+
revealWebStyle: Platform.OS === 'web' ? { transitionProperty: 'opacity', transitionDuration: webDragging ? '0ms' : '150ms' } : {},
|
|
142
|
+
webStyle: Platform.OS === 'web' ? { transitionProperty: 'transform', transitionDuration: webDragging ? '0ms' : '150ms', transitionTimingFunction: 'cubic-bezier(0.215,0.61,0.355,1)' } : {},
|
|
125
143
|
handlers: Platform.OS === 'web' ? {} : responder.panHandlers,
|
|
126
144
|
suppressPress: () => Date.now() < suppressUntil.current };
|
|
127
145
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/** Original conventional artwork, composed from conditions; identical on iOS and Android. */
|
|
3
|
+
export default function WeatherArtwork({ code, isDay, cloud, windKph, size }: {
|
|
4
|
+
code?: number;
|
|
5
|
+
isDay?: boolean;
|
|
6
|
+
cloud?: number | null;
|
|
7
|
+
windKph?: number | null;
|
|
8
|
+
size?: number;
|
|
9
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Svg, { Circle, G, Path } from "react-native-svg";
|
|
3
|
+
import { weatherScene } from "./weather-artwork.js";
|
|
4
|
+
const ink = "#52677f", blue = "#2674bd", amber = "#b86a08";
|
|
5
|
+
function Sun() {
|
|
6
|
+
return _jsxs(G, { stroke: amber, strokeWidth: 3.5, strokeLinecap: "round", children: [_jsx(Circle, { cx: 32, cy: 32, r: 13, fill: "#df9b36" }), _jsx(Path, { d: "M32 5v7M32 52v7M5 32h7M52 32h7M13 13l5 5M46 46l5 5M13 51l5-5M46 18l5-5" })] });
|
|
7
|
+
}
|
|
8
|
+
function Moon() {
|
|
9
|
+
return _jsx(Path, { d: "M43 9C20 6 8 26 17 43c8 16 31 17 41 0-20 6-35-16-15-34Z", fill: "#9ba7c7", stroke: "#59698f", strokeWidth: 3.5, strokeLinejoin: "round" });
|
|
10
|
+
}
|
|
11
|
+
function Cloud({ dark = false }) {
|
|
12
|
+
return _jsx(Path, { d: "M14 46C0 44 1 26 15 25c1-19 28-22 34-3 17-1 20 24 3 24Z", fill: dark ? "#8594a6" : "#dce4ec", stroke: ink, strokeWidth: 3.5, strokeLinejoin: "round" });
|
|
13
|
+
}
|
|
14
|
+
function Wind() {
|
|
15
|
+
return _jsx(G, { fill: "none", stroke: ink, strokeWidth: 4, strokeLinecap: "round", children: _jsx(Path, { d: "M5 24h31c14 0 14-19 3-19-6 0-9 5-8 9M9 35h42c13 0 13 21 1 21-6 0-9-4-9-8M3 46h23" }) });
|
|
16
|
+
}
|
|
17
|
+
function Flake({ x, y, size = 10 }) {
|
|
18
|
+
return _jsx(G, { transform: `translate(${x} ${y}) scale(${size / 10})`, stroke: blue, strokeWidth: 2.8, strokeLinecap: "round", children: _jsx(Path, { d: "M0-9V9M-8-4.5l16 9M-8 4.5l16-9" }) });
|
|
19
|
+
}
|
|
20
|
+
function Drop({ x, y, small = false }) {
|
|
21
|
+
return _jsx(Path, { transform: `translate(${x} ${y}) scale(${small ? .65 : 1})`, d: "M0-9C-2-5-6 0-6 3a6 6 0 0 0 12 0C6 0 2-5 0-9Z", fill: blue });
|
|
22
|
+
}
|
|
23
|
+
/** Original conventional artwork, composed from conditions; identical on iOS and Android. */
|
|
24
|
+
export default function WeatherArtwork({ code, isDay = true, cloud, windKph, size = 32 }) {
|
|
25
|
+
const scene = weatherScene(code, cloud, windKph);
|
|
26
|
+
if (!scene)
|
|
27
|
+
return _jsxs(Svg, { width: size, height: size, viewBox: "0 0 64 64", accessible: false, children: [_jsx(Circle, { cx: 32, cy: 32, r: 23, fill: "none", stroke: ink, strokeWidth: 4 }), _jsx(Path, { d: "M22 32h20", stroke: ink, strokeWidth: 4, strokeLinecap: "round" })] });
|
|
28
|
+
const detail = !!(scene.precipitation || scene.atmosphere || scene.windy || scene.thunder || scene.freezing);
|
|
29
|
+
const hasSky = scene.sky !== "none";
|
|
30
|
+
const precipitation = scene.precipitation;
|
|
31
|
+
const count = scene.intensity === 3 ? 3 : 2;
|
|
32
|
+
const mixed = precipitation === "sleet";
|
|
33
|
+
const particles = Array.from({ length: count }, (_, i) => {
|
|
34
|
+
const x = count === 3 ? 12 + i * 20 : 18 + i * 28;
|
|
35
|
+
const y = count === 3 && i === 1 ? 42 : 49;
|
|
36
|
+
if (precipitation === "snow" || (mixed && i === 1))
|
|
37
|
+
return _jsx(Flake, { x: x, y: y, size: count === 3 ? 8 : 10 }, i);
|
|
38
|
+
if (precipitation === "ice")
|
|
39
|
+
return _jsx(Path, { d: `M${x} ${y - 7}l7 7-7 7-7-7Z`, fill: "#cce7f3", stroke: blue, strokeWidth: 3 }, i);
|
|
40
|
+
return _jsx(Drop, { x: x, y: y, small: precipitation === "drizzle" }, i);
|
|
41
|
+
});
|
|
42
|
+
return _jsxs(Svg, { width: size, height: size, viewBox: "0 0 64 64", accessible: false, children: [(scene.sky === "clear" || scene.sky === "partial") && _jsx(G, { transform: detail || scene.sky === "partial" ? "translate(0 -1) scale(.68)" : undefined, children: isDay ? _jsx(Sun, {}) : _jsx(Moon, {}) }), (scene.sky === "cloud" || scene.sky === "partial") && _jsx(G, { transform: detail ? "translate(17 0) scale(.72)" : scene.sky === "partial" ? "translate(15 14) scale(.75)" : "translate(1 3) scale(.95)", children: _jsx(Cloud, { dark: scene.intensity === 3 || scene.thunder }) }), scene.windy && _jsx(G, { transform: precipitation || scene.atmosphere ? "translate(0 -1) scale(.63)" : hasSky ? "translate(17 24) scale(.72)" : "translate(0 0)", children: _jsx(Wind, {}) }), precipitation && _jsx(G, { transform: scene.thunder || scene.freezing ? "translate(-1 22) scale(.63)" : !hasSky && !scene.windy ? "translate(0 -10)" : undefined, children: particles }), scene.atmosphere && _jsx(G, { children: ["dust", "sand", "haze"].includes(scene.atmosphere) ? _jsxs(G, { fill: scene.atmosphere === "haze" ? ink : "#996b36", children: [[[8, 43], [20, 51], [32, 39], [44, 52], [56, 41], [32, 59]].map(([x, y], i) => _jsx(Circle, { cx: x, cy: y, r: scene.intensity === 3 ? 3.8 : 2.8 }, i)), !scene.windy && _jsx(Path, { d: "M7 33q12-12 24 0t26 0", fill: "none", stroke: scene.atmosphere === "haze" ? ink : "#996b36", strokeWidth: 3.5, strokeLinecap: "round" })] }) : _jsx(G, { fill: "none", stroke: ink, strokeWidth: scene.intensity === 3 ? 5 : 3.5, strokeLinecap: "round", children: scene.atmosphere === "smoke" || scene.atmosphere === "smog" ? _jsx(Path, { d: "M15 56c-15-18 15-19 4-35M32 57c-14-20 19-23 5-44M49 57c-10-14 14-19 4-31" }) : _jsx(Path, { d: "M7 24h17m8 0h25M4 35h38m8 0h10M9 46h15m8 0h23" }) }) }), scene.freezing && _jsxs(G, { transform: "translate(45 22)", children: [_jsx(Path, { d: "M0-10v17m0-17a3 3 0 0 1 6 0v17a7 7 0 1 1-6 0", fill: "#e1f2fa", stroke: blue, strokeWidth: 2.5 }), _jsx(Path, { d: "M3-5v18", stroke: blue, strokeWidth: 3, strokeLinecap: "round" })] }), scene.thunder && _jsx(Path, { d: "M39 26 29 43h10l-5 18 22-27H44l6-8Z", fill: "#df9b36", stroke: "#925510", strokeWidth: 2.5, strokeLinejoin: "round" })] });
|
|
43
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** WeatherAPI condition codes. Composition uses actual conditions, never rain probability. */
|
|
2
|
+
export type WeatherScene = {
|
|
3
|
+
sky: "clear" | "partial" | "cloud" | "none";
|
|
4
|
+
precipitation?: "rain" | "drizzle" | "snow" | "sleet" | "ice";
|
|
5
|
+
intensity?: 1 | 2 | 3;
|
|
6
|
+
freezing?: boolean;
|
|
7
|
+
thunder?: boolean;
|
|
8
|
+
windy?: boolean;
|
|
9
|
+
atmosphere?: "mist" | "fog" | "haze" | "dust" | "sand" | "smoke" | "smog";
|
|
10
|
+
};
|
|
11
|
+
export declare const WEATHER_SCENES: Record<number, WeatherScene>;
|
|
12
|
+
export declare function weatherScene(code?: number, cloud?: number | null, windKph?: number | null): WeatherScene | null;
|
|
13
|
+
/** One precipitation row. Mixed/ice conditions have no separate provider probability. */
|
|
14
|
+
export declare function precipitationMetric(code: number, rain: number | null, snow: number | null): {
|
|
15
|
+
label: string;
|
|
16
|
+
chance: number | null;
|
|
17
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export const WEATHER_SCENES = {
|
|
2
|
+
1000: { sky: "clear" }, 1003: { sky: "partial" },
|
|
3
|
+
1006: { sky: "cloud" }, 1009: { sky: "cloud", intensity: 3 },
|
|
4
|
+
1012: { sky: "clear", atmosphere: "haze" },
|
|
5
|
+
1015: { sky: "clear", atmosphere: "dust" },
|
|
6
|
+
1018: { sky: "none", atmosphere: "dust", windy: true },
|
|
7
|
+
1021: { sky: "none", atmosphere: "dust", windy: true, intensity: 3 },
|
|
8
|
+
1024: { sky: "none", atmosphere: "sand", windy: true },
|
|
9
|
+
1027: { sky: "none", atmosphere: "sand", windy: true, intensity: 3 },
|
|
10
|
+
1030: { sky: "none", atmosphere: "mist" },
|
|
11
|
+
1033: { sky: "none", atmosphere: "smoke" },
|
|
12
|
+
1036: { sky: "clear", atmosphere: "smoke" },
|
|
13
|
+
1039: { sky: "none", atmosphere: "smog" },
|
|
14
|
+
1042: { sky: "none", atmosphere: "smog", intensity: 3 },
|
|
15
|
+
1045: { sky: "none", atmosphere: "dust" },
|
|
16
|
+
1048: { sky: "none", atmosphere: "dust" },
|
|
17
|
+
1063: { sky: "clear", precipitation: "rain", intensity: 1 },
|
|
18
|
+
1066: { sky: "clear", precipitation: "snow", intensity: 1 },
|
|
19
|
+
1069: { sky: "clear", precipitation: "sleet", intensity: 1 },
|
|
20
|
+
1072: { sky: "clear", precipitation: "drizzle", freezing: true },
|
|
21
|
+
1087: { sky: "cloud", thunder: true },
|
|
22
|
+
1114: { sky: "none", precipitation: "snow", windy: true },
|
|
23
|
+
1117: { sky: "none", precipitation: "snow", windy: true, intensity: 3 },
|
|
24
|
+
1135: { sky: "none", atmosphere: "fog" },
|
|
25
|
+
1147: { sky: "none", atmosphere: "fog", freezing: true },
|
|
26
|
+
1150: { sky: "clear", precipitation: "drizzle", intensity: 1 },
|
|
27
|
+
1153: { sky: "none", precipitation: "drizzle", intensity: 1 },
|
|
28
|
+
1168: { sky: "none", precipitation: "drizzle", freezing: true },
|
|
29
|
+
1171: { sky: "none", precipitation: "drizzle", freezing: true, intensity: 3 },
|
|
30
|
+
1180: { sky: "clear", precipitation: "rain", intensity: 1 },
|
|
31
|
+
1183: { sky: "none", precipitation: "rain", intensity: 1 },
|
|
32
|
+
1186: { sky: "clear", precipitation: "rain", intensity: 2 },
|
|
33
|
+
1189: { sky: "none", precipitation: "rain", intensity: 2 },
|
|
34
|
+
1192: { sky: "clear", precipitation: "rain", intensity: 3 },
|
|
35
|
+
1195: { sky: "none", precipitation: "rain", intensity: 3 },
|
|
36
|
+
1198: { sky: "none", precipitation: "rain", freezing: true, intensity: 1 },
|
|
37
|
+
1201: { sky: "none", precipitation: "rain", freezing: true, intensity: 3 },
|
|
38
|
+
1204: { sky: "none", precipitation: "sleet", intensity: 1 },
|
|
39
|
+
1207: { sky: "none", precipitation: "sleet", intensity: 3 },
|
|
40
|
+
1210: { sky: "clear", precipitation: "snow", intensity: 1 },
|
|
41
|
+
1213: { sky: "none", precipitation: "snow", intensity: 1 },
|
|
42
|
+
1216: { sky: "clear", precipitation: "snow", intensity: 2 },
|
|
43
|
+
1219: { sky: "none", precipitation: "snow", intensity: 2 },
|
|
44
|
+
1222: { sky: "clear", precipitation: "snow", intensity: 3 },
|
|
45
|
+
1225: { sky: "none", precipitation: "snow", intensity: 3 },
|
|
46
|
+
1237: { sky: "none", precipitation: "ice" },
|
|
47
|
+
1240: { sky: "clear", precipitation: "rain", intensity: 1 },
|
|
48
|
+
1243: { sky: "clear", precipitation: "rain", intensity: 2 },
|
|
49
|
+
1246: { sky: "clear", precipitation: "rain", intensity: 3 },
|
|
50
|
+
1249: { sky: "clear", precipitation: "sleet", intensity: 1 },
|
|
51
|
+
1252: { sky: "clear", precipitation: "sleet", intensity: 3 },
|
|
52
|
+
1255: { sky: "clear", precipitation: "snow", intensity: 1 },
|
|
53
|
+
1258: { sky: "clear", precipitation: "snow", intensity: 3 },
|
|
54
|
+
1261: { sky: "clear", precipitation: "ice", intensity: 1 },
|
|
55
|
+
1264: { sky: "clear", precipitation: "ice", intensity: 3 },
|
|
56
|
+
1273: { sky: "clear", precipitation: "rain", thunder: true, intensity: 1 },
|
|
57
|
+
1276: { sky: "cloud", precipitation: "rain", thunder: true, intensity: 3 },
|
|
58
|
+
1279: { sky: "clear", precipitation: "snow", thunder: true, intensity: 1 },
|
|
59
|
+
1282: { sky: "cloud", precipitation: "snow", thunder: true, intensity: 3 },
|
|
60
|
+
};
|
|
61
|
+
export function weatherScene(code, cloud, windKph) {
|
|
62
|
+
const base = code === undefined ? undefined : WEATHER_SCENES[code];
|
|
63
|
+
if (!base)
|
|
64
|
+
return null;
|
|
65
|
+
const scene = { ...base };
|
|
66
|
+
// Keep blowing snow/obscuration prominent. Do not add a decorative cloud to every condition.
|
|
67
|
+
if ((scene.precipitation || scene.thunder) && !base.windy && cloud != null && Number.isFinite(cloud) && cloud >= 0 && cloud <= 100) {
|
|
68
|
+
scene.sky = cloud <= 25 ? "clear" : cloud < 75 ? "partial" : "cloud";
|
|
69
|
+
}
|
|
70
|
+
// Visual fresh-breeze threshold, not a weather warning. Canonical km/h in all locales.
|
|
71
|
+
scene.windy = !!scene.windy || (windKph != null && Number.isFinite(windKph) && windKph >= 32);
|
|
72
|
+
return scene;
|
|
73
|
+
}
|
|
74
|
+
/** One precipitation row. Mixed/ice conditions have no separate provider probability. */
|
|
75
|
+
export function precipitationMetric(code, rain, snow) {
|
|
76
|
+
const kind = WEATHER_SCENES[code]?.precipitation;
|
|
77
|
+
if (kind === "snow")
|
|
78
|
+
return { label: "Snow", chance: snow };
|
|
79
|
+
if (kind === "sleet")
|
|
80
|
+
return { label: "Sleet", chance: null };
|
|
81
|
+
if (kind === "ice")
|
|
82
|
+
return { label: "Ice pellets", chance: null };
|
|
83
|
+
if (kind === "rain" || kind === "drizzle")
|
|
84
|
+
return { label: "Rain", chance: rain };
|
|
85
|
+
return snow !== null && snow > (rain ?? 0) ? { label: "Snow", chance: snow } : { label: "Rain", chance: rain };
|
|
86
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// Generated from Messenger by scripts/design/generate-messaging-weather.mjs.
|
|
2
|
+
export const weatherConditions = [{ "code": 1000, "day": "Sunny", "night": "Clear" }, { "code": 1003, "day": "Partly cloudy", "night": "Partly cloudy" }, { "code": 1006, "day": "Cloudy", "night": "Cloudy" }, { "code": 1009, "day": "Overcast", "night": "Overcast" }, { "code": 1012, "day": "Haze", "night": "Haze" }, { "code": 1015, "day": "Dust haze", "night": "Dust haze" }, { "code": 1018, "day": "Blowing dust", "night": "Blowing dust" }, { "code": 1021, "day": "Dust storm", "night": "Dust storm" }, { "code": 1024, "day": "Sandstorm", "night": "Sandstorm" }, { "code": 1027, "day": "Severe sandstorm", "night": "Severe sandstorm" }, { "code": 1030, "day": "Mist", "night": "Mist" }, { "code": 1033, "day": "Smoke", "night": "Smoke" }, { "code": 1036, "day": "Smoky haze", "night": "Smoky haze" }, { "code": 1039, "day": "Smog", "night": "Smog" }, { "code": 1042, "day": "Severe smog", "night": "Severe smog" }, { "code": 1045, "day": "Saharan dust", "night": "Saharan dust" }, { "code": 1048, "day": "Dust", "night": "Dust" }, { "code": 1063, "day": "Patchy rain possible", "night": "Patchy rain possible" }, { "code": 1066, "day": "Patchy snow possible", "night": "Patchy snow possible" }, { "code": 1069, "day": "Patchy sleet possible", "night": "Patchy sleet possible" }, { "code": 1072, "day": "Patchy freezing drizzle possible", "night": "Patchy freezing drizzle possible" }, { "code": 1087, "day": "Thundery outbreaks possible", "night": "Thundery outbreaks possible" }, { "code": 1114, "day": "Blowing snow", "night": "Blowing snow" }, { "code": 1117, "day": "Blizzard", "night": "Blizzard" }, { "code": 1135, "day": "Fog", "night": "Fog" }, { "code": 1147, "day": "Freezing fog", "night": "Freezing fog" }, { "code": 1150, "day": "Patchy light drizzle", "night": "Patchy light drizzle" }, { "code": 1153, "day": "Light drizzle", "night": "Light drizzle" }, { "code": 1168, "day": "Freezing drizzle", "night": "Freezing drizzle" }, { "code": 1171, "day": "Heavy freezing drizzle", "night": "Heavy freezing drizzle" }, { "code": 1180, "day": "Patchy light rain", "night": "Patchy light rain" }, { "code": 1183, "day": "Light rain", "night": "Light rain" }, { "code": 1186, "day": "Moderate rain at times", "night": "Moderate rain at times" }, { "code": 1189, "day": "Moderate rain", "night": "Moderate rain" }, { "code": 1192, "day": "Heavy rain at times", "night": "Heavy rain at times" }, { "code": 1195, "day": "Heavy rain", "night": "Heavy rain" }, { "code": 1198, "day": "Light freezing rain", "night": "Light freezing rain" }, { "code": 1201, "day": "Moderate or heavy freezing rain", "night": "Moderate or heavy freezing rain" }, { "code": 1204, "day": "Light sleet", "night": "Light sleet" }, { "code": 1207, "day": "Moderate or heavy sleet", "night": "Moderate or heavy sleet" }, { "code": 1210, "day": "Patchy light snow", "night": "Patchy light snow" }, { "code": 1213, "day": "Light snow", "night": "Light snow" }, { "code": 1216, "day": "Patchy moderate snow", "night": "Patchy moderate snow" }, { "code": 1219, "day": "Moderate snow", "night": "Moderate snow" }, { "code": 1222, "day": "Patchy heavy snow", "night": "Patchy heavy snow" }, { "code": 1225, "day": "Heavy snow", "night": "Heavy snow" }, { "code": 1237, "day": "Ice pellets", "night": "Ice pellets" }, { "code": 1240, "day": "Light rain shower", "night": "Light rain shower" }, { "code": 1243, "day": "Moderate or heavy rain shower", "night": "Moderate or heavy rain shower" }, { "code": 1246, "day": "Torrential rain shower", "night": "Torrential rain shower" }, { "code": 1249, "day": "Light sleet showers", "night": "Light sleet showers" }, { "code": 1252, "day": "Moderate or heavy sleet showers", "night": "Moderate or heavy sleet showers" }, { "code": 1255, "day": "Light snow showers", "night": "Light snow showers" }, { "code": 1258, "day": "Moderate or heavy snow showers", "night": "Moderate or heavy snow showers" }, { "code": 1261, "day": "Light showers of ice pellets", "night": "Light showers of ice pellets" }, { "code": 1264, "day": "Moderate or heavy showers of ice pellets", "night": "Moderate or heavy showers of ice pellets" }, { "code": 1273, "day": "Patchy light rain with thunder", "night": "Patchy light rain with thunder" }, { "code": 1276, "day": "Moderate or heavy rain with thunder", "night": "Moderate or heavy rain with thunder" }, { "code": 1279, "day": "Patchy light snow with thunder", "night": "Patchy light snow with thunder" }, { "code": 1282, "day": "Moderate or heavy snow with thunder", "night": "Moderate or heavy snow with thunder" }];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Messenger playback display normalization; never changes the stored recording. */
|
|
2
|
+
export function messengerVoiceWaveform(value, durationMs) {
|
|
3
|
+
const count = 32, valid = value?.slice(0, 80);
|
|
4
|
+
if (valid?.length && valid.every(n => Number.isFinite(n) && n >= 0)) {
|
|
5
|
+
const levels = valid.map(n => Math.min(1, n));
|
|
6
|
+
const sampled = Array.from({ length: count }, (_, i) => {
|
|
7
|
+
if (levels.length >= count) {
|
|
8
|
+
const start = Math.floor(i / count * levels.length), end = Math.max(start + 1, Math.floor((i + 1) / count * levels.length));
|
|
9
|
+
return Math.max(...levels.slice(start, end));
|
|
10
|
+
}
|
|
11
|
+
const p = i / (count - 1) * (levels.length - 1), a = Math.floor(p), b = Math.ceil(p);
|
|
12
|
+
return levels[a] + (levels[b] - levels[a]) * (p - a);
|
|
13
|
+
});
|
|
14
|
+
const peak = Math.max(...sampled);
|
|
15
|
+
if (peak > .001)
|
|
16
|
+
return sampled.map(n => n <= .001 ? .035 : Math.max(.055, Math.min(1, Math.pow(n / peak, .72))));
|
|
17
|
+
}
|
|
18
|
+
// Same visual fallback as Messenger for older recordings without waveform data.
|
|
19
|
+
const factor = Math.max(.75, Math.min((durationMs || 2200) / 2800, 1.35));
|
|
20
|
+
return Array.from({ length: count }, (_, i) => Math.max(.08, Math.min(.9, Math.sin(Math.PI * i / (count - 1)) * (.38 + .34 * Math.sin((i + 1) * 1.73 * factor) + .18 * Math.sin((i + 3) * .67)))));
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robono/messaging-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Optional, composable direct and group messaging screens for Robono.",
|
|
@@ -28,7 +28,15 @@
|
|
|
28
28
|
"import": "./dist/expo-calling.js"
|
|
29
29
|
},
|
|
30
30
|
"./app.plugin": "./app.plugin.cjs",
|
|
31
|
-
"./app.plugin.cjs": "./app.plugin.cjs"
|
|
31
|
+
"./app.plugin.cjs": "./app.plugin.cjs",
|
|
32
|
+
"./expo-privacy": {
|
|
33
|
+
"types": "./dist/expo-privacy.d.ts",
|
|
34
|
+
"import": "./dist/expo-privacy.js"
|
|
35
|
+
},
|
|
36
|
+
"./expo-notifications": {
|
|
37
|
+
"types": "./dist/expo-notifications.d.ts",
|
|
38
|
+
"import": "./dist/expo-notifications.js"
|
|
39
|
+
}
|
|
32
40
|
},
|
|
33
41
|
"files": [
|
|
34
42
|
"dist",
|
|
@@ -45,7 +53,7 @@
|
|
|
45
53
|
"prepack": "npm run build && node ../../scripts/generate-sdk-file-sbom.mjs"
|
|
46
54
|
},
|
|
47
55
|
"peerDependencies": {
|
|
48
|
-
"@robono/messaging": "^0.
|
|
56
|
+
"@robono/messaging": "^0.3.0",
|
|
49
57
|
"react": ">=18.2 <20",
|
|
50
58
|
"react-native": ">=0.76 <1",
|
|
51
59
|
"expo-audio": ">=55 <57",
|
|
@@ -61,7 +69,10 @@
|
|
|
61
69
|
"expo-clipboard": ">=8 <57",
|
|
62
70
|
"expo-image-manipulator": ">=14 <57",
|
|
63
71
|
"expo-video-thumbnails": ">=14 <57",
|
|
64
|
-
"react-native-webview": ">=13 <14"
|
|
72
|
+
"react-native-webview": ">=13 <14",
|
|
73
|
+
"expo-blur": ">=55 <57",
|
|
74
|
+
"expo-notifications": ">=55 <57",
|
|
75
|
+
"expo-secure-store": ">=55 <57"
|
|
65
76
|
},
|
|
66
77
|
"license": "SEE LICENSE IN LICENSE",
|
|
67
78
|
"peerDependenciesMeta": {
|
|
@@ -103,6 +114,15 @@
|
|
|
103
114
|
},
|
|
104
115
|
"react-native-webview": {
|
|
105
116
|
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"expo-blur": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"expo-notifications": {
|
|
122
|
+
"optional": true
|
|
123
|
+
},
|
|
124
|
+
"expo-secure-store": {
|
|
125
|
+
"optional": true
|
|
106
126
|
}
|
|
107
127
|
},
|
|
108
128
|
"author": {
|