stream-chat-react-native-core 5.30.1-beta.1 → 5.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/lib/commonjs/components/Chat/hooks/useAppSettings.js +2 -4
  2. package/lib/commonjs/components/Chat/hooks/useAppSettings.js.map +1 -1
  3. package/lib/commonjs/components/MessageInput/FileUploadPreview.js +5 -6
  4. package/lib/commonjs/components/MessageInput/FileUploadPreview.js.map +1 -1
  5. package/lib/commonjs/components/MessageInput/MessageInput.js +4 -26
  6. package/lib/commonjs/components/MessageInput/MessageInput.js.map +1 -1
  7. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +89 -76
  8. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  9. package/lib/commonjs/contexts/messageInputContext/utils/utils.js +66 -0
  10. package/lib/commonjs/contexts/messageInputContext/utils/utils.js.map +1 -0
  11. package/lib/commonjs/i18n/en.json +2 -2
  12. package/lib/commonjs/i18n/es.json +72 -72
  13. package/lib/commonjs/i18n/fr.json +72 -72
  14. package/lib/commonjs/i18n/he.json +72 -72
  15. package/lib/commonjs/i18n/hi.json +72 -72
  16. package/lib/commonjs/i18n/it.json +72 -72
  17. package/lib/commonjs/i18n/ja.json +72 -72
  18. package/lib/commonjs/i18n/ko.json +72 -72
  19. package/lib/commonjs/i18n/nl.json +72 -72
  20. package/lib/commonjs/i18n/pt-BR.json +72 -72
  21. package/lib/commonjs/i18n/ru.json +72 -72
  22. package/lib/commonjs/i18n/tr.json +72 -72
  23. package/lib/commonjs/version.json +1 -1
  24. package/lib/module/components/Chat/hooks/useAppSettings.js +2 -4
  25. package/lib/module/components/Chat/hooks/useAppSettings.js.map +1 -1
  26. package/lib/module/components/MessageInput/FileUploadPreview.js +5 -6
  27. package/lib/module/components/MessageInput/FileUploadPreview.js.map +1 -1
  28. package/lib/module/components/MessageInput/MessageInput.js +4 -26
  29. package/lib/module/components/MessageInput/MessageInput.js.map +1 -1
  30. package/lib/module/contexts/messageInputContext/MessageInputContext.js +89 -76
  31. package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  32. package/lib/module/contexts/messageInputContext/utils/utils.js +66 -0
  33. package/lib/module/contexts/messageInputContext/utils/utils.js.map +1 -0
  34. package/lib/module/i18n/en.json +2 -2
  35. package/lib/module/i18n/es.json +72 -72
  36. package/lib/module/i18n/fr.json +72 -72
  37. package/lib/module/i18n/he.json +72 -72
  38. package/lib/module/i18n/hi.json +72 -72
  39. package/lib/module/i18n/it.json +72 -72
  40. package/lib/module/i18n/ja.json +72 -72
  41. package/lib/module/i18n/ko.json +72 -72
  42. package/lib/module/i18n/nl.json +72 -72
  43. package/lib/module/i18n/pt-BR.json +72 -72
  44. package/lib/module/i18n/ru.json +72 -72
  45. package/lib/module/i18n/tr.json +72 -72
  46. package/lib/module/version.json +1 -1
  47. package/lib/typescript/components/Chat/hooks/useAppSettings.d.ts.map +1 -1
  48. package/lib/typescript/components/MessageInput/FileUploadPreview.d.ts.map +1 -1
  49. package/lib/typescript/components/MessageInput/MessageInput.d.ts.map +1 -1
  50. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts.map +1 -1
  51. package/lib/typescript/contexts/messageInputContext/utils/utils.d.ts +22 -0
  52. package/lib/typescript/contexts/messageInputContext/utils/utils.d.ts.map +1 -0
  53. package/lib/typescript/i18n/en.json +2 -2
  54. package/lib/typescript/i18n/es.json +72 -72
  55. package/lib/typescript/i18n/fr.json +72 -72
  56. package/lib/typescript/i18n/he.json +72 -72
  57. package/lib/typescript/i18n/hi.json +72 -72
  58. package/lib/typescript/i18n/it.json +72 -72
  59. package/lib/typescript/i18n/ja.json +72 -72
  60. package/lib/typescript/i18n/ko.json +72 -72
  61. package/lib/typescript/i18n/nl.json +72 -72
  62. package/lib/typescript/i18n/pt-BR.json +72 -72
  63. package/lib/typescript/i18n/ru.json +72 -72
  64. package/lib/typescript/i18n/tr.json +72 -72
  65. package/lib/typescript/utils/Streami18n.d.ts +1 -1
  66. package/package.json +1 -1
  67. package/src/components/Chat/hooks/useAppSettings.ts +4 -6
  68. package/src/components/MessageInput/FileUploadPreview.tsx +2 -3
  69. package/src/components/MessageInput/MessageInput.tsx +4 -45
  70. package/src/contexts/messageInputContext/MessageInputContext.tsx +60 -55
  71. package/src/contexts/messageInputContext/__tests__/MessageInputContext.test.tsx +9 -0
  72. package/src/contexts/messageInputContext/__tests__/pickFile.test.tsx +8 -3
  73. package/src/contexts/messageInputContext/utils/utils.ts +86 -0
  74. package/src/i18n/en.json +2 -2
  75. package/src/i18n/es.json +72 -72
  76. package/src/i18n/fr.json +72 -72
  77. package/src/i18n/he.json +72 -72
  78. package/src/i18n/hi.json +72 -72
  79. package/src/i18n/it.json +72 -72
  80. package/src/i18n/ja.json +72 -72
  81. package/src/i18n/ko.json +72 -72
  82. package/src/i18n/nl.json +72 -72
  83. package/src/i18n/pt-BR.json +72 -72
  84. package/src/i18n/ru.json +72 -72
  85. package/src/i18n/tr.json +72 -72
  86. package/src/version.json +1 -1
