stream-chat-react-native-core 4.7.3 → 4.9.0-beta.1
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/lib/commonjs/components/Attachment/GallaryImage.js +41 -0
- package/lib/commonjs/components/Attachment/GallaryImage.js.map +1 -0
- package/lib/commonjs/components/Attachment/Gallery.js +101 -36
- package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
- package/lib/commonjs/components/Attachment/Giphy.js +118 -25
- package/lib/commonjs/components/Attachment/Giphy.js.map +1 -1
- package/lib/commonjs/components/Attachment/ImageLoadingFailedIndicator.js +105 -0
- package/lib/commonjs/components/Attachment/ImageLoadingFailedIndicator.js.map +1 -0
- package/lib/commonjs/components/Attachment/ImageLoadingIndicator.js +58 -0
- package/lib/commonjs/components/Attachment/ImageLoadingIndicator.js.map +1 -0
- package/lib/commonjs/components/Attachment/hooks/useLoadingImage.js +32 -0
- package/lib/commonjs/components/Attachment/hooks/useLoadingImage.js.map +1 -0
- package/lib/commonjs/components/Channel/Channel.js +23 -13
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js +4 -0
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/hooks/useLatestMessagePreview.js +43 -19
- package/lib/commonjs/components/ChannelPreview/hooks/useLatestMessagePreview.js.map +1 -1
- package/lib/commonjs/components/MessageInput/FileUploadPreview.js +20 -19
- package/lib/commonjs/components/MessageInput/FileUploadPreview.js.map +1 -1
- package/lib/commonjs/components/MessageInput/ImageUploadPreview.js +14 -15
- package/lib/commonjs/components/MessageInput/ImageUploadPreview.js.map +1 -1
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js +2 -2
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +4 -0
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/i18n/he.json +67 -0
- package/lib/commonjs/index.js +9 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/mock-builders/api/channelMocks.js +299 -0
- package/lib/commonjs/mock-builders/api/channelMocks.js.map +1 -0
- package/lib/commonjs/utils/Streami18n.js +5 -0
- package/lib/commonjs/utils/Streami18n.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Attachment/GallaryImage.js +41 -0
- package/lib/module/components/Attachment/GallaryImage.js.map +1 -0
- package/lib/module/components/Attachment/Gallery.js +101 -36
- package/lib/module/components/Attachment/Gallery.js.map +1 -1
- package/lib/module/components/Attachment/Giphy.js +118 -25
- package/lib/module/components/Attachment/Giphy.js.map +1 -1
- package/lib/module/components/Attachment/ImageLoadingFailedIndicator.js +105 -0
- package/lib/module/components/Attachment/ImageLoadingFailedIndicator.js.map +1 -0
- package/lib/module/components/Attachment/ImageLoadingIndicator.js +58 -0
- package/lib/module/components/Attachment/ImageLoadingIndicator.js.map +1 -0
- package/lib/module/components/Attachment/hooks/useLoadingImage.js +32 -0
- package/lib/module/components/Attachment/hooks/useLoadingImage.js.map +1 -0
- package/lib/module/components/Channel/Channel.js +23 -13
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js +4 -0
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/module/components/ChannelPreview/hooks/useLatestMessagePreview.js +43 -19
- package/lib/module/components/ChannelPreview/hooks/useLatestMessagePreview.js.map +1 -1
- package/lib/module/components/MessageInput/FileUploadPreview.js +20 -19
- package/lib/module/components/MessageInput/FileUploadPreview.js.map +1 -1
- package/lib/module/components/MessageInput/ImageUploadPreview.js +14 -15
- package/lib/module/components/MessageInput/ImageUploadPreview.js.map +1 -1
- package/lib/module/contexts/messagesContext/MessagesContext.js +2 -2
- package/lib/module/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +4 -0
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/i18n/he.json +67 -0
- package/lib/module/index.js +9 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/mock-builders/api/channelMocks.js +299 -0
- package/lib/module/mock-builders/api/channelMocks.js.map +1 -0
- package/lib/module/utils/Streami18n.js +5 -0
- package/lib/module/utils/Streami18n.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Attachment/GallaryImage.d.ts +5 -0
- package/lib/typescript/components/Attachment/Gallery.d.ts +1 -1
- package/lib/typescript/components/Attachment/Giphy.d.ts +1 -1
- package/lib/typescript/components/Attachment/ImageLoadingFailedIndicator.d.ts +3 -0
- package/lib/typescript/components/Attachment/ImageLoadingIndicator.d.ts +3 -0
- package/lib/typescript/components/Attachment/hooks/useLoadingImage.d.ts +7 -0
- package/lib/typescript/components/Channel/Channel.d.ts +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts +1 -1
- package/lib/typescript/components/ChannelPreview/hooks/__tests__/useLatestMessagePreview.test.d.ts +1 -0
- package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts +10 -0
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +4 -0
- package/lib/typescript/i18n/he.json +67 -0
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/mock-builders/api/channelMocks.d.ts +14 -0
- package/lib/typescript/utils/Streami18n.d.ts +1 -4
- package/package.json +1 -1
- package/src/components/Attachment/GallaryImage.tsx +22 -0
- package/src/components/Attachment/Gallery.tsx +68 -35
- package/src/components/Attachment/Giphy.tsx +68 -1
- package/src/components/Attachment/ImageLoadingFailedIndicator.tsx +56 -0
- package/src/components/Attachment/ImageLoadingIndicator.tsx +31 -0
- package/src/components/Attachment/__tests__/Attachment.test.js +9 -3
- package/src/components/Attachment/__tests__/Gallery.test.js +36 -1
- package/src/components/Attachment/__tests__/Giphy.test.js +110 -90
- package/src/components/Attachment/hooks/useLoadingImage.tsx +8 -0
- package/src/components/Channel/Channel.tsx +8 -0
- package/src/components/Channel/hooks/useCreateMessagesContext.ts +4 -0
- package/src/components/ChannelPreview/__tests__/ChannelPreviewMessenger.test.js +0 -1
- package/src/components/ChannelPreview/hooks/__tests__/useLatestMessagePreview.test.tsx +145 -0
- package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts +50 -24
- package/src/components/MessageInput/FileUploadPreview.tsx +5 -4
- package/src/components/MessageInput/ImageUploadPreview.tsx +2 -3
- package/src/contexts/messagesContext/MessagesContext.tsx +15 -0
- package/src/contexts/themeContext/utils/theme.ts +8 -0
- package/src/i18n/he.json +67 -0
- package/src/index.ts +1 -0
- package/src/mock-builders/api/channelMocks.tsx +272 -0
- package/src/utils/Streami18n.ts +6 -3
- package/src/version.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from 'react';
|
|
2
2
|
import type { TouchableOpacityProps } from 'react-native';
|
|
3
|
+
import type { ImageLoadingFailedIndicatorProps } from 'src/components/Attachment/ImageLoadingFailedIndicator';
|
|
4
|
+
import type { ImageLoadingIndicatorProps } from 'src/components/Attachment/ImageLoadingIndicator';
|
|
3
5
|
import type { MessagePinnedHeaderProps } from 'src/components/Message/MessageSimple/MessagePinnedHeader';
|
|
4
6
|
import type { Attachment, ChannelState, MessageResponse } from 'stream-chat';
|
|
5
7
|
import type { AttachmentProps } from '../../components/Attachment/Attachment';
|
|
@@ -96,6 +98,14 @@ export declare type MessagesContextValue<StreamChatGenerics extends DefaultStrea
|
|
|
96
98
|
* The giphy version to render - check the keys of the [Image Object](https://developers.giphy.com/docs/api/schema#image-object) for possible values. Uses 'fixed_height' by default
|
|
97
99
|
* */
|
|
98
100
|
giphyVersion: keyof NonNullable<Attachment['giphy']>;
|
|
101
|
+
/**
|
|
102
|
+
* The indicator rendered when loading an image fails.
|
|
103
|
+
*/
|
|
104
|
+
ImageLoadingFailedIndicator: React.ComponentType<ImageLoadingFailedIndicatorProps>;
|
|
105
|
+
/**
|
|
106
|
+
* The indicator rendered when image is loading. By default renders <ActivityIndicator/>
|
|
107
|
+
*/
|
|
108
|
+
ImageLoadingIndicator: React.ComponentType<ImageLoadingIndicatorProps>;
|
|
99
109
|
/**
|
|
100
110
|
* When true, messageList will be scrolled at first unread message, when opened.
|
|
101
111
|
*/
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"1 Reply": "תגובה אחת",
|
|
3
|
+
"1 Thread Reply": "תגובה אחת לשרשור",
|
|
4
|
+
"Allow access to your Gallery": "אפשר גישה לגלריה שלך",
|
|
5
|
+
"Also send to channel": "שלח/י הודעה לשיחה",
|
|
6
|
+
"Are you sure you want to permanently delete this message?": "האם את/ה בטוח/ה שאת/ה רוצה למחוק את ההודעה הזו לצמיתות?",
|
|
7
|
+
"Block User": "חסום משתמש",
|
|
8
|
+
"Cancel": "ביטול",
|
|
9
|
+
"Cannot Flag Message": "סימון הודעה לא אפשרי",
|
|
10
|
+
"Copy Message": "העתק/י הודעה",
|
|
11
|
+
"Delete": "מחק",
|
|
12
|
+
"Delete Message": "מחק/י הודעה",
|
|
13
|
+
"Do you want to send a copy of this message to a moderator for further investigation?": "האם את/ה רוצה לשלוח עותק של הודעה זו למנחה להמשך חקירה?",
|
|
14
|
+
"Edit Message": "ערוך הודעה",
|
|
15
|
+
"Editing Message": "הודעה בעריכה",
|
|
16
|
+
"Emoji matching": "התאמת אמוג'י",
|
|
17
|
+
"Empty message...": "הודעה ריקה...",
|
|
18
|
+
"Error loading": "שגיאה ארעה בעת הטעינה",
|
|
19
|
+
"Error loading channel list...": "שגיאה ארעה בטעינת השיחות...",
|
|
20
|
+
"Error loading messages for this channel...": "שגיאה ארעה בטעינת הודעות עבור שיחה זאת...",
|
|
21
|
+
"Error while loading, please reload/refresh": "שגיאה ארעה בזמן הטעינה, אנא טען מחדש/רענן",
|
|
22
|
+
"File type not supported": "סוג הקובץ אינו נתמך",
|
|
23
|
+
"Flag": "סמן",
|
|
24
|
+
"Flag Message": "סמן הודעה",
|
|
25
|
+
"Flag action failed either due to a network issue or the message is already flagged": "פעולת הסימון נכשלה בגלל בעיית רשת או שההודעה כבר סומנה.",
|
|
26
|
+
"Instant Commands": "פעולות מיידיות",
|
|
27
|
+
"Links are disabled": "הקישורים מבוטלים",
|
|
28
|
+
"Loading channels...": "השיחות בטעינה...",
|
|
29
|
+
"Loading messages...": "ההודעות בטעינה..",
|
|
30
|
+
"Loading...": "טוען...",
|
|
31
|
+
"Message Reactions": "תגובות להודעה",
|
|
32
|
+
"Message deleted": "ההודעה נמחקה",
|
|
33
|
+
"Message flagged": "ההודעה סומנה",
|
|
34
|
+
"Mute User": "השתק/י משתמש",
|
|
35
|
+
"Not supported": "לא נתמך",
|
|
36
|
+
"Nothing yet...": "אינפורמציה תתקבל בהמשך...",
|
|
37
|
+
"Ok": "אוקיי",
|
|
38
|
+
"Only visible to you": "גלוי רק לך",
|
|
39
|
+
"Photo": "תמונה",
|
|
40
|
+
"Photos": "תמונות",
|
|
41
|
+
"Pin to Conversation": "הצמד/י לשיחה",
|
|
42
|
+
"Please enable access to your photos and videos so you can share them.": "אפשר/י גישה לתמונות ולסרטונים שלך כדי שתוכל/י לשתף אותם.",
|
|
43
|
+
"Please select a channel first": "אנא בחר/י שיחה תחילה",
|
|
44
|
+
"Reconnecting...": "מתחבר מחדש...",
|
|
45
|
+
"Reply": "השב/י",
|
|
46
|
+
"Reply to Message": "השב/י להודעה",
|
|
47
|
+
"Resend": "שלח/י שוב",
|
|
48
|
+
"Search GIFs": "חפש/י GIFs",
|
|
49
|
+
"Send a message": "שלח/י הודעה",
|
|
50
|
+
"Sending links is not allowed in this conversation": "שליחת קישורים אינה מותרת בשיחה זו",
|
|
51
|
+
"Slow mode ON": "מצב איטי מופעל",
|
|
52
|
+
"The message has been reported to a moderator.": "ההודעה דווחה למנהל",
|
|
53
|
+
"Thread Reply": "הגב/י בשרשור",
|
|
54
|
+
"Unblock User": "בטל/י חסימת משתמש",
|
|
55
|
+
"Unknown User": "משתמש לא ידוע",
|
|
56
|
+
"Unmute User": "בטל/י השתקת משתמש",
|
|
57
|
+
"Unpin from Conversation": "בטל/י הצמדה לשיחה",
|
|
58
|
+
"Unread Messages": "הודעות שטרם נקרו",
|
|
59
|
+
"You": "את/ה",
|
|
60
|
+
"You can't send messages in this channel": "את/ב לא יכול/ה לשלוח הודעות בשיחה זו",
|
|
61
|
+
"{{ firstUser }} and {{ nonSelfUserLength }} more are typing": "{{ firstUser }} ו-{{ nonSelfUserLength }} משתמש/ים אחר/ים מקלידים",
|
|
62
|
+
"{{ index }} of {{ photoLength }}": "{{ index }} מתוך {{ photoLength }}",
|
|
63
|
+
"{{ replyCount }} Replies": "{{ replyCount }} תגובות",
|
|
64
|
+
"{{ replyCount }} Thread Replies": "{{ replyCount }} תגובות שרשור",
|
|
65
|
+
"{{ user }} is typing": "{{ user }} מקליד/ה",
|
|
66
|
+
"🏙 Attachment...": "🏙 קובץ מצורף..."
|
|
67
|
+
}
|
|
@@ -14,4 +14,5 @@ export { default as itTranslations } from './i18n/it.json';
|
|
|
14
14
|
export { default as nlTranslations } from './i18n/nl.json';
|
|
15
15
|
export { default as ruTranslations } from './i18n/ru.json';
|
|
16
16
|
export { default as trTranslations } from './i18n/tr.json';
|
|
17
|
+
export { default as heTranslations } from './i18n/he.json';
|
|
17
18
|
export { version } from './version.json';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Channel, FormatMessageResponse, MessageResponse } from 'stream-chat';
|
|
2
|
+
import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
3
|
+
declare const CHANNEL: Channel<DefaultStreamChatGenerics>;
|
|
4
|
+
declare const CHANNEL_WITH_MESSAGES_TEXT: Channel<DefaultStreamChatGenerics>;
|
|
5
|
+
declare const CHANNEL_WITH_DELETED_MESSAGES: Channel<DefaultStreamChatGenerics>;
|
|
6
|
+
declare const CHANNEL_WITH_NO_MESSAGES: Channel<DefaultStreamChatGenerics>;
|
|
7
|
+
declare const CHANNEL_WITH_MESSAGE_COMMAND: Channel<DefaultStreamChatGenerics>;
|
|
8
|
+
declare const CHANNEL_WITH_MESSAGES_ATTACHMENTS: Channel<DefaultStreamChatGenerics>;
|
|
9
|
+
declare const LATEST_MESSAGE: MessageResponse<DefaultStreamChatGenerics>;
|
|
10
|
+
declare const FORMATTED_MESSAGE: FormatMessageResponse<DefaultStreamChatGenerics>;
|
|
11
|
+
declare const CHANNEL_WITH_MENTIONED_USERS: Channel<DefaultStreamChatGenerics>;
|
|
12
|
+
declare const CHANNEL_WITH_EMPTY_MESSAGE: Channel<DefaultStreamChatGenerics>;
|
|
13
|
+
declare const CHANNEL_WITH_MESSAGES: Channel<DefaultStreamChatGenerics>;
|
|
14
|
+
export { CHANNEL, CHANNEL_WITH_EMPTY_MESSAGE, CHANNEL_WITH_MESSAGES, CHANNEL_WITH_MENTIONED_USERS, FORMATTED_MESSAGE, LATEST_MESSAGE, CHANNEL_WITH_MESSAGES_ATTACHMENTS, CHANNEL_WITH_MESSAGE_COMMAND as CHANNEL_WITH_MESSAGES_COMMAND, CHANNEL_WITH_NO_MESSAGES, CHANNEL_WITH_DELETED_MESSAGES, CHANNEL_WITH_MESSAGES_TEXT, };
|
|
@@ -11,6 +11,7 @@ import 'dayjs/locale/ko';
|
|
|
11
11
|
import 'dayjs/locale/nl';
|
|
12
12
|
import 'dayjs/locale/ru';
|
|
13
13
|
import 'dayjs/locale/tr';
|
|
14
|
+
import 'dayjs/locale/he';
|
|
14
15
|
/**
|
|
15
16
|
* These locale imports also set these locales globally.
|
|
16
17
|
* So as a last step we import the english locale to make
|
|
@@ -154,10 +155,6 @@ export declare class Streami18n {
|
|
|
154
155
|
"Please enable access to your photos and videos so you can share them.": string;
|
|
155
156
|
"Please select a channel first": string;
|
|
156
157
|
"Reconnecting...": string;
|
|
157
|
-
/**
|
|
158
|
-
* Hindi notation for meridiems are quite fuzzy in practice. While there exists
|
|
159
|
-
* a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
|
|
160
|
-
*/
|
|
161
158
|
Reply: string;
|
|
162
159
|
"Reply to Message": string;
|
|
163
160
|
Resend: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stream-chat-react-native-core",
|
|
3
3
|
"description": "The official React Native and Expo components for Stream Chat, a service for building chat applications",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.9.0-beta.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"company": "Stream.io Inc",
|
|
7
7
|
"name": "Stream.io Inc"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ImageBackground, ImageProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { makeImageCompatibleUrl } from '../../utils/utils';
|
|
5
|
+
|
|
6
|
+
export const GalleryImage: React.FC<
|
|
7
|
+
Omit<ImageProps, 'height' | 'source'> & {
|
|
8
|
+
uri: string;
|
|
9
|
+
}
|
|
10
|
+
> = (props) => {
|
|
11
|
+
const { uri, ...rest } = props;
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<ImageBackground
|
|
15
|
+
{...rest}
|
|
16
|
+
accessibilityLabel='gallery-image'
|
|
17
|
+
source={{
|
|
18
|
+
uri: makeImageCompatibleUrl(uri),
|
|
19
|
+
}}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|
3
3
|
|
|
4
|
+
import { GalleryImage } from './GallaryImage';
|
|
5
|
+
import { useLoadingImage } from './hooks/useLoadingImage';
|
|
4
6
|
import { buildGallery } from './utils/buildGallery/buildGallery';
|
|
5
7
|
|
|
6
8
|
import { getGalleryImageBorderRadius } from './utils/getGalleryImageBorderRadius';
|
|
@@ -27,25 +29,7 @@ import {
|
|
|
27
29
|
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
28
30
|
import { isVideoPackageAvailable } from '../../native';
|
|
29
31
|
import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
30
|
-
import { getUrlWithoutParams
|
|
31
|
-
|
|
32
|
-
const GalleryImage: React.FC<
|
|
33
|
-
Omit<ImageProps, 'height' | 'source'> & {
|
|
34
|
-
uri: string;
|
|
35
|
-
}
|
|
36
|
-
> = (props) => {
|
|
37
|
-
const { uri, ...rest } = props;
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<Image
|
|
41
|
-
{...rest}
|
|
42
|
-
source={{
|
|
43
|
-
uri: makeImageCompatibleUrl(uri),
|
|
44
|
-
}}
|
|
45
|
-
testID='image-attachment-single'
|
|
46
|
-
/>
|
|
47
|
-
);
|
|
48
|
-
};
|
|
32
|
+
import { getUrlWithoutParams } from '../../utils/utils';
|
|
49
33
|
|
|
50
34
|
const MemoizedGalleryImage = React.memo(
|
|
51
35
|
GalleryImage,
|
|
@@ -54,7 +38,7 @@ const MemoizedGalleryImage = React.memo(
|
|
|
54
38
|
) as typeof GalleryImage;
|
|
55
39
|
|
|
56
40
|
const styles = StyleSheet.create({
|
|
57
|
-
|
|
41
|
+
errorTextSize: { fontSize: 10 },
|
|
58
42
|
galleryContainer: {
|
|
59
43
|
borderTopLeftRadius: 13,
|
|
60
44
|
borderTopRightRadius: 13,
|
|
@@ -62,7 +46,19 @@ const styles = StyleSheet.create({
|
|
|
62
46
|
flexWrap: 'wrap',
|
|
63
47
|
overflow: 'hidden',
|
|
64
48
|
},
|
|
65
|
-
imageContainer: {
|
|
49
|
+
imageContainer: {
|
|
50
|
+
alignItems: 'center',
|
|
51
|
+
display: 'flex',
|
|
52
|
+
flexDirection: 'row',
|
|
53
|
+
justifyContent: 'center',
|
|
54
|
+
padding: 1,
|
|
55
|
+
},
|
|
56
|
+
imageContainerStyle: { alignItems: 'center', flex: 1, justifyContent: 'center' },
|
|
57
|
+
imageLoadingIndicatorStyle: {
|
|
58
|
+
alignItems: 'center',
|
|
59
|
+
justifyContent: 'center',
|
|
60
|
+
position: 'absolute',
|
|
61
|
+
},
|
|
66
62
|
moreImagesContainer: {
|
|
67
63
|
alignItems: 'center',
|
|
68
64
|
justifyContent: 'center',
|
|
@@ -88,7 +84,11 @@ export type GalleryPropsWithContext<
|
|
|
88
84
|
> &
|
|
89
85
|
Pick<
|
|
90
86
|
MessagesContextValue<StreamChatGenerics>,
|
|
91
|
-
|
|
87
|
+
| 'additionalTouchableProps'
|
|
88
|
+
| 'legacyImageViewerSwipeBehaviour'
|
|
89
|
+
| 'VideoThumbnail'
|
|
90
|
+
| 'ImageLoadingIndicator'
|
|
91
|
+
| 'ImageLoadingFailedIndicator'
|
|
92
92
|
> &
|
|
93
93
|
Pick<OverlayContextValue, 'setOverlay'> & {
|
|
94
94
|
channelId: string | undefined;
|
|
@@ -118,6 +118,8 @@ const GalleryWithContext = <
|
|
|
118
118
|
alignment,
|
|
119
119
|
groupStyles,
|
|
120
120
|
hasThreadReplies,
|
|
121
|
+
ImageLoadingFailedIndicator,
|
|
122
|
+
ImageLoadingIndicator,
|
|
121
123
|
images,
|
|
122
124
|
legacyImageViewerSwipeBehaviour,
|
|
123
125
|
message,
|
|
@@ -133,6 +135,9 @@ const GalleryWithContext = <
|
|
|
133
135
|
VideoThumbnail,
|
|
134
136
|
} = props;
|
|
135
137
|
|
|
138
|
+
const { isLoadingImage, isLoadingImageError, setLoadingImage, setLoadingImageError } =
|
|
139
|
+
useLoadingImage();
|
|
140
|
+
|
|
136
141
|
const {
|
|
137
142
|
theme: {
|
|
138
143
|
colors: { overlay },
|
|
@@ -304,18 +309,37 @@ const GalleryWithContext = <
|
|
|
304
309
|
]}
|
|
305
310
|
/>
|
|
306
311
|
) : (
|
|
307
|
-
<
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
312
|
+
<View style={styles.imageContainerStyle}>
|
|
313
|
+
<MemoizedGalleryImage
|
|
314
|
+
onError={(error) => {
|
|
315
|
+
console.warn(error);
|
|
316
|
+
setLoadingImage(false);
|
|
317
|
+
setLoadingImageError(true);
|
|
318
|
+
}}
|
|
319
|
+
onLoadEnd={() => setLoadingImage(false)}
|
|
320
|
+
onLoadStart={() => setLoadingImage(true)}
|
|
321
|
+
resizeMode={resizeMode}
|
|
322
|
+
style={[
|
|
323
|
+
borderRadius,
|
|
324
|
+
image,
|
|
325
|
+
{
|
|
326
|
+
height: height - 1,
|
|
327
|
+
width: width - 1,
|
|
328
|
+
},
|
|
329
|
+
]}
|
|
330
|
+
uri={url}
|
|
331
|
+
/>
|
|
332
|
+
{isLoadingImage && (
|
|
333
|
+
<View style={{ position: 'absolute' }}>
|
|
334
|
+
<ImageLoadingIndicator style={styles.imageLoadingIndicatorStyle} />
|
|
335
|
+
</View>
|
|
336
|
+
)}
|
|
337
|
+
{isLoadingImageError && (
|
|
338
|
+
<View style={{ position: 'absolute' }}>
|
|
339
|
+
<ImageLoadingFailedIndicator style={styles.imageLoadingIndicatorStyle} />
|
|
340
|
+
</View>
|
|
341
|
+
)}
|
|
342
|
+
</View>
|
|
319
343
|
)}
|
|
320
344
|
{colIndex === numOfColumns - 1 &&
|
|
321
345
|
rowIndex === numOfRows - 1 &&
|
|
@@ -412,6 +436,8 @@ export const Gallery = <
|
|
|
412
436
|
alignment: propAlignment,
|
|
413
437
|
groupStyles: propGroupStyles,
|
|
414
438
|
hasThreadReplies,
|
|
439
|
+
ImageLoadingFailedIndicator: PropImageLoadingFailedIndicator,
|
|
440
|
+
ImageLoadingIndicator: PropImageLoadingIndicator,
|
|
415
441
|
images: propImages,
|
|
416
442
|
onLongPress: propOnLongPress,
|
|
417
443
|
onPress: propOnPress,
|
|
@@ -439,6 +465,8 @@ export const Gallery = <
|
|
|
439
465
|
} = useMessageContext<StreamChatGenerics>();
|
|
440
466
|
const {
|
|
441
467
|
additionalTouchableProps: contextAdditionalTouchableProps,
|
|
468
|
+
ImageLoadingFailedIndicator: ContextImageLoadingFailedIndicator,
|
|
469
|
+
ImageLoadingIndicator: ContextImageLoadingIndicator,
|
|
442
470
|
legacyImageViewerSwipeBehaviour,
|
|
443
471
|
VideoThumbnail: ContextVideoThumnbnail,
|
|
444
472
|
} = useMessagesContext<StreamChatGenerics>();
|
|
@@ -461,6 +489,9 @@ export const Gallery = <
|
|
|
461
489
|
const setOverlay = propSetOverlay || contextSetOverlay;
|
|
462
490
|
const threadList = propThreadList || contextThreadList;
|
|
463
491
|
const VideoThumbnail = PropVideoThumbnail || ContextVideoThumnbnail;
|
|
492
|
+
const ImageLoadingFailedIndicator =
|
|
493
|
+
PropImageLoadingFailedIndicator || ContextImageLoadingFailedIndicator;
|
|
494
|
+
const ImageLoadingIndicator = PropImageLoadingIndicator || ContextImageLoadingIndicator;
|
|
464
495
|
|
|
465
496
|
return (
|
|
466
497
|
<MemoizedGallery
|
|
@@ -470,6 +501,8 @@ export const Gallery = <
|
|
|
470
501
|
channelId: message?.cid,
|
|
471
502
|
groupStyles,
|
|
472
503
|
hasThreadReplies: hasThreadReplies || !!message?.reply_count,
|
|
504
|
+
ImageLoadingFailedIndicator,
|
|
505
|
+
ImageLoadingIndicator,
|
|
473
506
|
images,
|
|
474
507
|
legacyImageViewerSwipeBehaviour,
|
|
475
508
|
message,
|
|
@@ -3,6 +3,8 @@ import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|
|
3
3
|
|
|
4
4
|
import type { Attachment } from 'stream-chat';
|
|
5
5
|
|
|
6
|
+
import { useLoadingImage } from './hooks/useLoadingImage';
|
|
7
|
+
|
|
6
8
|
import {
|
|
7
9
|
ImageGalleryContextValue,
|
|
8
10
|
useImageGalleryContext,
|
|
@@ -40,6 +42,11 @@ const styles = StyleSheet.create({
|
|
|
40
42
|
fontWeight: '600',
|
|
41
43
|
paddingVertical: 16,
|
|
42
44
|
},
|
|
45
|
+
centerChild: {
|
|
46
|
+
alignItems: 'center',
|
|
47
|
+
display: 'flex',
|
|
48
|
+
justifyContent: 'center',
|
|
49
|
+
},
|
|
43
50
|
container: {
|
|
44
51
|
overflow: 'hidden',
|
|
45
52
|
width: 270,
|
|
@@ -84,6 +91,17 @@ const styles = StyleSheet.create({
|
|
|
84
91
|
padding: 8,
|
|
85
92
|
width: '60%',
|
|
86
93
|
},
|
|
94
|
+
imageErrorIndicatorStyle: {
|
|
95
|
+
alignItems: 'center',
|
|
96
|
+
flex: 1,
|
|
97
|
+
justifyContent: 'center',
|
|
98
|
+
},
|
|
99
|
+
imageLoadingIndicatorStyle: {
|
|
100
|
+
alignItems: 'center',
|
|
101
|
+
flex: 1,
|
|
102
|
+
justifyContent: 'center',
|
|
103
|
+
position: 'absolute',
|
|
104
|
+
},
|
|
87
105
|
selectionContainer: {
|
|
88
106
|
borderBottomRightRadius: 0,
|
|
89
107
|
borderRadius: 16,
|
|
@@ -128,7 +146,13 @@ export type GiphyPropsWithContext<
|
|
|
128
146
|
| 'onPressIn'
|
|
129
147
|
| 'preventPress'
|
|
130
148
|
> &
|
|
131
|
-
Pick<
|
|
149
|
+
Pick<
|
|
150
|
+
MessagesContextValue<StreamChatGenerics>,
|
|
151
|
+
| 'giphyVersion'
|
|
152
|
+
| 'additionalTouchableProps'
|
|
153
|
+
| 'ImageLoadingIndicator'
|
|
154
|
+
| 'ImageLoadingFailedIndicator'
|
|
155
|
+
> & {
|
|
132
156
|
attachment: Attachment<StreamChatGenerics>;
|
|
133
157
|
} & Pick<OverlayContextValue, 'setOverlay'>;
|
|
134
158
|
|
|
@@ -142,6 +166,8 @@ const GiphyWithContext = <
|
|
|
142
166
|
attachment,
|
|
143
167
|
giphyVersion,
|
|
144
168
|
handleAction,
|
|
169
|
+
ImageLoadingFailedIndicator,
|
|
170
|
+
ImageLoadingIndicator,
|
|
145
171
|
isMyMessage,
|
|
146
172
|
message,
|
|
147
173
|
onLongPress,
|
|
@@ -155,6 +181,9 @@ const GiphyWithContext = <
|
|
|
155
181
|
|
|
156
182
|
const { actions, giphy: giphyData, image_url, thumb_url, title, type } = attachment;
|
|
157
183
|
|
|
184
|
+
const { isLoadingImage, isLoadingImageError, setLoadingImage, setLoadingImageError } =
|
|
185
|
+
useLoadingImage();
|
|
186
|
+
|
|
158
187
|
const {
|
|
159
188
|
theme: {
|
|
160
189
|
colors: { accent_blue, black, grey, grey_dark, grey_gainsboro, label_bg_transparent, white },
|
|
@@ -214,6 +243,13 @@ const GiphyWithContext = <
|
|
|
214
243
|
</View>
|
|
215
244
|
<View style={styles.selectionImageContainer}>
|
|
216
245
|
<Image
|
|
246
|
+
onError={(error) => {
|
|
247
|
+
console.warn(error);
|
|
248
|
+
setLoadingImage(false);
|
|
249
|
+
setLoadingImageError(true);
|
|
250
|
+
}}
|
|
251
|
+
onLoadEnd={() => setLoadingImage(false)}
|
|
252
|
+
onLoadStart={() => setLoadingImage(true)}
|
|
217
253
|
resizeMode='contain'
|
|
218
254
|
source={{ uri: makeImageCompatibleUrl(uri) }}
|
|
219
255
|
style={[styles.giphy, giphyDimensions, giphy]}
|
|
@@ -299,16 +335,36 @@ const GiphyWithContext = <
|
|
|
299
335
|
<View
|
|
300
336
|
style={[
|
|
301
337
|
styles.container,
|
|
338
|
+
styles.centerChild,
|
|
302
339
|
{ backgroundColor: isMyMessage ? grey_gainsboro : white },
|
|
303
340
|
container,
|
|
304
341
|
]}
|
|
305
342
|
>
|
|
306
343
|
<Image
|
|
344
|
+
accessibilityLabel='giphy-attachment-image'
|
|
345
|
+
onError={(error) => {
|
|
346
|
+
console.warn(error);
|
|
347
|
+
setLoadingImage(false);
|
|
348
|
+
setLoadingImageError(true);
|
|
349
|
+
}}
|
|
350
|
+
onLoadEnd={() => setLoadingImage(false)}
|
|
351
|
+
onLoadStart={() => setLoadingImage(true)}
|
|
307
352
|
resizeMode='contain'
|
|
308
353
|
source={{ uri: makeImageCompatibleUrl(uri) }}
|
|
309
354
|
style={[styles.giphy, giphyDimensions, giphy]}
|
|
310
355
|
testID='giphy-attachment-image'
|
|
311
356
|
/>
|
|
357
|
+
|
|
358
|
+
{isLoadingImageError && (
|
|
359
|
+
<View style={{ position: 'absolute' }}>
|
|
360
|
+
<ImageLoadingFailedIndicator style={styles.imageErrorIndicatorStyle} />
|
|
361
|
+
</View>
|
|
362
|
+
)}
|
|
363
|
+
{isLoadingImage && (
|
|
364
|
+
<View style={{ position: 'absolute' }}>
|
|
365
|
+
<ImageLoadingIndicator style={styles.imageLoadingIndicatorStyle} />
|
|
366
|
+
</View>
|
|
367
|
+
)}
|
|
312
368
|
<View style={[styles.giphyMask, giphyMask]}>
|
|
313
369
|
<View
|
|
314
370
|
style={[
|
|
@@ -387,12 +443,23 @@ export const Giphy = <
|
|
|
387
443
|
const { additionalTouchableProps, giphyVersion } = useMessagesContext<StreamChatGenerics>();
|
|
388
444
|
const { setImage, setImages } = useImageGalleryContext<StreamChatGenerics>();
|
|
389
445
|
const { setOverlay } = useOverlayContext();
|
|
446
|
+
|
|
447
|
+
const {
|
|
448
|
+
ImageLoadingFailedIndicator: ContextImageLoadingFailedIndicator,
|
|
449
|
+
ImageLoadingIndicator: ContextImageLoadingIndicator,
|
|
450
|
+
} = useMessagesContext<StreamChatGenerics>();
|
|
451
|
+
const ImageLoadingFailedIndicator =
|
|
452
|
+
ContextImageLoadingFailedIndicator || props.ImageLoadingFailedIndicator;
|
|
453
|
+
const ImageLoadingIndicator = ContextImageLoadingIndicator || props.ImageLoadingIndicator;
|
|
454
|
+
|
|
390
455
|
return (
|
|
391
456
|
<MemoizedGiphy
|
|
392
457
|
{...{
|
|
393
458
|
additionalTouchableProps,
|
|
394
459
|
giphyVersion,
|
|
395
460
|
handleAction,
|
|
461
|
+
ImageLoadingFailedIndicator,
|
|
462
|
+
ImageLoadingIndicator,
|
|
396
463
|
isMyMessage,
|
|
397
464
|
message,
|
|
398
465
|
onLongPress,
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet, Text, View, ViewProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
5
|
+
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
|
|
6
|
+
|
|
7
|
+
import { Warning } from '../../icons';
|
|
8
|
+
|
|
9
|
+
const WARNING_ICON_SIZE = 14;
|
|
10
|
+
|
|
11
|
+
const styles = StyleSheet.create({
|
|
12
|
+
container: {
|
|
13
|
+
alignContent: 'center',
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
borderRadius: 20,
|
|
16
|
+
flexDirection: 'row',
|
|
17
|
+
justifyContent: 'center',
|
|
18
|
+
},
|
|
19
|
+
errorText: {
|
|
20
|
+
fontSize: 8,
|
|
21
|
+
justifyContent: 'center',
|
|
22
|
+
paddingHorizontal: 8,
|
|
23
|
+
},
|
|
24
|
+
warningIconStyle: {
|
|
25
|
+
borderRadius: 24,
|
|
26
|
+
marginLeft: 4,
|
|
27
|
+
marginTop: 6,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export type ImageLoadingFailedIndicatorProps = ViewProps;
|
|
32
|
+
|
|
33
|
+
export const ImageLoadingFailedIndicator = (props: ImageLoadingFailedIndicatorProps) => {
|
|
34
|
+
const {
|
|
35
|
+
theme: {
|
|
36
|
+
colors: { accent_red, overlay, white },
|
|
37
|
+
},
|
|
38
|
+
} = useTheme();
|
|
39
|
+
|
|
40
|
+
const { t } = useTranslationContext();
|
|
41
|
+
|
|
42
|
+
const { style, ...rest } = props;
|
|
43
|
+
return (
|
|
44
|
+
<View {...rest} accessibilityHint='image-loading-error' style={[style]}>
|
|
45
|
+
<View style={[styles.container, { backgroundColor: overlay }]}>
|
|
46
|
+
<Warning
|
|
47
|
+
height={WARNING_ICON_SIZE}
|
|
48
|
+
pathFill={accent_red}
|
|
49
|
+
style={styles.warningIconStyle}
|
|
50
|
+
width={WARNING_ICON_SIZE}
|
|
51
|
+
/>
|
|
52
|
+
<Text style={[styles.errorText, { color: white }]}>{t('Error loading')}</Text>
|
|
53
|
+
</View>
|
|
54
|
+
</View>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ActivityIndicator, StyleSheet, View, ViewProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
5
|
+
|
|
6
|
+
const styles = StyleSheet.create({
|
|
7
|
+
container: {
|
|
8
|
+
alignItems: 'center',
|
|
9
|
+
display: 'flex',
|
|
10
|
+
justifyContent: 'center',
|
|
11
|
+
width: '100%',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export type ImageLoadingIndicatorProps = ViewProps;
|
|
16
|
+
|
|
17
|
+
export const ImageLoadingIndicator = (props: ImageLoadingIndicatorProps) => {
|
|
18
|
+
const {
|
|
19
|
+
theme: {
|
|
20
|
+
messageSimple: {
|
|
21
|
+
loadingIndicator: { container },
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
} = useTheme();
|
|
25
|
+
const { style, ...rest } = props;
|
|
26
|
+
return (
|
|
27
|
+
<View {...rest} accessibilityHint='image-loading' style={[styles.container, container, style]}>
|
|
28
|
+
<ActivityIndicator />
|
|
29
|
+
</View>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
@@ -4,6 +4,7 @@ import { fireEvent, render, waitFor } from '@testing-library/react-native';
|
|
|
4
4
|
import { v4 as uuidv4 } from 'uuid';
|
|
5
5
|
|
|
6
6
|
import { MessageProvider } from '../../../contexts/messageContext/MessageContext';
|
|
7
|
+
import { MessagesProvider } from '../../../contexts/messagesContext/MessagesContext';
|
|
7
8
|
import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext';
|
|
8
9
|
import {
|
|
9
10
|
generateAttachmentAction,
|
|
@@ -12,6 +13,9 @@ import {
|
|
|
12
13
|
generateImageAttachment,
|
|
13
14
|
} from '../../../mock-builders/generator/attachment';
|
|
14
15
|
import { generateMessage } from '../../../mock-builders/generator/message';
|
|
16
|
+
|
|
17
|
+
import { ImageLoadingFailedIndicator } from '../../Attachment/ImageLoadingFailedIndicator';
|
|
18
|
+
import { ImageLoadingIndicator } from '../../Attachment/ImageLoadingIndicator';
|
|
15
19
|
import { Attachment } from '../Attachment';
|
|
16
20
|
import { AttachmentActions } from '../AttachmentActions';
|
|
17
21
|
|
|
@@ -19,9 +23,11 @@ const getAttachmentComponent = (props) => {
|
|
|
19
23
|
const message = generateMessage();
|
|
20
24
|
return (
|
|
21
25
|
<ThemeProvider>
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
|
|
26
|
+
<MessagesProvider value={{ ImageLoadingFailedIndicator, ImageLoadingIndicator }}>
|
|
27
|
+
<MessageProvider value={{ message }}>
|
|
28
|
+
<Attachment {...props} />
|
|
29
|
+
</MessageProvider>
|
|
30
|
+
</MessagesProvider>
|
|
25
31
|
</ThemeProvider>
|
|
26
32
|
);
|
|
27
33
|
};
|