@ethora/chat-component-rn 26.5.4 → 26.5.7
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 +66 -0
- package/README.md +25 -4
- package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js +1 -7
- package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js +7 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +8 -2
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +2 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +11 -5
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +10 -2
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js +60 -7
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +1 -38
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +20 -28
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +35 -16
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js +11 -2
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageEmoji.js +9 -6
- package/lib/commonjs/components/RoomComponents/styled/LastMessageEmoji.js.map +1 -1
- package/lib/commonjs/components/UsersList/Checkbox.js +68 -0
- package/lib/commonjs/components/UsersList/Checkbox.js.map +1 -0
- package/lib/commonjs/components/UsersList/StyledComponents.js +1 -7
- package/lib/commonjs/components/UsersList/StyledComponents.js.map +1 -1
- package/lib/commonjs/components/UsersList/UsersList.js +3 -1
- package/lib/commonjs/components/UsersList/UsersList.js.map +1 -1
- package/lib/commonjs/components/styled/MediaFilePreview.js +96 -5
- package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/commonjs/components/styled/MessageImage.js +1 -2
- package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +4 -2
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +2 -10
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +71 -2
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/mimeToExtension.js +131 -0
- package/lib/commonjs/helpers/mimeToExtension.js.map +1 -0
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js +73 -1
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/commonjs/hooks/useChatWrapperInit.js +22 -10
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/commonjs/hooks/useEventHandlers.js +9 -1
- package/lib/commonjs/hooks/useEventHandlers.js.map +1 -1
- package/lib/commonjs/hooks/useMessageHeapState.js +6 -2
- package/lib/commonjs/hooks/useMessageHeapState.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +48 -4
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/networking/api-requests/auth.api.js +7 -1
- package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +87 -1
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/roomHeapSlice.js +26 -8
- package/lib/commonjs/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/module/components/ContextMenu/ContextMenuComponents.js +0 -6
- package/lib/module/components/ContextMenu/ContextMenuComponents.js.map +1 -1
- package/lib/module/components/MainComponents/ChatHeader.js +7 -1
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +8 -2
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +2 -1
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +11 -5
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +11 -3
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/MessageBubble/Message.js +60 -7
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +3 -40
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +21 -29
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +36 -17
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js +11 -2
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessageEmoji.js +9 -6
- package/lib/module/components/RoomComponents/styled/LastMessageEmoji.js.map +1 -1
- package/lib/module/components/UsersList/Checkbox.js +63 -0
- package/lib/module/components/UsersList/Checkbox.js.map +1 -0
- package/lib/module/components/UsersList/StyledComponents.js +0 -6
- package/lib/module/components/UsersList/StyledComponents.js.map +1 -1
- package/lib/module/components/UsersList/UsersList.js +2 -1
- package/lib/module/components/UsersList/UsersList.js.map +1 -1
- package/lib/module/components/styled/MediaFilePreview.js +97 -6
- package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/module/components/styled/MessageImage.js +1 -2
- package/lib/module/components/styled/MessageImage.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +4 -2
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +2 -10
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/context/xmppProvider.js +73 -3
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/mimeToExtension.js +124 -0
- package/lib/module/helpers/mimeToExtension.js.map +1 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js +71 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/module/hooks/useChatWrapperInit.js +22 -10
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/module/hooks/useEventHandlers.js +9 -1
- package/lib/module/hooks/useEventHandlers.js.map +1 -1
- package/lib/module/hooks/useMessageHeapState.js +6 -2
- package/lib/module/hooks/useMessageHeapState.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +49 -5
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/networking/api-requests/auth.api.js +7 -1
- package/lib/module/networking/api-requests/auth.api.js.map +1 -1
- package/lib/module/networking/xmppClient.js +87 -1
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/roomHeapSlice.js +24 -7
- package/lib/module/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts +0 -1
- package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts +6 -0
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageEmoji.d.ts +8 -0
- package/lib/typescript/components/RoomComponents/styled/LastMessageEmoji.d.ts.map +1 -1
- package/lib/typescript/components/UsersList/Checkbox.d.ts +16 -0
- package/lib/typescript/components/UsersList/Checkbox.d.ts.map +1 -0
- package/lib/typescript/components/UsersList/StyledComponents.d.ts +0 -1
- package/lib/typescript/components/UsersList/StyledComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/MediaFilePreview.d.ts.map +1 -1
- package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/mimeToExtension.d.ts +37 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts +18 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- package/lib/typescript/hooks/useEventHandlers.d.ts +6 -0
- package/lib/typescript/hooks/useEventHandlers.d.ts.map +1 -1
- package/lib/typescript/hooks/useMessageHeapState.d.ts +2 -0
- package/lib/typescript/hooks/useMessageHeapState.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts +2 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +25 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts +22 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +6 -0
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/metro.js +17 -57
- package/package.json +1 -1
- package/src/components/ContextMenu/ContextMenuComponents.tsx +0 -7
- package/src/components/MainComponents/ChatHeader.tsx +5 -1
- package/src/components/MainComponents/ChatRoom.tsx +6 -1
- package/src/components/MainComponents/ChatWrapper.tsx +1 -0
- package/src/components/MainComponents/MediaMessage.tsx +15 -8
- package/src/components/MainComponents/MessageList.tsx +10 -3
- package/src/components/MessageBubble/Message.tsx +64 -10
- package/src/components/MessageBubble/MessageInteractions.tsx +2 -105
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +20 -41
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +30 -12
- package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +22 -1
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +1 -1
- package/src/components/RoomComponents/styled/LastMessageEmoji.tsx +9 -7
- package/src/components/UsersList/Checkbox.tsx +68 -0
- package/src/components/UsersList/StyledComponents.ts +0 -8
- package/src/components/UsersList/UsersList.tsx +1 -1
- package/src/components/styled/MediaFilePreview.tsx +91 -5
- package/src/components/styled/MessageImage.tsx +1 -2
- package/src/components/styled/SendInput.tsx +3 -0
- package/src/components/styled/VideoMessage.tsx +3 -10
- package/src/context/xmppProvider.tsx +90 -2
- package/src/helpers/mimeToExtension.ts +135 -0
- package/src/helpers/resolveInitBeforeLoadUser.ts +79 -0
- package/src/hooks/useChatWrapperInit.ts +51 -46
- package/src/hooks/useEventHandlers.tsx +24 -1
- package/src/hooks/useMessageHeapState.tsx +6 -2
- package/src/hooks/useSendMessage.tsx +75 -4
- package/src/networking/api-requests/auth.api.ts +5 -1
- package/src/networking/xmppClient.ts +95 -1
- package/src/roomStore/roomHeapSlice.ts +47 -4
- package/src/types/types.ts +10 -0
- package/lib/commonjs/components/InputComponents/AudioInput.js +0 -23
- package/lib/commonjs/components/InputComponents/AudioInput.js.map +0 -1
- package/lib/commonjs/components/InputComponents/AudioRecorder.js +0 -101
- package/lib/commonjs/components/InputComponents/AudioRecorder.js.map +0 -1
- package/lib/commonjs/components/InputComponents/MediaInput.js +0 -98
- package/lib/commonjs/components/InputComponents/MediaInput.js.map +0 -1
- package/lib/commonjs/components/InputComponents/RecordingIndicator.js +0 -70
- package/lib/commonjs/components/InputComponents/RecordingIndicator.js.map +0 -1
- package/lib/commonjs/components/Modals/ModalSelectMedia/ModalSelectMedia.js +0 -207
- package/lib/commonjs/components/Modals/ModalSelectMedia/ModalSelectMedia.js.map +0 -1
- package/lib/commonjs/components/OperationalModal/OperationalModal.js +0 -83
- package/lib/commonjs/components/OperationalModal/OperationalModal.js.map +0 -1
- package/lib/module/components/InputComponents/AudioInput.js +0 -18
- package/lib/module/components/InputComponents/AudioInput.js.map +0 -1
- package/lib/module/components/InputComponents/AudioRecorder.js +0 -95
- package/lib/module/components/InputComponents/AudioRecorder.js.map +0 -1
- package/lib/module/components/InputComponents/MediaInput.js +0 -92
- package/lib/module/components/InputComponents/MediaInput.js.map +0 -1
- package/lib/module/components/InputComponents/RecordingIndicator.js +0 -65
- package/lib/module/components/InputComponents/RecordingIndicator.js.map +0 -1
- package/lib/module/components/Modals/ModalSelectMedia/ModalSelectMedia.js +0 -200
- package/lib/module/components/Modals/ModalSelectMedia/ModalSelectMedia.js.map +0 -1
- package/lib/module/components/OperationalModal/OperationalModal.js +0 -77
- package/lib/module/components/OperationalModal/OperationalModal.js.map +0 -1
- package/lib/typescript/components/InputComponents/AudioInput.d.ts +0 -9
- package/lib/typescript/components/InputComponents/AudioInput.d.ts.map +0 -1
- package/lib/typescript/components/InputComponents/AudioRecorder.d.ts +0 -9
- package/lib/typescript/components/InputComponents/AudioRecorder.d.ts.map +0 -1
- package/lib/typescript/components/InputComponents/MediaInput.d.ts +0 -16
- package/lib/typescript/components/InputComponents/MediaInput.d.ts.map +0 -1
- package/lib/typescript/components/InputComponents/RecordingIndicator.d.ts +0 -4
- package/lib/typescript/components/InputComponents/RecordingIndicator.d.ts.map +0 -1
- package/lib/typescript/components/Modals/ModalSelectMedia/ModalSelectMedia.d.ts +0 -9
- package/lib/typescript/components/Modals/ModalSelectMedia/ModalSelectMedia.d.ts.map +0 -1
- package/lib/typescript/components/OperationalModal/OperationalModal.d.ts +0 -9
- package/lib/typescript/components/OperationalModal/OperationalModal.d.ts.map +0 -1
- package/src/components/InputComponents/AudioInput.tsx +0 -24
- package/src/components/InputComponents/AudioRecorder.tsx +0 -100
- package/src/components/InputComponents/MediaInput.tsx +0 -113
- package/src/components/InputComponents/RecordingIndicator.tsx +0 -77
- package/src/components/Modals/ModalSelectMedia/ModalSelectMedia.tsx +0 -283
- package/src/components/OperationalModal/OperationalModal.tsx +0 -78
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { View } from 'react-native';
|
|
1
|
+
import { View, Text, StyleSheet, Modal, TouchableOpacity, SafeAreaView } from 'react-native';
|
|
2
2
|
import {
|
|
3
3
|
MediaContainer,
|
|
4
4
|
MediaImage,
|
|
5
5
|
} from './StyledInputComponents/StyledInputComponents';
|
|
6
6
|
import { FileIcon } from '../../assets/icons';
|
|
7
7
|
import { RemoveButton, RemoveButtonText } from './StyledComponents';
|
|
8
|
-
import { FC } from 'react';
|
|
8
|
+
import { FC, useState } from 'react';
|
|
9
9
|
import { MediaFile } from '../../types/types';
|
|
10
|
+
import { Video, ResizeMode } from 'expo-av';
|
|
10
11
|
|
|
11
12
|
interface MediaFilePreviewProps {
|
|
12
13
|
filePreviews: MediaFile[];
|
|
@@ -17,15 +18,34 @@ export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
|
|
|
17
18
|
filePreviews,
|
|
18
19
|
handleRemoveImage,
|
|
19
20
|
}) => {
|
|
21
|
+
const [previewUri, setPreviewUri] = useState<string | null>(null);
|
|
22
|
+
|
|
20
23
|
return (
|
|
21
24
|
<MediaContainer>
|
|
22
25
|
{filePreviews.map((file, index) => {
|
|
23
|
-
const
|
|
24
|
-
|
|
26
|
+
const isImage = file.type?.startsWith('image');
|
|
27
|
+
const isVideo = file.type?.startsWith('video');
|
|
25
28
|
return (
|
|
26
29
|
<View key={`${file.name}_${index}`}>
|
|
27
|
-
{
|
|
30
|
+
{isImage ? (
|
|
28
31
|
<MediaImage source={{ uri: file.uri }} />
|
|
32
|
+
) : isVideo ? (
|
|
33
|
+
<TouchableOpacity
|
|
34
|
+
activeOpacity={0.8}
|
|
35
|
+
onPress={() => setPreviewUri(file.uri)}
|
|
36
|
+
style={styles.videoThumb}
|
|
37
|
+
>
|
|
38
|
+
<Video
|
|
39
|
+
source={{ uri: file.uri }}
|
|
40
|
+
style={StyleSheet.absoluteFill}
|
|
41
|
+
resizeMode={ResizeMode.COVER}
|
|
42
|
+
shouldPlay={false}
|
|
43
|
+
isMuted
|
|
44
|
+
/>
|
|
45
|
+
<View style={styles.playOverlay}>
|
|
46
|
+
<Text style={styles.playIcon}>▶</Text>
|
|
47
|
+
</View>
|
|
48
|
+
</TouchableOpacity>
|
|
29
49
|
) : (
|
|
30
50
|
<View style={{ width: 70, height: 70, borderRadius: 8 }}>
|
|
31
51
|
<FileIcon width={70} height={70} />
|
|
@@ -37,6 +57,72 @@ export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
|
|
|
37
57
|
</View>
|
|
38
58
|
);
|
|
39
59
|
})}
|
|
60
|
+
|
|
61
|
+
<Modal visible={!!previewUri} animationType="fade" transparent>
|
|
62
|
+
<SafeAreaView style={styles.modalContainer}>
|
|
63
|
+
<TouchableOpacity
|
|
64
|
+
style={styles.closeButton}
|
|
65
|
+
onPress={() => setPreviewUri(null)}
|
|
66
|
+
>
|
|
67
|
+
<Text style={styles.closeText}>✕</Text>
|
|
68
|
+
</TouchableOpacity>
|
|
69
|
+
{previewUri && (
|
|
70
|
+
<Video
|
|
71
|
+
source={{ uri: previewUri }}
|
|
72
|
+
style={styles.fullVideo}
|
|
73
|
+
resizeMode={ResizeMode.CONTAIN}
|
|
74
|
+
useNativeControls
|
|
75
|
+
shouldPlay
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
78
|
+
</SafeAreaView>
|
|
79
|
+
</Modal>
|
|
40
80
|
</MediaContainer>
|
|
41
81
|
);
|
|
42
82
|
};
|
|
83
|
+
|
|
84
|
+
const styles = StyleSheet.create({
|
|
85
|
+
videoThumb: {
|
|
86
|
+
width: 70,
|
|
87
|
+
height: 70,
|
|
88
|
+
borderRadius: 8,
|
|
89
|
+
overflow: 'hidden',
|
|
90
|
+
backgroundColor: '#1a1a1a',
|
|
91
|
+
},
|
|
92
|
+
playOverlay: {
|
|
93
|
+
...StyleSheet.absoluteFillObject,
|
|
94
|
+
justifyContent: 'center',
|
|
95
|
+
alignItems: 'center',
|
|
96
|
+
backgroundColor: 'rgba(0,0,0,0.3)',
|
|
97
|
+
},
|
|
98
|
+
playIcon: {
|
|
99
|
+
fontSize: 24,
|
|
100
|
+
color: '#fff',
|
|
101
|
+
},
|
|
102
|
+
modalContainer: {
|
|
103
|
+
flex: 1,
|
|
104
|
+
backgroundColor: '#000',
|
|
105
|
+
justifyContent: 'center',
|
|
106
|
+
},
|
|
107
|
+
closeButton: {
|
|
108
|
+
position: 'absolute',
|
|
109
|
+
top: 60,
|
|
110
|
+
right: 20,
|
|
111
|
+
zIndex: 10,
|
|
112
|
+
width: 36,
|
|
113
|
+
height: 36,
|
|
114
|
+
borderRadius: 18,
|
|
115
|
+
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
116
|
+
justifyContent: 'center',
|
|
117
|
+
alignItems: 'center',
|
|
118
|
+
},
|
|
119
|
+
closeText: {
|
|
120
|
+
fontSize: 18,
|
|
121
|
+
color: '#fff',
|
|
122
|
+
fontWeight: '600',
|
|
123
|
+
},
|
|
124
|
+
fullVideo: {
|
|
125
|
+
width: '100%',
|
|
126
|
+
height: '70%',
|
|
127
|
+
},
|
|
128
|
+
});
|
|
@@ -38,8 +38,7 @@ const CustomMessageImage: React.FC<CustomMessageImageProps> = ({
|
|
|
38
38
|
'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg'
|
|
39
39
|
}
|
|
40
40
|
style={{
|
|
41
|
-
|
|
42
|
-
width: 150,
|
|
41
|
+
width: 250,
|
|
43
42
|
height: 200,
|
|
44
43
|
}}
|
|
45
44
|
onError={() => setError(true)}
|
|
@@ -117,6 +117,7 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
117
117
|
const result = await ImagePicker.launchCameraAsync({
|
|
118
118
|
mediaTypes: ['images', 'videos'],
|
|
119
119
|
quality: 0.9,
|
|
120
|
+
videoQuality: ImagePicker.UIImagePickerControllerQualityType.Medium,
|
|
120
121
|
});
|
|
121
122
|
if (result.canceled || !result.assets?.[0]) {return;}
|
|
122
123
|
const asset = result.assets[0];
|
|
@@ -151,6 +152,8 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
151
152
|
mediaTypes: ['images', 'videos'],
|
|
152
153
|
allowsEditing: false,
|
|
153
154
|
quality: 0.9,
|
|
155
|
+
preferredAssetRepresentationMode:
|
|
156
|
+
ImagePicker.UIImagePickerPreferredAssetRepresentationMode.Compatible,
|
|
154
157
|
});
|
|
155
158
|
if (result.canceled || !result.assets?.[0]) {return;}
|
|
156
159
|
const asset = result.assets[0];
|
|
@@ -27,7 +27,7 @@ const CustomMessageVideo: React.FC<CustomMessageVideoProps> = ({
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
|
-
<TouchableOpacity
|
|
30
|
+
<TouchableOpacity onPress={handleOpen}>
|
|
31
31
|
<Video
|
|
32
32
|
source={{ uri: fileURL }}
|
|
33
33
|
style={styles.video}
|
|
@@ -42,16 +42,9 @@ const CustomMessageVideo: React.FC<CustomMessageVideoProps> = ({
|
|
|
42
42
|
export default CustomMessageVideo;
|
|
43
43
|
|
|
44
44
|
const styles = StyleSheet.create({
|
|
45
|
-
container: {
|
|
46
|
-
margin: 0,
|
|
47
|
-
alignItems: 'center',
|
|
48
|
-
justifyContent: 'center',
|
|
49
|
-
width: '100%',
|
|
50
|
-
},
|
|
51
45
|
video: {
|
|
52
|
-
width:
|
|
53
|
-
|
|
54
|
-
borderRadius: 10,
|
|
46
|
+
width: '100%',
|
|
47
|
+
aspectRatio: 16 / 9,
|
|
55
48
|
backgroundColor: '#000',
|
|
56
49
|
},
|
|
57
50
|
});
|
|
@@ -4,11 +4,15 @@ import React, {
|
|
|
4
4
|
useCallback,
|
|
5
5
|
useContext,
|
|
6
6
|
useEffect,
|
|
7
|
+
useMemo,
|
|
7
8
|
useRef,
|
|
8
9
|
useState,
|
|
9
10
|
} from 'react';
|
|
10
11
|
import { AppState, DeviceEventEmitter } from 'react-native';
|
|
11
|
-
import XmppClient
|
|
12
|
+
import XmppClient, {
|
|
13
|
+
XmppCredentialsProvider,
|
|
14
|
+
} from '../networking/xmppClient';
|
|
15
|
+
import { refreshTokens } from '../roomStore/chatSettingsSlice';
|
|
12
16
|
import {
|
|
13
17
|
IConfig,
|
|
14
18
|
ProviderBootstrapStatus,
|
|
@@ -24,6 +28,7 @@ import {
|
|
|
24
28
|
} from '../utils/clientRegistry';
|
|
25
29
|
import {
|
|
26
30
|
applyResolvedUserToStore,
|
|
31
|
+
refreshUserCredentialsForXmpp,
|
|
27
32
|
resolveInitBeforeLoadUser,
|
|
28
33
|
} from '../helpers/resolveInitBeforeLoadUser';
|
|
29
34
|
import { ensureScopedChatCache } from '../helpers/ensureScopedChatCache';
|
|
@@ -77,6 +82,79 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config })
|
|
|
77
82
|
const completedBootstrapKeyRef = useRef<string>('');
|
|
78
83
|
const inflightBootstrapKeyRef = useRef<string>('');
|
|
79
84
|
|
|
85
|
+
// Callback XmppClient uses to fetch fresh credentials after a SASL
|
|
86
|
+
// `not-authorized` (typically JWT expiry during idle, bug #17).
|
|
87
|
+
// Always installed — the underlying `refreshUserCredentialsForXmpp`
|
|
88
|
+
// picks the right path based on config:
|
|
89
|
+
// - `jwtLogin` → re-exchange JWT via `/users/client`
|
|
90
|
+
// - `userLogin` / `customLogin` / store / persisted → `/users/my`
|
|
91
|
+
// with REST refresh chain (handles 401 → refresh → retry)
|
|
92
|
+
// Returns last-known cached creds if nothing usable is available so
|
|
93
|
+
// the XmppClient at least doesn't crash on `undefined.password`.
|
|
94
|
+
const credentialsProvider = useMemo<XmppCredentialsProvider>(() => {
|
|
95
|
+
return async () => {
|
|
96
|
+
// 1. Consumer-supplied REST refresh (when wired). This runs
|
|
97
|
+
// before the SDK's own refresh chain so non-Ethora backends
|
|
98
|
+
// can keep auth state in sync with their own token endpoint.
|
|
99
|
+
const customRefresh = config?.refreshTokens?.refreshFunction;
|
|
100
|
+
if (customRefresh) {
|
|
101
|
+
try {
|
|
102
|
+
const result = await customRefresh();
|
|
103
|
+
if (result?.accessToken) {
|
|
104
|
+
store.dispatch(
|
|
105
|
+
refreshTokens({
|
|
106
|
+
token: result.accessToken,
|
|
107
|
+
refreshToken: result.refreshToken || '',
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
} catch (err) {
|
|
112
|
+
devPushLog('warn', 'XMPP creds refresh: customRefresh failed', err);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 2. Re-mint XMPP creds via the right priority chain for the
|
|
117
|
+
// current auth mode. This call ALWAYS hydrates (unlike
|
|
118
|
+
// `resolveInitBeforeLoadUser` which short-circuits when a
|
|
119
|
+
// cached user already has xmppCredentials).
|
|
120
|
+
const fresh = await refreshUserCredentialsForXmpp(config).catch(
|
|
121
|
+
(err) => {
|
|
122
|
+
devPushLog('warn', 'XMPP creds refresh: full chain failed', err);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
if (fresh) {
|
|
127
|
+
applyResolvedUserToStore(fresh);
|
|
128
|
+
return {
|
|
129
|
+
username:
|
|
130
|
+
fresh.xmppUsername ||
|
|
131
|
+
fresh.defaultWallet?.walletAddress ||
|
|
132
|
+
'',
|
|
133
|
+
password: fresh.xmppPassword || '',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 3. Last-resort: return the cached creds so reconnect() can
|
|
138
|
+
// still attempt a connection. If the original failure was
|
|
139
|
+
// a stale JWT this will fail again and the user has to
|
|
140
|
+
// re-mount the chat — but at least we don't break the
|
|
141
|
+
// transient-network-blip case where the cached creds are
|
|
142
|
+
// still valid.
|
|
143
|
+
const u = store.getState().chatSettingStore.user;
|
|
144
|
+
return {
|
|
145
|
+
username: u?.xmppUsername || u?.defaultWallet?.walletAddress || '',
|
|
146
|
+
password: u?.xmppPassword || '',
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
}, [
|
|
150
|
+
config?.jwtLogin?.enabled,
|
|
151
|
+
config?.jwtLogin?.token,
|
|
152
|
+
config?.refreshTokens?.refreshFunction,
|
|
153
|
+
config?.userLogin?.enabled,
|
|
154
|
+
config?.customLogin?.enabled,
|
|
155
|
+
config?.initBeforeLoadAuth?.myEndpoint,
|
|
156
|
+
]);
|
|
157
|
+
|
|
80
158
|
const initializeClient = useCallback(
|
|
81
159
|
async (
|
|
82
160
|
username: string,
|
|
@@ -104,6 +182,12 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config })
|
|
|
104
182
|
// concurrent calls for the same key.
|
|
105
183
|
const created = await withXmppClientInitLock(key, async () => {
|
|
106
184
|
const newClient = new XmppClient(username, password, settings);
|
|
185
|
+
// Wire up the credentialsProvider so SASL `not-authorized`
|
|
186
|
+
// after idle triggers a refresh chain (jwtLogin →
|
|
187
|
+
// /users/client; userLogin/customLogin/store → /users/my +
|
|
188
|
+
// REST refresh) instead of looping forever with stale creds.
|
|
189
|
+
// Bug #17 — full coverage in 26.5.6.
|
|
190
|
+
newClient.setCredentialsProvider(credentialsProvider);
|
|
107
191
|
setGlobalXmppClient(newClient, key);
|
|
108
192
|
await newClient.waitForOnline().catch((err) => {
|
|
109
193
|
console.error('Error waiting for xmpp online:', err);
|
|
@@ -112,12 +196,16 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config })
|
|
|
112
196
|
return newClient;
|
|
113
197
|
});
|
|
114
198
|
|
|
199
|
+
// Reused clients (steps 1+2 above) also need the provider — config
|
|
200
|
+
// may have changed since the singleton was created.
|
|
201
|
+
created.setCredentialsProvider(credentialsProvider);
|
|
202
|
+
|
|
115
203
|
setClient(created);
|
|
116
204
|
lastCredsRef.current = { username, password, settings };
|
|
117
205
|
setReconnectAttempts(0);
|
|
118
206
|
return created;
|
|
119
207
|
},
|
|
120
|
-
[client, config?.xmppSettings]
|
|
208
|
+
[client, config?.xmppSettings, credentialsProvider]
|
|
121
209
|
);
|
|
122
210
|
|
|
123
211
|
// -----------------------------------------------------------
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// MIME → file extension table for download/preview filename fallbacks.
|
|
2
|
+
// Centralized so FilePreviewModal, MediaMessage, and any future media
|
|
3
|
+
// surface share one source of truth. Keep additions sorted by category.
|
|
4
|
+
|
|
5
|
+
const MIME_TO_EXT: Record<string, string> = {
|
|
6
|
+
// images
|
|
7
|
+
'image/jpeg': '.jpg',
|
|
8
|
+
'image/jpg': '.jpg',
|
|
9
|
+
'image/png': '.png',
|
|
10
|
+
'image/gif': '.gif',
|
|
11
|
+
'image/webp': '.webp',
|
|
12
|
+
'image/heic': '.heic',
|
|
13
|
+
'image/heif': '.heif',
|
|
14
|
+
'image/bmp': '.bmp',
|
|
15
|
+
'image/svg+xml': '.svg',
|
|
16
|
+
'image/tiff': '.tiff',
|
|
17
|
+
|
|
18
|
+
// video
|
|
19
|
+
'video/mp4': '.mp4',
|
|
20
|
+
'video/quicktime': '.mov',
|
|
21
|
+
'video/x-m4v': '.m4v',
|
|
22
|
+
'video/webm': '.webm',
|
|
23
|
+
'video/3gpp': '.3gp',
|
|
24
|
+
'video/x-matroska': '.mkv',
|
|
25
|
+
'video/mpeg': '.mpeg',
|
|
26
|
+
|
|
27
|
+
// audio
|
|
28
|
+
'audio/mpeg': '.mp3',
|
|
29
|
+
'audio/mp3': '.mp3',
|
|
30
|
+
'audio/mp4': '.m4a',
|
|
31
|
+
'audio/x-m4a': '.m4a',
|
|
32
|
+
'audio/wav': '.wav',
|
|
33
|
+
'audio/x-wav': '.wav',
|
|
34
|
+
'audio/aac': '.aac',
|
|
35
|
+
'audio/ogg': '.ogg',
|
|
36
|
+
'audio/flac': '.flac',
|
|
37
|
+
'audio/webm': '.weba',
|
|
38
|
+
|
|
39
|
+
// documents
|
|
40
|
+
'application/pdf': '.pdf',
|
|
41
|
+
'application/msword': '.doc',
|
|
42
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
|
|
43
|
+
'.docx',
|
|
44
|
+
'application/vnd.ms-excel': '.xls',
|
|
45
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx',
|
|
46
|
+
'application/vnd.ms-powerpoint': '.ppt',
|
|
47
|
+
'application/vnd.openxmlformats-officedocument.presentationml.presentation':
|
|
48
|
+
'.pptx',
|
|
49
|
+
'text/plain': '.txt',
|
|
50
|
+
'text/csv': '.csv',
|
|
51
|
+
'text/html': '.html',
|
|
52
|
+
'application/json': '.json',
|
|
53
|
+
'application/xml': '.xml',
|
|
54
|
+
'text/xml': '.xml',
|
|
55
|
+
'application/rtf': '.rtf',
|
|
56
|
+
|
|
57
|
+
// archives
|
|
58
|
+
'application/zip': '.zip',
|
|
59
|
+
'application/x-rar-compressed': '.rar',
|
|
60
|
+
'application/x-7z-compressed': '.7z',
|
|
61
|
+
'application/gzip': '.gz',
|
|
62
|
+
'application/x-tar': '.tar',
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const VALID_EXT_RE = /\.[a-z0-9]{1,8}$/i;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Returns the conventional extension (including the leading dot) for a
|
|
69
|
+
* MIME type, or `.bin` as a last-resort fallback so callers never end up
|
|
70
|
+
* with an extension-less filename.
|
|
71
|
+
*/
|
|
72
|
+
export function getExtensionForMime(mime: string | undefined | null): string {
|
|
73
|
+
if (!mime) {return '.bin';}
|
|
74
|
+
const normalized = mime.toLowerCase().split(';')[0]!.trim();
|
|
75
|
+
return MIME_TO_EXT[normalized] || '.bin';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Parses a URL or file path and returns the last segment, URL-decoded,
|
|
80
|
+
* stripped of query/hash. Returns `''` when nothing usable is present.
|
|
81
|
+
*/
|
|
82
|
+
export function filenameFromUrl(url: string | undefined | null): string {
|
|
83
|
+
if (!url) {return '';}
|
|
84
|
+
try {
|
|
85
|
+
// Strip query + hash without depending on a real URL parser (some RN
|
|
86
|
+
// URLs from CDNs do not parse cleanly).
|
|
87
|
+
const noQuery = url.split('?')[0]!.split('#')[0]!;
|
|
88
|
+
const last = noQuery.split('/').pop() || '';
|
|
89
|
+
return decodeURIComponent(last);
|
|
90
|
+
} catch {
|
|
91
|
+
return '';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Ensures `fileName` ends with a valid extension. Strategy:
|
|
97
|
+
* 1. If the input already has an extension, return it unchanged.
|
|
98
|
+
* 2. Otherwise, derive the extension from `mime` and append it.
|
|
99
|
+
* 3. If `mime` is unknown, append `.bin`.
|
|
100
|
+
*
|
|
101
|
+
* Empty/falsy filenames get a `media_<timestamp>` base before the
|
|
102
|
+
* extension is appended so callers always get a usable filename.
|
|
103
|
+
*/
|
|
104
|
+
export function ensureFilenameHasExtension(
|
|
105
|
+
fileName: string | undefined | null,
|
|
106
|
+
mime: string | undefined | null
|
|
107
|
+
): string {
|
|
108
|
+
const base =
|
|
109
|
+
(fileName && fileName.trim()) || `media_${Date.now()}`;
|
|
110
|
+
if (VALID_EXT_RE.test(base)) {return base;}
|
|
111
|
+
return `${base}${getExtensionForMime(mime)}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Best-effort filename derivation for a message bubble:
|
|
116
|
+
* - server-provided `fileName`
|
|
117
|
+
* - server-provided `originalName`
|
|
118
|
+
* - URL pathname
|
|
119
|
+
* - generic `media_<timestamp>` so we never render an empty label
|
|
120
|
+
*
|
|
121
|
+
* Always returns a string with a valid extension.
|
|
122
|
+
*/
|
|
123
|
+
export function deriveDisplayFilename(opts: {
|
|
124
|
+
fileName?: string | null;
|
|
125
|
+
originalName?: string | null;
|
|
126
|
+
url?: string | null;
|
|
127
|
+
mime?: string | null;
|
|
128
|
+
}): string {
|
|
129
|
+
const candidate =
|
|
130
|
+
(opts.fileName && opts.fileName.trim()) ||
|
|
131
|
+
(opts.originalName && opts.originalName.trim()) ||
|
|
132
|
+
filenameFromUrl(opts.url) ||
|
|
133
|
+
'';
|
|
134
|
+
return ensureFilenameHasExtension(candidate, opts.mime);
|
|
135
|
+
}
|
|
@@ -237,4 +237,83 @@ export const applyResolvedUserToStore = (user?: User | null) => {
|
|
|
237
237
|
store.dispatch(setUser(user));
|
|
238
238
|
};
|
|
239
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Re-mints a User with a fresh xmppPassword for the XMPP credentials-
|
|
242
|
+
* provider path (bug #17). Unlike `resolveInitBeforeLoadUser` this
|
|
243
|
+
* ALWAYS hydrates via the chosen auth path even if the cached user
|
|
244
|
+
* already had xmppCredentials — that's the whole point, the old ones
|
|
245
|
+
* are stale.
|
|
246
|
+
*
|
|
247
|
+
* Selection order:
|
|
248
|
+
* 1. `jwtLogin` — re-exchange the JWT via `/users/client`.
|
|
249
|
+
* 2. Anything else (`userLogin` / `customLogin` / store / persisted)
|
|
250
|
+
* — `tryHydrateViaMy` on the current user, which calls
|
|
251
|
+
* `/users/my` and, on 401, refreshes the access token via
|
|
252
|
+
* `/users/login/refresh` and retries.
|
|
253
|
+
*
|
|
254
|
+
* Returns `null` only when nothing usable is available — the caller
|
|
255
|
+
* (xmppProvider) falls back to the cached creds in that case.
|
|
256
|
+
*/
|
|
257
|
+
export const refreshUserCredentialsForXmpp = async (
|
|
258
|
+
config?: IConfig,
|
|
259
|
+
signal?: AbortSignal
|
|
260
|
+
): Promise<User | null> => {
|
|
261
|
+
if (signal?.aborted) {return null;}
|
|
262
|
+
|
|
263
|
+
// Priority 1: jwtLogin — same path as `resolveInitBeforeLoadUser`
|
|
264
|
+
// priority 3. We always re-exchange because the original JWT may
|
|
265
|
+
// itself have expired (and the consumer is expected to swap
|
|
266
|
+
// `config.jwtLogin.token` for a fresh one before then).
|
|
267
|
+
if (config?.jwtLogin?.enabled && config?.jwtLogin?.token) {
|
|
268
|
+
try {
|
|
269
|
+
const fresh = await loginViaJwt(config.jwtLogin.token);
|
|
270
|
+
const normalized = normalizeUserForXmpp(fresh);
|
|
271
|
+
if (normalized && hasXmppCredentials(normalized)) {return normalized;}
|
|
272
|
+
} catch (error) {
|
|
273
|
+
if (signal?.aborted || isAbortError(error)) {return null;}
|
|
274
|
+
// fall through to /users/my path
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const myEndpoint = config?.initBeforeLoadAuth?.myEndpoint || '/users/my';
|
|
279
|
+
|
|
280
|
+
// Priority 2: redux store user (covers userLogin + customLogin +
|
|
281
|
+
// anything previously persisted into chatSettingStore.user). The
|
|
282
|
+
// user must have at least a refreshToken for the refresh chain to
|
|
283
|
+
// produce something useful.
|
|
284
|
+
const currentUser = store.getState().chatSettingStore.user;
|
|
285
|
+
if (currentUser?.token || currentUser?.refreshToken) {
|
|
286
|
+
const hydrated = await tryHydrateViaMy(
|
|
287
|
+
currentUser as User,
|
|
288
|
+
myEndpoint,
|
|
289
|
+
signal
|
|
290
|
+
).catch(() => null);
|
|
291
|
+
if (hydrated && hasXmppCredentials(hydrated)) {return hydrated;}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Priority 3: persisted user in AsyncStorage — defensive; the store
|
|
295
|
+
// should already mirror this, but if the redux state got cleared
|
|
296
|
+
// mid-session (logout race) this gives us one last shot.
|
|
297
|
+
try {
|
|
298
|
+
const storedUser = await asyncLocalStorage<User>(
|
|
299
|
+
localStorageConstants.ETHORA_USER
|
|
300
|
+
).get();
|
|
301
|
+
if (
|
|
302
|
+
storedUser &&
|
|
303
|
+
(storedUser.token || storedUser.refreshToken || storedUser.xmppPassword)
|
|
304
|
+
) {
|
|
305
|
+
const hydrated = await tryHydrateViaMy(
|
|
306
|
+
storedUser,
|
|
307
|
+
myEndpoint,
|
|
308
|
+
signal
|
|
309
|
+
).catch(() => null);
|
|
310
|
+
if (hydrated && hasXmppCredentials(hydrated)) {return hydrated;}
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
// ignore storage errors
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return null;
|
|
317
|
+
};
|
|
318
|
+
|
|
240
319
|
export default resolveInitBeforeLoadUser;
|
|
@@ -119,10 +119,8 @@ const useChatWrapperInit = ({
|
|
|
119
119
|
user.xmppUsername || user?.defaultWallet?.walletAddress,
|
|
120
120
|
user?.xmppPassword,
|
|
121
121
|
config?.xmppSettings
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
return client;
|
|
125
|
-
});
|
|
122
|
+
);
|
|
123
|
+
console.log(' Client initialized', newClient?.status);
|
|
126
124
|
|
|
127
125
|
if (roomsList && Object.keys(roomsList).length > 0) {
|
|
128
126
|
console.log(
|
|
@@ -156,27 +154,29 @@ const useChatWrapperInit = ({
|
|
|
156
154
|
await newClient.getRoomsStanza();
|
|
157
155
|
}
|
|
158
156
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
console.log(
|
|
166
|
-
'Got chats private store',
|
|
167
|
-
roomTimestampObject?.length || 0
|
|
168
|
-
);
|
|
169
|
-
updatedChatLastTimestamps(roomTimestampObject, dispatch);
|
|
170
|
-
if (!hasSyncedHistoryRef.current) {
|
|
171
|
-
console.log('Updating messages till last');
|
|
172
|
-
await updateMessagesTillLast(rooms, newClient);
|
|
173
|
-
hasSyncedHistoryRef.current = true;
|
|
174
|
-
}
|
|
175
|
-
setClient(newClient);
|
|
176
|
-
setConnectionLost(false);
|
|
177
|
-
console.log('Initialization complete');
|
|
178
|
-
}
|
|
157
|
+
try {
|
|
158
|
+
const roomTimestampObject: any =
|
|
159
|
+
await newClient.getChatsPrivateStoreRequestStanza();
|
|
160
|
+
console.log(
|
|
161
|
+
'Got chats private store',
|
|
162
|
+
roomTimestampObject?.length || 0
|
|
179
163
|
);
|
|
164
|
+
if (roomTimestampObject) {
|
|
165
|
+
updatedChatLastTimestamps(roomTimestampObject, dispatch);
|
|
166
|
+
}
|
|
167
|
+
if (!hasSyncedHistoryRef.current) {
|
|
168
|
+
console.log('Updating messages till last');
|
|
169
|
+
await updateMessagesTillLast(rooms, newClient);
|
|
170
|
+
hasSyncedHistoryRef.current = true;
|
|
171
|
+
}
|
|
172
|
+
setClient(newClient);
|
|
173
|
+
setConnectionLost(false);
|
|
174
|
+
console.log('Initialization complete');
|
|
175
|
+
} catch (err) {
|
|
176
|
+
console.warn('privateStore/timestamps failed', err);
|
|
177
|
+
setClient(newClient);
|
|
178
|
+
setConnectionLost(false);
|
|
179
|
+
}
|
|
180
180
|
|
|
181
181
|
{
|
|
182
182
|
config?.refreshTokens?.enabled && refresh();
|
|
@@ -204,29 +204,34 @@ const useChatWrapperInit = ({
|
|
|
204
204
|
}
|
|
205
205
|
setInited(true);
|
|
206
206
|
console.log(' Getting chats private store for existing client');
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
console.log(
|
|
214
|
-
'Got chats private store for existing client',
|
|
215
|
-
roomTimestampObject?.length || 0
|
|
216
|
-
);
|
|
217
|
-
updatedChatLastTimestamps(roomTimestampObject, dispatch);
|
|
218
|
-
if (!hasSyncedHistoryRef.current) {
|
|
219
|
-
console.log(
|
|
220
|
-
'Updating messages till last for existing client'
|
|
221
|
-
);
|
|
222
|
-
await updateMessagesTillLast(rooms, client);
|
|
223
|
-
hasSyncedHistoryRef.current = true;
|
|
224
|
-
}
|
|
225
|
-
setClient(client);
|
|
226
|
-
setConnectionLost(false);
|
|
227
|
-
console.log(' Initialization complete for existing client');
|
|
228
|
-
}
|
|
207
|
+
try {
|
|
208
|
+
const roomTimestampObject: any =
|
|
209
|
+
await client.getChatsPrivateStoreRequestStanza();
|
|
210
|
+
console.log(
|
|
211
|
+
'Got chats private store for existing client',
|
|
212
|
+
roomTimestampObject?.length || 0
|
|
229
213
|
);
|
|
214
|
+
if (roomTimestampObject) {
|
|
215
|
+
updatedChatLastTimestamps(roomTimestampObject, dispatch);
|
|
216
|
+
}
|
|
217
|
+
if (!hasSyncedHistoryRef.current) {
|
|
218
|
+
console.log(
|
|
219
|
+
'Updating messages till last for existing client'
|
|
220
|
+
);
|
|
221
|
+
await updateMessagesTillLast(rooms, client);
|
|
222
|
+
hasSyncedHistoryRef.current = true;
|
|
223
|
+
}
|
|
224
|
+
setClient(client);
|
|
225
|
+
setConnectionLost(false);
|
|
226
|
+
console.log(' Initialization complete for existing client');
|
|
227
|
+
} catch (err) {
|
|
228
|
+
console.warn(
|
|
229
|
+
'privateStore/timestamps failed (existing client)',
|
|
230
|
+
err
|
|
231
|
+
);
|
|
232
|
+
setClient(client);
|
|
233
|
+
setConnectionLost(false);
|
|
234
|
+
}
|
|
230
235
|
{
|
|
231
236
|
config?.refreshTokens?.enabled && refresh();
|
|
232
237
|
}
|