Skip to content

Commit

Permalink
fix: add useCallback to a couple of functions
Browse files Browse the repository at this point in the history
  • Loading branch information
khushal87 committed Aug 29, 2024
1 parent 3263159 commit 96e00d4
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Alert, ImageBackground, Platform, StyleSheet, Text, View } from 'react-
import { TouchableOpacity } from '@gorhom/bottom-sheet';
import { lookup } from 'mime-types';

import type { AttachmentPickerContextValue } from '../../../contexts/attachmentPickerContext/AttachmentPickerContext';
import { AttachmentPickerContextValue } from '../../../contexts/attachmentPickerContext/AttachmentPickerContext';
import { useTheme } from '../../../contexts/themeContext/ThemeContext';
import { useViewport } from '../../../hooks/useViewport';
import { Recorder } from '../../../icons';
Expand All @@ -23,7 +23,6 @@ type AttachmentPickerItemType = Pick<
selected: boolean;
numberOfAttachmentPickerImageColumns?: number;
};

type AttachmentImageProps = Omit<AttachmentPickerItemType, 'setSelectedFiles' | 'selectedFiles'>;

type AttachmentVideoProps = Omit<AttachmentPickerItemType, 'setSelectedImages' | 'selectedImages'>;
Expand Down
5 changes: 3 additions & 2 deletions package/src/components/MessageInput/FileUploadPreview.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { FlatList, I18nManager, StyleSheet, Text, TouchableOpacity, View } from 'react-native';