@@ -1,11 +1,5 @@
1
1
  import React, { useEffect, useMemo, useState } from 'react';
2
- import {
3
- Alert,
4
- NativeSyntheticEvent,
5
- StyleSheet,
6
- TextInputFocusEventData,
7
- View,
8
- } from 'react-native';
2
+ import { NativeSyntheticEvent, StyleSheet, TextInputFocusEventData, View } from 'react-native';
9
3
 
10
4
  import {
11
5
  GestureEvent,
@@ -231,7 +225,6 @@ const MessageInputWithContext = <
231
225
  } = props;
232
226
 
233
227
  const [height, setHeight] = useState(0);
234
- const { t } = useTranslationContext();
235
228
 
236
229
  const {
237
230
  theme: {
@@ -323,9 +316,6 @@ const MessageInputWithContext = <
323
316
  }
324
317
  }, [imagesForInput]);
325
318
 
326
- const MEGA_BYTES_TO_BYTES = 1024 * 1024;
327
- const MAX_FILE_SIZE_TO_UPLOAD_IN_MB = 100;
328
-
329
319
  const uploadImagesHandler = () => {
330
320
  const imageToUpload = selectedImages.find((selectedImage) => {
331
321
  const uploadedImage = imageUploads.find(
@@ -334,23 +324,8 @@ const MessageInputWithContext = <
334
324
  );
335
325
  return !uploadedImage;
336
326
  });
337
- // Check if the file size of the image exceeds the threshold of 100MB
338
- if (
339
- imageToUpload &&
340
- Number(imageToUpload.size) / MEGA_BYTES_TO_BYTES > MAX_FILE_SIZE_TO_UPLOAD_IN_MB
341
- ) {
342
- Alert.alert(
343
- t(
344
- `Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.`,
345
- { MAX_FILE_SIZE_TO_UPLOAD_IN_MB },
346
- ),
347
- );
348
- setSelectedImages(
349
- selectedImages.filter((selectedImage) => selectedImage.uri !== imageToUpload.uri),
350
- );
351
- } else {
352
- if (imageToUpload) uploadNewImage(imageToUpload);
353
- }
327
+
328
+ if (imageToUpload) uploadNewImage(imageToUpload);
354
329
  };
355
330
 
356
331
  const removeImagesHandler = () => {
@@ -386,23 +361,7 @@ const MessageInputWithContext = <
386
361
  );
387
362
  return !uploadedFile;
388
363
  });
