@ethora/chat-component-rn 26.6.11 → 26.6.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/lib/commonjs/components/MainComponents/MediaMessage.js +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/InteractionsOverlay.js +1 -1
- package/lib/commonjs/components/MessageBubble/InteractionsOverlay.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +7 -4
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/GViewWebView.js +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/GViewWebView.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/VideoCallSession.js +6 -3
- package/lib/commonjs/components/VideoCalls/VideoCallSession.js.map +1 -1
- package/lib/commonjs/components/styled/MediaFilePreview.js +1 -1
- package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +29 -63
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MessageBubble/InteractionsOverlay.js +1 -1
- package/lib/module/components/MessageBubble/InteractionsOverlay.js.map +1 -1
- package/lib/module/components/MessageBubble/Message.js +1 -1
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +7 -4
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/GViewWebView.js +1 -1
- package/lib/module/components/Modals/FilePreviewModal/GViewWebView.js.map +1 -1
- package/lib/module/components/VideoCalls/VideoCallSession.js +6 -3
- package/lib/module/components/VideoCalls/VideoCallSession.js.map +1 -1
- package/lib/module/components/styled/MediaFilePreview.js +1 -1
- package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +29 -63
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts.map +1 -1
- package/lib/typescript/components/styled/VideoMessage.d.ts.map +1 -1
- package/lib/typescript/hooks/useCustomTypingIndicator.d.ts +16 -4
- package/lib/typescript/hooks/useCustomTypingIndicator.d.ts.map +1 -1
- package/package.json +29 -28
- package/src/components/MainComponents/MediaMessage.tsx +1 -1
- package/src/components/MessageBubble/InteractionsOverlay.tsx +1 -1
- package/src/components/MessageBubble/Message.tsx +1 -1
- package/src/components/MessageBubble/MessageInteractions.tsx +1 -1
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +6 -3
- package/src/components/Modals/FilePreviewModal/GViewWebView.tsx +1 -1
- package/src/components/VideoCalls/VideoCallSession.tsx +8 -3
- package/src/components/styled/MediaFilePreview.tsx +1 -1
- package/src/components/styled/VideoMessage.tsx +26 -59
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethora/chat-component-rn",
|
|
3
|
-
"version": "26.6.
|
|
3
|
+
"version": "26.6.12",
|
|
4
4
|
"description": "Drop-in XMPP chat component for React Native / Expo. <Chat config={...}/> and you're done.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "lib/module/main.js",
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
"@xmpp/client": "^0.13.1",
|
|
140
140
|
"axios": "^1.7.9",
|
|
141
141
|
"js-sha256": "^0.11.0",
|
|
142
|
-
"react-native-keyboard-controller": "^1.
|
|
142
|
+
"react-native-keyboard-controller": "^1.22.3",
|
|
143
143
|
"react-native-webview": "^13.16.1",
|
|
144
144
|
"react-redux": "^9.2.0",
|
|
145
145
|
"styled-components": "^6.1.13"
|
|
@@ -148,44 +148,45 @@
|
|
|
148
148
|
"@babel/core": "^7.25.2",
|
|
149
149
|
"@babel/preset-env": "^7.25.3",
|
|
150
150
|
"@babel/runtime": "^7.25.0",
|
|
151
|
-
"@livekit/react-native": "2.
|
|
152
|
-
"@livekit/react-native-webrtc": "
|
|
151
|
+
"@livekit/react-native": "2.12.0",
|
|
152
|
+
"@livekit/react-native-webrtc": "144.1.2",
|
|
153
153
|
"@react-native-async-storage/async-storage": "2.2.0",
|
|
154
|
-
"@react-native-community/netinfo": "
|
|
154
|
+
"@react-native-community/netinfo": "12.0.1",
|
|
155
|
+
"@react-native/eslint-config": "^0.86.2",
|
|
155
156
|
"@types/jest": "^29.5.12",
|
|
156
|
-
"@types/react": "~19.
|
|
157
|
+
"@types/react": "~19.2.0",
|
|
157
158
|
"@types/react-test-renderer": "^19.1.0",
|
|
158
159
|
"babel-jest": "^29.6.3",
|
|
159
160
|
"eslint": "^8.19.0",
|
|
160
|
-
"eslint-config-expo": "~
|
|
161
|
-
"expo": "~
|
|
162
|
-
"expo-audio": "~
|
|
163
|
-
"expo-build-properties": "
|
|
164
|
-
"expo-clipboard": "~
|
|
165
|
-
"expo-document-picker": "~
|
|
166
|
-
"expo-image-manipulator": "~
|
|
167
|
-
"expo-image-picker": "~
|
|
168
|
-
"expo-media-library": "~
|
|
169
|
-
"expo-status-bar": "~
|
|
170
|
-
"expo-video": "~
|
|
161
|
+
"eslint-config-expo": "~57.0.1",
|
|
162
|
+
"expo": "~57.0.0",
|
|
163
|
+
"expo-audio": "~57.0.3",
|
|
164
|
+
"expo-build-properties": "~57.0.10",
|
|
165
|
+
"expo-clipboard": "~57.0.1",
|
|
166
|
+
"expo-document-picker": "~57.0.1",
|
|
167
|
+
"expo-image-manipulator": "~57.0.9",
|
|
168
|
+
"expo-image-picker": "~57.0.9",
|
|
169
|
+
"expo-media-library": "~57.0.3",
|
|
170
|
+
"expo-status-bar": "~57.0.1",
|
|
171
|
+
"expo-video": "~57.0.2",
|
|
171
172
|
"jest": "^29.6.3",
|
|
172
|
-
"jest-expo": "~
|
|
173
|
-
"livekit-client": "2.
|
|
173
|
+
"jest-expo": "~57.0.4",
|
|
174
|
+
"livekit-client": "2.21.0",
|
|
174
175
|
"patch-package": "^8.0.1",
|
|
175
176
|
"prettier": "2.8.8",
|
|
176
|
-
"react": "19.
|
|
177
|
-
"react-native": "0.
|
|
177
|
+
"react": "19.2.8",
|
|
178
|
+
"react-native": "0.86.2",
|
|
178
179
|
"react-native-builder-bob": "^0.41.0",
|
|
179
180
|
"react-native-callkeep": "4.3.16",
|
|
180
|
-
"react-native-gesture-handler": "~2.
|
|
181
|
+
"react-native-gesture-handler": "~2.32.0",
|
|
181
182
|
"react-native-get-random-values": "~1.11.0",
|
|
182
|
-
"react-native-reanimated": "~4.1
|
|
183
|
-
"react-native-safe-area-context": "~5.
|
|
184
|
-
"react-native-screens": "~4.
|
|
185
|
-
"react-native-svg": "15.
|
|
186
|
-
"react-native-worklets": "~0.
|
|
183
|
+
"react-native-reanimated": "~4.5.1",
|
|
184
|
+
"react-native-safe-area-context": "~5.7.0",
|
|
185
|
+
"react-native-screens": "~4.26.0",
|
|
186
|
+
"react-native-svg": "15.15.4",
|
|
187
|
+
"react-native-worklets": "~0.10.1",
|
|
187
188
|
"react-qr-code": "^2.0.15",
|
|
188
|
-
"react-test-renderer": "19.
|
|
189
|
+
"react-test-renderer": "19.2.8",
|
|
189
190
|
"typescript": "~5.9.0"
|
|
190
191
|
},
|
|
191
192
|
"engines": {
|
|
@@ -115,7 +115,7 @@ export const InteractionsOverlayProvider: React.FC<{
|
|
|
115
115
|
|
|
116
116
|
const styles = StyleSheet.create({
|
|
117
117
|
host: { flex: 1 },
|
|
118
|
-
overlay: { ...StyleSheet.
|
|
118
|
+
overlay: { ...StyleSheet.absoluteFill, zIndex: 9999, elevation: 9999 },
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
export default InteractionsOverlayProvider;
|
|
@@ -82,7 +82,10 @@ const ModalVideo: React.FC<{ uri: string }> = ({ uri }) => {
|
|
|
82
82
|
contentFit="contain"
|
|
83
83
|
nativeControls
|
|
84
84
|
surfaceType="textureView"
|
|
85
|
-
|
|
85
|
+
// Fullscreen stays available by default on both expo-video lines:
|
|
86
|
+
// `allowsFullscreen` (SDK 54, default true) was replaced by
|
|
87
|
+
// `fullscreenOptions.enable` (SDK 57, default true). Passing neither
|
|
88
|
+
// keeps this file compiling against both.
|
|
86
89
|
/>
|
|
87
90
|
{/* Play affordance shown immediately on open; tapping starts
|
|
88
91
|
playback and the native controls take over. */}
|
|
@@ -90,7 +93,7 @@ const ModalVideo: React.FC<{ uri: string }> = ({ uri }) => {
|
|
|
90
93
|
<TouchableOpacity
|
|
91
94
|
activeOpacity={0.8}
|
|
92
95
|
onPress={handlePlay}
|
|
93
|
-
style={StyleSheet.
|
|
96
|
+
style={StyleSheet.absoluteFill}
|
|
94
97
|
>
|
|
95
98
|
<View style={styles.playOverlay}>
|
|
96
99
|
<View style={styles.playButton}>
|
|
@@ -426,7 +429,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
426
429
|
|
|
427
430
|
const styles = StyleSheet.create({
|
|
428
431
|
playOverlay: {
|
|
429
|
-
...StyleSheet.
|
|
432
|
+
...StyleSheet.absoluteFill,
|
|
430
433
|
justifyContent: 'center',
|
|
431
434
|
alignItems: 'center',
|
|
432
435
|
},
|
|
@@ -134,7 +134,7 @@ const styles = StyleSheet.create({
|
|
|
134
134
|
container: { flex: 1, width: '100%', backgroundColor: '#fff' },
|
|
135
135
|
webview: { flex: 1, backgroundColor: '#fff' },
|
|
136
136
|
loadingOverlay: {
|
|
137
|
-
...StyleSheet.
|
|
137
|
+
...StyleSheet.absoluteFill,
|
|
138
138
|
justifyContent: 'center',
|
|
139
139
|
alignItems: 'center',
|
|
140
140
|
backgroundColor: '#ffffff',
|
|
@@ -345,9 +345,14 @@ export const VideoCallSession: FC<VideoCallSessionProps> = ({
|
|
|
345
345
|
if (!runtime) {return;}
|
|
346
346
|
try {
|
|
347
347
|
if (Platform.OS === 'android') {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
348
|
+
// NB: not `setAndroidAudioConfiguration` — that method has never
|
|
349
|
+
// existed on AudioSession (the old `?.` call silently no-oped, so
|
|
350
|
+
// the speaker icon toggled while audio stayed on the earpiece).
|
|
351
|
+
// `selectAudioOutput` routes directly; on Android its device ids
|
|
352
|
+
// are the literal strings 'speaker' / 'earpiece'.
|
|
353
|
+
await runtime.AudioSession.selectAudioOutput(
|
|
354
|
+
next ? 'speaker' : 'earpiece'
|
|
355
|
+
);
|
|
351
356
|
} else {
|
|
352
357
|
await runtime.AudioSession.setAppleAudioConfiguration?.({
|
|
353
358
|
audioCategory: 'playAndRecord',
|
|
@@ -110,7 +110,7 @@ const styles = StyleSheet.create({
|
|
|
110
110
|
backgroundColor: '#1a1a1a',
|
|
111
111
|
},
|
|
112
112
|
playOverlay: {
|
|
113
|
-
...StyleSheet.
|
|
113
|
+
...StyleSheet.absoluteFill,
|
|
114
114
|
justifyContent: 'center',
|
|
115
115
|
alignItems: 'center',
|
|
116
116
|
backgroundColor: 'rgba(0,0,0,0.3)',
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { Image, Pressable, StyleSheet, View } from 'react-native';
|
|
3
|
-
import { useVideoPlayer, VideoView } from 'expo-video';
|
|
4
3
|
import { useDispatch } from 'react-redux';
|
|
5
4
|
import {
|
|
6
5
|
setActiveFile,
|
|
@@ -37,12 +36,6 @@ const PlayBadge: React.FC = () => (
|
|
|
37
36
|
* playback happens in the full-screen preview. Drawing that still with a
|
|
38
37
|
* plain <Image> keeps the whole bubble inside the RN view hierarchy, so
|
|
39
38
|
* the play badge is guaranteed to composite on top of it.
|
|
40
|
-
*
|
|
41
|
-
* The VideoView path below cannot make that promise: expo-video draws
|
|
42
|
-
* into a native surface, and depending on platform, expo-video version
|
|
43
|
-
* and surfaceType that surface can end up above its sibling RN views —
|
|
44
|
-
* swallowing the badge and leaving the video looking like a plain photo.
|
|
45
|
-
* It is also cheaper: no video player instance per row in a long list.
|
|
46
39
|
*/
|
|
47
40
|
const PosterVideo: React.FC<{
|
|
48
41
|
previewURL: string;
|
|
@@ -85,8 +78,8 @@ const PosterVideo: React.FC<{
|
|
|
85
78
|
resizeMode="cover"
|
|
86
79
|
// Not every backend returns a real still — some set
|
|
87
80
|
// locationPreview to the video URL itself, which decodes to
|
|
88
|
-
// nothing. Rather than show an empty box,
|
|
89
|
-
//
|
|
81
|
+
// nothing. Rather than show an empty box, fall back to the
|
|
82
|
+
// static placeholder branch.
|
|
90
83
|
onError={onPosterError}
|
|
91
84
|
/>
|
|
92
85
|
<PlayBadge />
|
|
@@ -95,61 +88,35 @@ const PosterVideo: React.FC<{
|
|
|
95
88
|
};
|
|
96
89
|
|
|
97
90
|
/**
|
|
98
|
-
* Fallback for messages with no usable poster frame:
|
|
99
|
-
*
|
|
91
|
+
* Fallback for messages with no usable poster frame: a static dark
|
|
92
|
+
* placeholder behind the play badge.
|
|
93
|
+
*
|
|
94
|
+
* This branch used to mount an expo-video player purely to paint the
|
|
95
|
+
* first frame (`VideoView` + `surfaceType="textureView"`). That never
|
|
96
|
+
* composited reliably: on Android (Pixel, Android 16, New Architecture)
|
|
97
|
+
* the native video surface draws ABOVE sibling RN views, swallowing the
|
|
98
|
+
* play badge — the video looked like a plain photo. There is no
|
|
99
|
+
* surfaceType/zIndex combination that guarantees ordering across SDK 54
|
|
100
|
+
* and 57, so we don't fight it: no live surface in the bubble at all.
|
|
101
|
+
* The badge is plain RN views over a plain RN background, which cannot
|
|
102
|
+
* be occluded, and we drop the per-row player instance as a bonus.
|
|
103
|
+
* Actual playback (and the real first frame) happens in the full-screen
|
|
104
|
+
* preview modal.
|
|
100
105
|
*/
|
|
101
|
-
const
|
|
102
|
-
fileURL: string;
|
|
106
|
+
const PlaceholderVideo: React.FC<{
|
|
103
107
|
onOpen: () => void;
|
|
104
|
-
}> = ({
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
const player = useVideoPlayer(fileURL, (p) => {
|
|
108
|
-
p.muted = true;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
useEffect(() => {
|
|
112
|
-
const sub = player.addListener('statusChange', () => {
|
|
113
|
-
const size = player.videoTrack?.size;
|
|
114
|
-
if (size?.width && size?.height) {
|
|
115
|
-
setDims(fitMediaDimensions(size.width, size.height));
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
return () => sub.remove();
|
|
119
|
-
}, [player]);
|
|
108
|
+
}> = ({ onOpen }) => {
|
|
109
|
+
const dims = defaultMediaDims();
|
|
120
110
|
|
|
121
111
|
return (
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// top owns the tap. Previously we wrapped VideoView in a
|
|
125
|
-
// TouchableOpacity and set `pointerEvents="none"` on the inner
|
|
126
|
-
// VideoView — but on some expo-video versions / iOS the native
|
|
127
|
-
// VideoView still intercepted gestures despite that hint, so
|
|
128
|
-
// tapping the poster did nothing. Customer-reported #9 (video
|
|
129
|
-
// preview unresponsive). The Pressable now guarantees the tap
|
|
130
|
-
// reaches `onOpen`.
|
|
131
|
-
<View
|
|
112
|
+
<Pressable
|
|
113
|
+
onPress={onOpen}
|
|
132
114
|
style={[styles.wrapper, { width: dims.width, height: dims.height }]}
|
|
115
|
+
accessibilityRole="button"
|
|
116
|
+
accessibilityLabel="Play video"
|
|
133
117
|
>
|
|
134
|
-
<VideoView
|
|
135
|
-
player={player}
|
|
136
|
-
style={styles.video}
|
|
137
|
-
contentFit="cover"
|
|
138
|
-
nativeControls={false}
|
|
139
|
-
surfaceType="textureView"
|
|
140
|
-
pointerEvents="none"
|
|
141
|
-
/>
|
|
142
118
|
<PlayBadge />
|
|
143
|
-
|
|
144
|
-
onPress={onOpen}
|
|
145
|
-
// Sits ON TOP of VideoView + the play-button overlay; transparent
|
|
146
|
-
// so the poster + play icon show through. Captures the tap and
|
|
147
|
-
// routes to onOpen → setActiveModal(FILE_PREVIEW).
|
|
148
|
-
style={StyleSheet.absoluteFill}
|
|
149
|
-
accessibilityRole="button"
|
|
150
|
-
accessibilityLabel="Play video"
|
|
151
|
-
/>
|
|
152
|
-
</View>
|
|
119
|
+
</Pressable>
|
|
153
120
|
);
|
|
154
121
|
};
|
|
155
122
|
|
|
@@ -177,7 +144,7 @@ const CustomMessageVideo: React.FC<CustomMessageVideoProps> = ({
|
|
|
177
144
|
);
|
|
178
145
|
}
|
|
179
146
|
|
|
180
|
-
return <
|
|
147
|
+
return <PlaceholderVideo onOpen={handleOpen} />;
|
|
181
148
|
};
|
|
182
149
|
|
|
183
150
|
export default CustomMessageVideo;
|
|
@@ -193,7 +160,7 @@ const styles = StyleSheet.create({
|
|
|
193
160
|
height: '100%',
|
|
194
161
|
},
|
|
195
162
|
overlay: {
|
|
196
|
-
...StyleSheet.
|
|
163
|
+
...StyleSheet.absoluteFill,
|
|
197
164
|
justifyContent: 'center',
|
|
198
165
|
alignItems: 'center',
|
|
199
166
|
},
|