import { UploadProgressIndicator } from './UploadProgressIndicator';
Expand Down Expand Up @@ -34,6 +34,7 @@ const styles = StyleSheet.create({
dismiss: {
borderRadius: 24,
height: 24,
marginRight: 4,
position: 'absolute',
right: 8,
top: 8,
Expand Down Expand Up @@ -299,7 +300,7 @@ const FileUploadPreviewWithContext = <
);
};

const fileUploadsLength = fileUploads.length;
const fileUploadsLength = useMemo(() => fileUploads.length, [fileUploads.length]);

useEffect(() => {
if (fileUploadsLength && flatListRef.current) {
Expand Down
196 changes: 114 additions & 82 deletions package/src/contexts/messageInputContext/MessageInputContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import type { LegacyRef } from 'react';
import React, { PropsWithChildren, useContext, useEffect, useRef, useState } from 'react';
import React, {
LegacyRef,
PropsWithChildren,
useCallback,
useContext,
useEffect,
useRef,
useState,
} from 'react';
import { Alert, Keyboard, Linking, TextInput, TextInputProps } from 'react-native';

import uniq from 'lodash/uniq';
Expand Down Expand Up @@ -46,7 +53,7 @@ import type { SendButtonProps } from '../../components/MessageInput/SendButton';
import type { UploadProgressIndicatorProps } from '../../components/MessageInput/UploadProgressIndicator';
import type { MessageType } from '../../components/MessageList/hooks/useMessageList';
import type { Emoji } from '../../emoji-data';
import { pickDocument, pickImage, takePhoto } from '../../native';
import { isImageMediaLibraryAvailable, pickDocument, pickImage, takePhoto } from '../../native';
import {
Asset,
DefaultStreamChatGenerics,
Expand Down Expand Up @@ -690,30 +697,30 @@ export const MessageInputProvider = <
/**
* Function to open the attachment picker if the MediaLibary is installed.
*/
const openAttachmentPicker = () => {
const openAttachmentPicker = useCallback(() => {
Keyboard.dismiss();
setSelectedPicker('images');
openPicker();
};
}, [openPicker, setSelectedPicker]);

/**
* Function to close the attachment picker if the MediaLibrary is installed.
*/
const closeAttachmentPicker = () => {
const closeAttachmentPicker = useCallback(() => {
setSelectedPicker(undefined);
closePicker();
};
}, [closePicker, setSelectedPicker]);

/**
* Function to toggle the attachment picker if the MediaLibrary is installed.
*/
const toggleAttachmentPicker = () => {
const toggleAttachmentPicker = useCallback(() => {
if (selectedPicker) {
closeAttachmentPicker();
} else {
openAttachmentPicker();
}
};
}, [closeAttachmentPicker, openAttachmentPicker, selectedPicker]);

const onSelectItem = (item: UserResponse<StreamChatGenerics>) => {
setMentionedUsers((prevMentionedUsers) => [...prevMentionedUsers, item.id]);
Expand Down Expand Up @@ -750,21 +757,35 @@ export const MessageInputProvider = <
}
};

const removeFile = (id: string) => {
if (fileUploads.some((file) => file.id === id)) {
setFileUploads((prevFileUploads) => prevFileUploads.filter((file) => file.id !== id));
setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
}
};
const removeFile = useCallback(
(id: string) => {
if (fileUploads.some((file) => file.id === id)) {
setFileUploads((prevFileUploads) => prevFileUploads.filter((file) => file.id !== id));
setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
}
},
[fileUploads, setFileUploads, setNumberOfUploads],
);

const removeImage = (id: string) => {
if (imageUploads.some((image) => image.id === id)) {
setImageUploads((prevImageUploads) => prevImageUploads.filter((image) => image.id !== id));
setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
}
};
const removeImage = useCallback(
(id: string) => {
if (imageUploads.some((image) => image.id === id)) {
setImageUploads((prevImageUploads) => prevImageUploads.filter((image) => image.id !== id));
setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
}
},
[imageUploads, setImageUploads, setNumberOfUploads],
);

const resetInput = (pendingAttachments: Attachment<StreamChatGenerics>[] = []) => {
/**
* If the MediaLibrary is available, reset the selected files and images
*/
if (isImageMediaLibraryAvailable()) {
setSelectedFiles([]);
setSelectedImages([]);
}

setFileUploads([]);
setGiphyActive(false);
setShowMoreOptions(true);
Expand Down Expand Up @@ -1250,87 +1271,98 @@ export const MessageInputProvider = <
};

const uploadNewFile = async (file: File) => {
const id: string = generateRandomId();
const fileConfig = getFileUploadConfig();
const { size_limit } = fileConfig;
try {
const id: string = generateRandomId();
const fileConfig = getFileUploadConfig();
const { size_limit } = fileConfig;

const isAllowed = isUploadAllowed({ config: fileConfig, file });
const isAllowed = isUploadAllowed({ config: fileConfig, file });

const sizeLimit = size_limit || MAX_FILE_SIZE_TO_UPLOAD;
const sizeLimit = size_limit || MAX_FILE_SIZE_TO_UPLOAD;

if (file.size && file.size > sizeLimit) {
Alert.alert(
t('File is too large: {{ size }}, maximum upload size is {{ limit }}', {
limit: prettifyFileSize(sizeLimit),
size: prettifyFileSize(file.size),
}),
);
setSelectedFiles(selectedFiles.filter((selectedFile) => selectedFile.uri !== file.uri));
return;
}
if (file.size && file.size > sizeLimit) {
Alert.alert(
t('File is too large: {{ size }}, maximum upload size is {{ limit }}', {
limit: prettifyFileSize(sizeLimit),
size: prettifyFileSize(file.size),
}),
);
setSelectedFiles(selectedFiles.filter((selectedFile) => selectedFile.uri !== file.uri));
return;
}

const fileState = isAllowed ? FileState.UPLOADING : FileState.NOT_SUPPORTED;
const fileState = isAllowed ? FileState.UPLOADING : FileState.NOT_SUPPORTED;

// If file type is explicitly provided while upload we use it, else we derive the file type.
const fileType = file.type || file.mimeType?.split('/')[0];
// If file type is explicitly provided while upload we use it, else we derive the file type.
const fileType = file.type || file.mimeType?.split('/')[0];

const newFile: FileUpload = {
duration: file.duration || 0,
file,
id: file.id || id,
state: fileState,
type: fileType,
};
const newFile: FileUpload = {
duration: file.duration || 0,
file,
id: file.id || id,
state: fileState,
type: fileType,
url: file.uri,
};

await Promise.all([
setFileUploads((prevFileUploads) => prevFileUploads.concat([newFile])),
setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads + 1),
]);
await Promise.all([
setFileUploads((prevFileUploads) => prevFileUploads.concat([newFile])),
setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads + 1),
]);

if (isAllowed) {
await uploadFile({ newFile });
if (isAllowed) {
await uploadFile({ newFile });
}
} catch (error) {
console.log('Error uploading file', error);
}
};

const uploadNewImage = async (image: Partial<Asset>) => {
const id = generateRandomId();
const imageUploadConfig = getImageUploadConfig();
try {
const id = generateRandomId();
const imageUploadConfig = getImageUploadConfig();

const { size_limit } = imageUploadConfig;
const { size_limit } = imageUploadConfig;

const isAllowed = isUploadAllowed({ config: imageUploadConfig, file: image });
const isAllowed = isUploadAllowed({ config: imageUploadConfig, file: image });

const sizeLimit = size_limit || MAX_FILE_SIZE_TO_UPLOAD;
const sizeLimit = size_limit || MAX_FILE_SIZE_TO_UPLOAD;

if (image.size && image?.size > sizeLimit) {
Alert.alert(
t('File is too large: {{ size }}, maximum upload size is {{ limit }}', {
limit: prettifyFileSize(sizeLimit),
size: prettifyFileSize(image.size),
}),
);
setSelectedImages(selectedImages.filter((selectedImage) => selectedImage.uri !== image.uri));
return;
}
if (image.size && image?.size > sizeLimit) {
Alert.alert(
t('File is too large: {{ size }}, maximum upload size is {{ limit }}', {
limit: prettifyFileSize(sizeLimit),
size: prettifyFileSize(image.size),
}),
);
setSelectedImages(
selectedImages.filter((selectedImage) => selectedImage.uri !== image.uri),
);
return;
}

const imageState = isAllowed ? FileState.UPLOADING : FileState.NOT_SUPPORTED;
const imageState = isAllowed ? FileState.UPLOADING : FileState.NOT_SUPPORTED;

const newImage: ImageUpload = {
file: image,
height: image.height,
id,
state: imageState,
url: image.uri,
width: image.width,
};
const newImage: ImageUpload = {
file: image,
height: image.height,
id,
state: imageState,
url: image.uri,
width: image.width,
};

await Promise.all([
setImageUploads((prevImageUploads) => prevImageUploads.concat([newImage])),
setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads + 1),
]);
await Promise.all([
setImageUploads((prevImageUploads) => prevImageUploads.concat([newImage])),
setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads + 1),
]);

if (isAllowed) {
await uploadImage({ newImage });
if (isAllowed) {
await uploadImage({ newImage });
}
} catch (error) {
console.log('Error uploading image', error);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
FileUpload,
ImageUpload,
} from '../../../types/types';
import { generateRandomId } from '../../../utils/utils';
import { generateRandomId, stringifyMessage } from '../../../utils/utils';

import type { MessageInputContextValue } from '../MessageInputContext';

Expand Down Expand Up @@ -37,8 +37,7 @@ export const useMessageDetailsForState = <
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [text, imageUploads.length, fileUploads.length]);

const messageValue =
message === undefined ? '' : `${message.id}${message.text}${message.updated_at}`;
const messageValue = message ? stringifyMessage(message) : '';

useEffect(() => {
if (message && Array.isArray(message?.mentioned_users)) {
Expand Down Expand Up @@ -67,9 +66,11 @@ export const useMessageDetailsForState = <
} else if (attachment.type === FileTypes.Video) {
return {
file: {
duration: attachment.duration,
mimeType: attachment.mime_type,
name: attachment.title || '',
size: attachment.file_size,
uri: attachment.asset_url,
},
id,
state: 'finished',
Expand All @@ -96,6 +97,7 @@ export const useMessageDetailsForState = <
mimeType: attachment.mime_type,
name: attachment.title || '',
size: attachment.file_size,
uri: attachment.asset_url,
},
id,
state: 'finished',
Expand All @@ -107,6 +109,7 @@ export const useMessageDetailsForState = <
mimeType: attachment.mime_type,
name: attachment.title || '',
size: attachment.file_size,
uri: attachment.asset_url,
},
id,
state: 'finished',
Expand All @@ -128,9 +131,11 @@ export const useMessageDetailsForState = <
const id = generateRandomId();
newImageUploads.push({
file: {
height: attachment.original_height,
name: attachment.fallback,
size: attachment.file_size,
type: attachment.type,
width: attachment.original_width,
},
id,
state: 'finished',
Expand Down

0 comments on commit 96e00d4

Please sign in to comment.