389
- // Check if the file size exceeds the threshold of 100MB
390
- if (
391
- fileToUpload &&
392
- Number(fileToUpload.size) / MEGA_BYTES_TO_BYTES > MAX_FILE_SIZE_TO_UPLOAD_IN_MB
393
- ) {
394
- Alert.alert(
395
- t(
396
- `Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.`,
397
- { MAX_FILE_SIZE_TO_UPLOAD_IN_MB },
398
- ),
399
- );
400
- setSelectedFiles(
401
- selectedFiles.filter((selectedFile) => selectedFile.uri !== fileToUpload.uri),
402
- );
403
- } else {
404
- if (fileToUpload) uploadNewFile(fileToUpload);
405
- }
364
+ if (fileToUpload) uploadNewFile(fileToUpload);
406
365
  } else {
407
366
  /** User de-selected a video in bottom sheet attachment picker */
408
367
  const filesToRemove = fileUploads.filter(
@@ -21,6 +21,8 @@ import {
21
21
  import { useCreateMessageInputContext } from './hooks/useCreateMessageInputContext';
22
22
  import { useMessageDetailsForState } from './hooks/useMessageDetailsForState';
23
23
 
24
+ import { isUploadAllowed, MAX_FILE_SIZE_TO_UPLOAD, prettifyFileSize } from './utils/utils';
25
+
24
26
  import { AudioAttachmentProps } from '../../components/Attachment/AudioAttachment';
25
27
  import { parseLinksFromText } from '../../components/Message/MessageSimple/utils/parseLinks';
26
28
  import type { AttachButtonProps } from '../../components/MessageInput/AttachButton';
@@ -483,34 +485,36 @@ export const MessageInputProvider = <
483
485
  }: PropsWithChildren<{
484
486
  value: InputMessageInputContextValue<StreamChatGenerics>;
485
487
  }>) => {
486
- const { closePicker, openPicker, selectedPicker, setSelectedPicker } =
487
- useAttachmentPickerContext();
488
+ const {
489
+ closePicker,
490
+ openPicker,
491
+ selectedFiles,
492
+ selectedImages,
493
+ selectedPicker,
494
+ setSelectedFiles,
495
+ setSelectedImages,
496
+ setSelectedPicker,
497
+ } = useAttachmentPickerContext();
488
498
  const { appSettings, client, enableOfflineSupport } = useChatContext<StreamChatGenerics>();
489
499
  const { removeMessage } = useMessagesContext();
490
500
 
491
501
  const getFileUploadConfig = () => {
492
502
  const fileConfig = appSettings?.app?.file_upload_config;
493
- if (fileConfig !== null || fileConfig !== undefined) {
503
+ if (fileConfig !== undefined) {
494
504
  return fileConfig;
495
505
  } else {
496
506
  return {};
497
507
  }
498
508
  };
499
509
 
500
- const blockedFileExtensionTypes = getFileUploadConfig()?.blocked_file_extensions;
501
- const blockedFileMimeTypes = getFileUploadConfig()?.blocked_mime_types;
502
-
503
510
  const getImageUploadConfig = () => {
504
511
  const imageConfig = appSettings?.app?.image_upload_config;
505
- if (imageConfig !== null || imageConfig !== undefined) {
512
+ if (imageConfig !== undefined) {
506
513
  return imageConfig;
507
514
  }
508
515
  return {};
509
516
  };
510
517
 
511
- const blockedImageExtensionTypes = getImageUploadConfig()?.blocked_file_extensions;
512
- const blockedImageMimeTypes = getImageUploadConfig()?.blocked_mime_types;
513
-
514
518
  const channelCapabities = useOwnCapabilitiesContext();
515
519
 
516
520
  const { channel, giphyEnabled, uploadAbortControllerRef } =
@@ -663,30 +667,17 @@ export const MessageInputProvider = <
663
667
  maxNumberOfFiles: value.maxNumberOfFiles - numberOfUploads,
664
668
  });
665
669
 
666
- const MEGA_BYTES_TO_BYTES = 1024 * 1024;
667
- const MAX_FILE_SIZE_TO_UPLOAD_IN_MB = 100;
668
-
669
670
  if (!result.cancelled && result.assets) {
670
- const totalFileSize = result.assets.reduce((acc, asset) => acc + Number(asset.size), 0);
671
- if (totalFileSize / MEGA_BYTES_TO_BYTES > MAX_FILE_SIZE_TO_UPLOAD_IN_MB) {
672
- Alert.alert(
673
- t(
674
- `Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.`,
675
- { MAX_FILE_SIZE_TO_UPLOAD_IN_MB },
676
- ),
677
- );
678
- } else {
679
- result.assets.forEach((asset) => {
680
- /**
681
- * TODO: The current tight coupling of images to the image
682
- * picker does not allow images picked from the file picker
683
- * to be rendered in a preview via the uploadNewImage call.
684
- * This should be updated alongside allowing image a file
685
- * uploads together.
686
- */
687
- uploadNewFile(asset);
688
- });
689
- }
671
+ result.assets.forEach((asset) => {
672
+ /**
673
+ * TODO: The current tight coupling of images to the image
674
+ * picker does not allow images picked from the file picker
675
+ * to be rendered in a preview via the uploadNewImage call.
676
+ * This should be updated alongside allowing image a file
677
+ * uploads together.
678
+ */
679
+ uploadNewFile(asset);
680
+ });
690
681
  }
691
682
  };
692
683
 
@@ -1191,18 +1182,25 @@ export const MessageInputProvider = <
1191
1182
 
1192
1183
  const uploadNewFile = async (file: File) => {
1193
1184
  const id: string = generateRandomId();
1185
+ const fileConfig = getFileUploadConfig();
1186
+ const { size_limit } = fileConfig;
1194
1187
 
1195
- const isBlockedFileExtension: boolean | undefined = blockedFileExtensionTypes?.some(
1196
- (fileExtensionType: string) => file.name?.includes(fileExtensionType),
1197
- );
1198
- const isBlockedFileMimeType: boolean | undefined = blockedFileMimeTypes?.some(
1199
- (mimeType: string) => file.name?.includes(mimeType),
1200
- );
1188
+ const isAllowed = isUploadAllowed({ config: fileConfig, file });
1189
+
1190
+ const sizeLimit = size_limit || MAX_FILE_SIZE_TO_UPLOAD;
1191
+
1192
+ if (file.size && file.size > sizeLimit) {
1193
+ Alert.alert(
1194
+ t('File is too large: {{ size }}, maximum upload size is {{ limit }}', {
1195
+ limit: prettifyFileSize(sizeLimit),
1196
+ size: prettifyFileSize(file.size),
1197
+ }),
1198
+ );
1199
+ setSelectedFiles(selectedFiles.filter((selectedFile) => selectedFile.uri !== file.uri));
1200
+ return;
1201
+ }
1201
1202
 
1202
- const fileState =
1203
- isBlockedFileExtension || isBlockedFileMimeType
1204
- ? FileState.NOT_SUPPORTED
1205
- : FileState.UPLOADING;
1203
+ const fileState = isAllowed ? FileState.UPLOADING : FileState.NOT_SUPPORTED;
1206
1204
 
1207
1205
  // If file type is explicitly provided while upload we use it, else we derive the file type.
1208
1206
  const fileType = file.type || file.mimeType?.split('/')[0];
@@ -1220,26 +1218,33 @@ export const MessageInputProvider = <
1220
1218
  setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads + 1),
1221
1219
  ]);
1222
1220
 
1223
- if (!isBlockedFileExtension) {
1221
+ if (isAllowed) {
1224
1222
  uploadFile({ newFile });
1225
1223
  }
1226
1224
  };
1227
1225
 
1228
1226
  const uploadNewImage = async (image: Partial<Asset>) => {
1229
1227
  const id = generateRandomId();
1228
+ const imageUploadConfig = getImageUploadConfig();
1230
1229
 
1231
- const isBlockedImageMimeType = blockedImageMimeTypes?.some((mimeType: string) =>
1232
- image.uri?.includes(mimeType),
1233
- );
1230
+ const { size_limit } = imageUploadConfig;
1234
1231
 
1235
- const isBlockedImageExtension = blockedImageExtensionTypes?.some((imageExtensionType: string) =>
1236
- image.uri?.includes(imageExtensionType),
1237
- );
1232
+ const isAllowed = isUploadAllowed({ config: imageUploadConfig, file: image });
1233
+
1234
+ const sizeLimit = size_limit || MAX_FILE_SIZE_TO_UPLOAD;
1235
+
1236
+ if (image.size && image?.size > sizeLimit) {
1237
+ Alert.alert(
1238
+ t('File is too large: {{ size }}, maximum upload size is {{ limit }}', {
1239
+ limit: prettifyFileSize(sizeLimit),
1240
+ size: prettifyFileSize(image.size),
1241
+ }),
1242
+ );
1243
+ setSelectedImages(selectedImages.filter((selectedImage) => selectedImage.uri !== image.uri));
1244
+ return;
1245
+ }
1238
1246
 
1239
- const imageState =
1240
- isBlockedImageExtension || isBlockedImageMimeType
1241
- ? FileState.NOT_SUPPORTED
1242
- : FileState.UPLOADING;
1247
+ const imageState = isAllowed ? FileState.UPLOADING : FileState.NOT_SUPPORTED;
1243
1248
 
1244
1249
  const newImage: ImageUpload = {
1245
1250
  file: image,
@@ -1255,7 +1260,7 @@ export const MessageInputProvider = <
1255
1260
  setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads + 1),
1256
1261
  ]);
1257
1262
 
1258
- if (!isBlockedImageExtension) {
1263
+ if (isAllowed) {
1259
1264
  uploadImage({ newImage });
1260
1265
  }
1261
1266
  };
@@ -118,12 +118,21 @@ describe('MessageInputContext', () => {
118
118
  act(() => {
119
119
  result.current.uploadNewImage(
120
120
  generateImageAttachment({
121
+ name: 'dummy.png',
121
122
  uri: 'https://www.bastiaanmulder.nl/wp-content/uploads/2013/11/dummy-image-square.png',
122
123
  }),
123
124
  );
124
125
  });
125
126
 
126
127
  expect(result.current.imageUploads[0].state).toBe(FileState.NOT_SUPPORTED);
128
+
129
+ act(() => {
130
+ result.current.uploadNewFile({
131
+ name: 'dummy.mp3',
132
+ uri: 'https://www.bastiaanmulder.nl/wp-content/uploads/2013/11/dummy.mp3',
133
+ });
134
+ });
135
+ expect(result.current.imageUploads[0].state).toBe(FileState.NOT_SUPPORTED);
127
136
  });
128
137
 
129
138
  it('onSelectItem works', () => {
@@ -9,8 +9,9 @@ import { generateFileAttachment } from '../../../mock-builders/generator/attachm
9
9
  import { generateMessage } from '../../../mock-builders/generator/message';
10
10
  import { generateUser } from '../../../mock-builders/generator/user';
11
11
  import * as NativeUtils from '../../../native';
12
-
13
12
  import type { DefaultStreamChatGenerics } from '../../../types/types';
13
+ import * as AttachmentPickerContext from '../../attachmentPickerContext/AttachmentPickerContext';
14
+
14
15
  import {
15
16
  InputMessageInputContextValue,
16
17
  MessageInputContextValue,
@@ -51,13 +52,17 @@ describe("MessageInputContext's pickFile", () => {
51
52
  cancelled: false,
52
53
  }),
53
54
  );
55
+ jest.spyOn(AttachmentPickerContext, 'useAttachmentPickerContext').mockImplementation(() => ({
56
+ selectedFiles: [],
57
+ setSelectedFiles: jest.fn(),
58
+ }));
54
59
 
55
60
  const initialProps = {
56
61
  editing: message,
57
62
  maxNumberOfFiles: 2,
58
63
  };
59
64
 
60
- it.each([[3, 1]])(
65
+ it.each([[3, 2]])(
61
66
  'run pickFile when numberOfUploads is %d and alert is triggered %d number of times',
62
67
  async (numberOfUploads, numberOfTimesCalled) => {
63
68
  const { rerender, result } = renderHook(() => useMessageInputContext(), {
@@ -103,6 +108,6 @@ describe("MessageInputContext's pickFile", () => {
103
108
  result.current.pickFile();
104
109
  });
105
110
 
106
- expect(Alert.alert).toHaveBeenCalledTimes(1);
111
+ expect(Alert.alert).toHaveBeenCalledTimes(2);
107
112
  });
108
113
  });
@@ -0,0 +1,86 @@
1
+ import { lookup } from 'mime-types';
2
+ import type { FileUploadConfig } from 'stream-chat';
3
+
4
+ import { Asset, File } from '../../../types/types';
5
+
6
+ export const MAX_FILE_SIZE_TO_UPLOAD = 100 * 1024 * 1024; // 100 MB
7
+
8
+ type CheckUploadPermissionsParams = {
9
+ config: FileUploadConfig;
10
+ file: File | Partial<Asset>;
11
+ };
12
+
13
+ /**
14
+ * This utility function checks if the file upload is allowed based on the file upload config.
15
+ * @param Object File upload config and file to check
16
+ * @returns
17
+ */
18
+ export const isUploadAllowed = ({ config, file }: CheckUploadPermissionsParams) => {
19
+ const {
20
+ allowed_file_extensions,
21
+ allowed_mime_types,
22
+ blocked_file_extensions,
23
+ blocked_mime_types,
24
+ } = config;
25
+
26
+ if (allowed_file_extensions?.length) {
27
+ const allowed = allowed_file_extensions.some((fileExtension: string) =>
28
+ file.name?.toLowerCase().endsWith(fileExtension.toLowerCase()),
29
+ );
30
+
31
+ if (!allowed) {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ if (blocked_file_extensions?.length) {
37
+ const blocked = blocked_file_extensions.some((fileExtension: string) =>
38
+ file.name?.toLowerCase().endsWith(fileExtension.toLowerCase()),
39
+ );
40
+
41
+ if (blocked) {
42
+ return false;
43
+ }
44
+ }
45
+
46
+ if (allowed_mime_types?.length) {
47
+ if (file.name) {
48
+ const fileMimeType = lookup(file.name) as string;
49
+ const allowed = allowed_mime_types.some(
50
+ (mimeType: string) => fileMimeType.toLowerCase() === mimeType.toLowerCase(),
51
+ );
52
+
53
+ if (!allowed) {
54
+ return false;
55
+ }
56
+ }
57
+ }
58
+
59
+ if (blocked_mime_types?.length) {
60
+ if (file.name) {
61
+ const fileMimeType = lookup(file.name) as string;
62
+ const blocked = blocked_mime_types.some(
63
+ (mimeType: string) => fileMimeType.toLowerCase() === mimeType.toLowerCase(),
64
+ );
65
+
66
+ if (blocked) {
67
+ return false;
68
+ }
69
+ }
70
+ }
71
+
72
+ return true;
73
+ };
74
+
75
+ /**
76
+ * This utility function prettifies the file size.
77
+ * @param bytes The bytes of the file
78
+ * @param precision The precision to which the file size should be rounded
79
+ * @returns
80
+ */
81
+ export function prettifyFileSize(bytes: number, precision = 3) {
82
+ const units = ['B', 'kB', 'MB', 'GB'];
83
+ const exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
84
+ const mantissa = bytes / 1024 ** exponent;
85
+ return `${mantissa.toPrecision(precision)} ${units[exponent]}`;
86
+ }
package/src/i18n/en.json CHANGED
@@ -24,10 +24,11 @@
24
24
  "Error loading channel list...": "Error loading channel list...",
25
25
  "Error loading messages for this channel...": "Error loading messages for this channel...",
26
26
  "Error while loading, please reload/refresh": "Error while loading, please reload/refresh",
27
+ "File is too large: {{ size }}, maximum upload size is {{ limit }}": "File is too large: {{ size }}, maximum upload size is {{ limit }}",
27
28
  "File type not supported": "File type not supported",
28
29
  "Flag": "Flag",
29
30
  "Flag Message": "Flag Message",
30
- "Flag action failed either due to a network issue or the message is already flagged": "Flag action failed either due to a network issue or the message is already flagged",
31
+ "Flag action failed either due to a network issue or the message is already flagged": "Flag action failed either due to a network issue or the message is already flagged.",
31
32
  "Hold to start recording.": "Hold to start recording.",
32
33
  "How about sending your first message to a friend?": "How about sending your first message to a friend?",
33
34
  "Instant Commands": "Instant Commands",
@@ -36,7 +37,6 @@
36
37
  "Loading channels...": "Loading channels...",
37
38
  "Loading messages...": "Loading messages...",
38
39
  "Loading...": "Loading...",
39
- "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.",
40
40
  "Message Reactions": "Message Reactions",
41
41
  "Message deleted": "Message deleted",
42
42
  "Message flagged": "Message flagged",
package/src/i18n/es.json CHANGED
@@ -1,83 +1,83 @@
1
1
  {
2
- "1 Reply": "",
3
- "1 Thread Reply": "",
4
- "Allow access to your Gallery": "",
5
- "Allow camera access in device settings": "",
6
- "Also send to channel": "",
7
- "Are you sure you want to permanently delete this message?": "",
2
+ "1 Reply": "1 respuesta",
3
+ "1 Thread Reply": "1 respuesta de hilo",
4
+ "Allow access to your Gallery": "Permitir acceso a tu galería",
5
+ "Allow camera access in device settings": "Permitir el acceso a la cámara en la configuración del dispositivo",
6
+ "Also send to channel": "También enviar al canal",
7
+ "Are you sure you want to permanently delete this message?": "¿Estás seguro de que deseas eliminar permanentemente este mensaje?",
8
8
  "Are you sure?": "¿Estás seguro?",
9
- "Block User": "",
10
- "Cancel": "",
11
- "Cannot Flag Message": "",
9
+ "Block User": "Bloquear usuario",
10
+ "Cancel": "Cancelar",
11
+ "Cannot Flag Message": "No se puede reportar el mensaje",
12
12
  "Consider how your comment might make others feel and be sure to follow our Community Guidelines": "Considera cómo tu comentario podría hacer sentir a los demás y asegúrate de seguir nuestras Normas de la Comunidad",
13
- "Copy Message": "",
14
- "Delete": "",
15
- "Delete Message": "",
16
- "Device camera is used to take photos or videos.": "",
17
- "Do you want to send a copy of this message to a moderator for further investigation?": "",
18
- "Edit Message": "",
19
- "Edited": "",
20
- "Editing Message": "",
21
- "Emoji matching": "",
22
- "Empty message...": "",
23
- "Error loading": "",
24
- "Error loading channel list...": "",
25
- "Error loading messages for this channel...": "",
26
- "Error while loading, please reload/refresh": "",
27
- "File type not supported": "",
28
- "Flag": "",
29
- "Flag Message": "",
30
- "Flag action failed either due to a network issue or the message is already flagged": "",
13
+ "Copy Message": "Copiar mensaje",
14
+ "Delete": "Eliminar",
15
+ "Delete Message": "Eliminar mensaje",
16
+ "Device camera is used to take photos or videos.": "La cámara del dispositivo se utiliza para tomar fotografías o vídeos.",
17
+ "Do you want to send a copy of this message to a moderator for further investigation?": "¿Deseas enviar una copia de este mensaje a un moderador para una investigación adicional?",
18
+ "Edit Message": "Editar mensaje",
19
+ "Edited": "Editado",
20
+ "Editing Message": "Editando mensaje",
21
+ "Emoji matching": "Coincidencia de emoji",
22
+ "Empty message...": "Mensaje vacío...",
23
+ "Error loading": "Error al cargar",
24
+ "Error loading channel list...": "Error al cargar la lista de canales...",
25
+ "Error loading messages for this channel...": "Error al cargar los mensajes de este canal...",
26
+ "Error while loading, please reload/refresh": "Error al cargar, por favor recarga/actualiza",
27
+ "File is too large: {{ size }}, maximum upload size is {{ limit }}": "El archivo es demasiado grande: {{ size }}, el tamaño máximo de carga es de {{ limit }}",
28
+ "File type not supported": "Tipo de archivo no admitido",
29
+ "Flag": "Reportar",
30
+ "Flag Message": "Reportar mensaje",
31
+ "Flag action failed either due to a network issue or the message is already flagged": "El reporte falló debido a un problema de red o el mensaje ya fue reportado.",
31
32
  "Hold to start recording.": "Mantén presionado para comenzar a grabar.",
32
- "How about sending your first message to a friend?": "",
33
- "Instant Commands": "",
34
- "Let's start chatting!": "",
35
- "Links are disabled": "",
36
- "Loading channels...": "",
37
- "Loading messages...": "",
38
- "Loading...": "",
39
- "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "",
40
- "Message Reactions": "",
33
+ "How about sending your first message to a friend?": "¿Qué tal enviar tu primer mensaje a un amigo?",
34
+ "Instant Commands": "Comandos instantáneos",
35
+ "Let's start chatting!": "¡Empecemos a charlar!",
36
+ "Links are disabled": "Los enlaces están desactivados",
37
+ "Loading channels...": "Cargando canales...",
38
+ "Loading messages...": "Cargando mensajes...",
39
+ "Loading...": "Cargando...",
40
+ "Message Reactions": "Reacciones al mensaje",
41
41
  "Message deleted": "Mensaje eliminado",
42
- "Message flagged": "",
43
- "Mute User": "",
44
- "No chats here yet…": "",
42
+ "Message flagged": "Mensaje reportado",
43
+ "Mute User": "Silenciar usuario",
44
+ "No chats here yet…": "No hay chats aquí todavía...",
45
45
  "Not supported": "No admitido",
46
- "Nothing yet...": "",
47
- "Ok": "",
48
- "Only visible to you": "",
49
- "Open Settings": "",
50
- "Photo": "",
51
- "Photos and Videos": "",
52
- "Pin to Conversation": "",
53
- "Pinned by": "",
46
+ "Nothing yet...": "Aún no hay nada...",
47
+ "Ok": "Aceptar",
48
+ "Only visible to you": "Solo visible para ti",
49
+ "Open Settings": "Configuración abierta",
50
+ "Photo": "Foto",
51
+ "Photos and Videos": "Fotos y videos",
52
+ "Pin to Conversation": "Fijar a la conversación",
53
+ "Pinned by": "Fijado por",
54
54
  "Please allow Audio permissions in settings.": "Por favor, permita los permisos de audio en la configuración.",
55
- "Please enable access to your photos and videos so you can share them.": "",
56
- "Please select a channel first": "",
55
+ "Please enable access to your photos and videos so you can share them.": "Por favor, habilita el acceso a tus fotos y videos para poder compartirlos.",
56
+ "Please select a channel first": "Por favor, selecciona primero un canal",
57
57
  "Reconnecting...": "Reconectando...",
58
- "Reply": "",
59
- "Reply to Message": "",
60
- "Resend": "",
61
- "Search GIFs": "",
62
- "Select More Photos": "",
58
+ "Reply": "Responder",
59
+ "Reply to Message": "Responder al mensaje",
60
+ "Resend": "Reenviar",
61
+ "Search GIFs": "Buscar GIFs",
62
+ "Select More Photos": "Seleccionar más fotos",
63
63
  "Send Anyway": "Enviar de todos modos",
64
- "Send a message": "",
65
- "Sending links is not allowed in this conversation": "",
66
- "Slow mode ON": "",
67
- "The message has been reported to a moderator.": "",
68
- "Thread Reply": "",
69
- "Unblock User": "",
70
- "Unknown User": "",
71
- "Unmute User": "",
72
- "Unpin from Conversation": "",
73
- "Unread Messages": "",
74
- "Video": "",
64
+ "Send a message": "Enviar un mensaje",
65
+ "Sending links is not allowed in this conversation": "No está permitido enviar enlaces en esta conversación",
66
+ "Slow mode ON": "Modo lento ACTIVADO",
67
+ "The message has been reported to a moderator.": "El mensaje ha sido reportado a un moderador.",
68
+ "Thread Reply": "Respuesta de hilo",
69
+ "Unblock User": "Desbloquear usuario",
70
+ "Unknown User": "Usuario desconocido",
71
+ "Unmute User": "Activar sonido del usuario",
72
+ "Unpin from Conversation": "Desmarcar de la conversación",
73
+ "Unread Messages": "Mensajes no leídos",
74
+ "Video": "Video",
75
75
  "You": "Tú",
76
- "You can't send messages in this channel": "",
77
- "{{ firstUser }} and {{ nonSelfUserLength }} more are typing": "",
78
- "{{ index }} of {{ photoLength }}": "",
79
- "{{ replyCount }} Replies": "",
80
- "{{ replyCount }} Thread Replies": "",
81
- "{{ user }} is typing": "",
82
- "🏙 Attachment...": ""
76
+ "You can't send messages in this channel": "No puedes enviar mensajes en este canal",
77
+ "{{ firstUser }} and {{ nonSelfUserLength }} more are typing": "{{ firstUser }} y {{ nonSelfUserLength }} más están escribiendo",
78
+ "{{ index }} of {{ photoLength }}": "{{ index }} de {{ photoLength }}",
79
+ "{{ replyCount }} Replies": "{{ replyCount }} Respuestas",
80
+ "{{ replyCount }} Thread Replies": "{{ replyCount }} respuestas de hilo",
81
+ "{{ user }} is typing": "{{ user }} está escribiendo",
82
+ "🏙 Attachment...": "🏙 Adjunto..."
83
83
  }