Skip to content

Commit

Permalink
feat: optimistic updates for new message
Browse files Browse the repository at this point in the history
  • Loading branch information
vishalnarkhede committed Oct 31, 2022
1 parent f3812ff commit be79ba2
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 119 deletions.
182 changes: 121 additions & 61 deletions package/src/components/Channel/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';

import {
Channel as ChannelClass,
ChannelState,
Channel as ChannelType,
ConnectionChangeEvent,
Expand Down Expand Up @@ -74,6 +75,7 @@ import {
WutReaction,
} from '../../icons';
import { FlatList as FlatListDefault } from '../../native';
import * as dbApi from '../../store/apis';
import type { DefaultStreamChatGenerics } from '../../types/types';
import { addReactionToLocalState } from '../../utils/addReactionToLocalState';
import { queueTask } from '../../utils/pendingTaskUtils';
Expand Down Expand Up @@ -201,7 +203,7 @@ export type ChannelPropsWithContext<
| 'StickyHeader'
>
> &
Pick<ChatContextValue<StreamChatGenerics>, 'client' | 'isOnline'> &
Pick<ChatContextValue<StreamChatGenerics>, 'client' | 'enableOfflineSupport'> &
Partial<
Omit<
InputMessageInputContextValue<StreamChatGenerics>,
Expand Down Expand Up @@ -427,6 +429,7 @@ const ChannelWithContext = <
doUpdateMessageRequest,
EmptyStateIndicator = EmptyStateIndicatorDefault,
enableMessageGroupingByUser = true,
enableOfflineSupport,
enforceUniqueReaction = false,
FileAttachment = FileAttachmentDefault,
FileAttachmentGroup = FileAttachmentGroupDefault,
Expand Down Expand Up @@ -467,7 +470,6 @@ const ChannelWithContext = <
InputGiphySearch = InputGiphyCommandInputDefault,
InputReplyStateHeader = InputReplyStateHeaderDefault,
isAttachmentEqual,
isOnline,
keyboardBehavior,
KeyboardCompatibleView = KeyboardCompatibleViewDefault,
keyboardVerticalOffset,
Expand Down Expand Up @@ -1169,6 +1171,7 @@ const ChannelWithContext = <
extraState = {},
) => {
if (channel) {
console.log(updatedMessage);
channel.state.addMessageSorted(updatedMessage, true);
if (thread && updatedMessage.parent_id) {
extraState.threadMessages = channel.state.threads[updatedMessage.parent_id] || [];
Expand Down Expand Up @@ -1268,6 +1271,8 @@ const ChannelWithContext = <
...extraFields
} = message;

if (!channel.id) return;

const messageData = {
attachments,
id: retrying ? undefined : id,
Expand All @@ -1279,12 +1284,25 @@ const ChannelWithContext = <

try {
let messageResponse = {} as SendMessageAPIResponse<StreamChatGenerics>;

if (doSendMessageRequest) {
messageResponse = await doSendMessageRequest(channel?.cid || '', messageData);
} else if (channel) {
} else if (!enableOfflineSupport || retrying) {
messageResponse = await channel.sendMessage(messageData);
} else if (channel) {
dbApi.upsertMessages({
messages: [{ ...message, cid: channel.cid }],
});
messageResponse = (await queueTask({
client,
task: {
channelId: channel.id,
channelType: channel.type,
payload: [messageData],
type: 'send-message',
},
})) as SendMessageAPIResponse<StreamChatGenerics>;
}

if (messageResponse.message) {
messageResponse.message.status = MessageStatusTypes.RECEIVED;
if (retrying) {
Expand All @@ -1296,6 +1314,9 @@ const ChannelWithContext = <
} catch (err) {
console.log(err);
message.status = MessageStatusTypes.FAILED;
dbApi.upsertMessages({
messages: [{ ...message, cid: channel.cid }],
});
updateMessage(message);
}
};
Expand Down Expand Up @@ -1477,67 +1498,105 @@ const ChannelWithContext = <
}
};

const addReaction: MessagesContextValue<StreamChatGenerics>['addReaction'] = useCallback(
(type, messageId) => {
if (!channel?.id || !client.user) return;
const sendReaction: MessagesContextValue<StreamChatGenerics>['sendReaction'] = (
type,
messageId,
) => {
if (!channel?.id || !client.user) return;

const payload: Parameters<ChannelClass<StreamChatGenerics>['sendReaction']> = [
messageId,
{
type,
} as Reaction<StreamChatGenerics>,
{ enforce_unique: enforceUniqueReaction },
];

if (!enableOfflineSupport) {
return channel.sendReaction(...payload);
}

addReactionToLocalState<StreamChatGenerics>({
channel,
enforceUniqueReaction,
messageId,
reactionType: type,
user: client.user,
});
addReactionToLocalState<StreamChatGenerics>({
channel,
enforceUniqueReaction,
messageId,
reactionType: type,
user: client.user,
});

setMessages(channel.state.messages);
setMessages(channel.state.messages);

const payload = [
messageId,
{
type,
} as Reaction<StreamChatGenerics>,
{ enforce_unique: enforceUniqueReaction },
];
queueTask({
client,
task: {
channelId: channel.id,
channelType: channel.type,
payload,
type: 'send-reaction',
},
});
};

queueTask({
client,
task: {
channelId: channel.id,
channelType: channel.type,
payload,
type: 'send-reaction',
},
});
},
[isOnline],
);
const deleteMessage: MessagesContextValue<StreamChatGenerics>['deleteMessage'] = async (
message,
) => {
if (!channel.id) return;

dbApi.updateMessage({
message: {
...message,
cid: channel.cid,
deleted_at: new Date().toISOString(),
type: 'deleted',
},
});
updateMessage({ ...message, deleted_at: new Date().toISOString(), type: 'deleted' });
const data = await queueTask({
client,
task: {
channelId: channel.id,
channelType: channel.type,
payload: [message.id],
type: 'delete-message',
},
});

const removeReaction: MessagesContextValue<StreamChatGenerics>['removeReaction'] = useCallback(
(type: string, messageId: string) => {
if (!channel?.id || !client.user) return;
if (data?.message) {
updateMessage({ ...data.message });
}
};

removeReactionFromLocalState({
channel,
messageId,
reactionType: type,
user: client.user,
});
const deleteReaction: MessagesContextValue<StreamChatGenerics>['deleteReaction'] = (
type: string,
messageId: string,
) => {
if (!channel?.id || !client.user) return;

setMessages(channel.state.messages);
const payload: Parameters<ChannelClass['deleteReaction']> = [messageId, type];

const payload = [messageId, type];
queueTask({
client,
task: {
channelId: channel.id,
channelType: channel.type,
payload,
type: 'delete-reaction',
},
});
},
[isOnline],
);
if (!enableOfflineSupport) {
return channel.deleteReaction(...payload);
}

removeReactionFromLocalState({
channel,
messageId,
reactionType: type,
user: client.user,
});

setMessages(channel.state.messages);

return queueTask({
client,
task: {
channelId: channel.id,
channelType: channel.type,
payload,
type: 'delete-reaction',
},
});
};

/**
* THREAD METHODS
Expand Down Expand Up @@ -1712,7 +1771,6 @@ const ChannelWithContext = <

const messagesContext = useCreateMessagesContext({
additionalTouchableProps,
addReaction,
Attachment,
AttachmentActions,
AudioAttachment,
Expand All @@ -1723,6 +1781,8 @@ const ChannelWithContext = <
channelId,
DateHeader,
deletedMessagesVisibilityType,
deleteMessage,
deleteReaction,
disableTypingIndicator,
dismissKeyboardOnMessageTouch,
enableMessageGroupingByUser,
Expand Down Expand Up @@ -1778,11 +1838,11 @@ const ChannelWithContext = <
OverlayReactionList,
ReactionList,
removeMessage,
removeReaction,
Reply,
retrySendMessage,
ScrollToBottomButton,
selectReaction,
sendReaction,
setEditingState,
setQuotedMessageState,
supportedReactions,
Expand Down Expand Up @@ -1878,7 +1938,7 @@ export const Channel = <
>(
props: PropsWithChildren<ChannelProps<StreamChatGenerics>>,
) => {
const { client, isOnline } = useChatContext<StreamChatGenerics>();
const { client, enableOfflineSupport } = useChatContext<StreamChatGenerics>();
const { t } = useTranslationContext();

const shouldSyncChannel = props.thread?.id ? !!props.threadList : true;
Expand Down Expand Up @@ -1907,7 +1967,7 @@ export const Channel = <
<ChannelWithContext<StreamChatGenerics>
{...{
client,
isOnline,
enableOfflineSupport,
t,
}}
{...props}
Expand Down
12 changes: 6 additions & 6 deletions package/src/components/Channel/hooks/useCreateMessagesContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const useCreateMessagesContext = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
>({
additionalTouchableProps,
addReaction,
Attachment,
AttachmentActions,
AudioAttachment,
Expand All @@ -18,6 +17,8 @@ export const useCreateMessagesContext = <
channelId,
DateHeader,
deletedMessagesVisibilityType,
deleteMessage,
deleteReaction,
disableTypingIndicator,
dismissKeyboardOnMessageTouch,
enableMessageGroupingByUser,
Expand Down Expand Up @@ -73,11 +74,11 @@ export const useCreateMessagesContext = <
OverlayReactionList,
ReactionList,
removeMessage,
removeReaction,
Reply,
retrySendMessage,
ScrollToBottomButton,
selectReaction,
sendReaction,
setEditingState,
setQuotedMessageState,
supportedReactions,
Expand All @@ -101,7 +102,7 @@ export const useCreateMessagesContext = <
const messagesContext: MessagesContextValue<StreamChatGenerics> = useMemo(
() => ({
additionalTouchableProps,
addReaction,
sendReaction,
Attachment,
AttachmentActions,
AudioAttachment,
Expand All @@ -110,6 +111,7 @@ export const useCreateMessagesContext = <
CardFooter,
CardHeader,
DateHeader,
deleteMessage,
deletedMessagesVisibilityType,
disableTypingIndicator,
dismissKeyboardOnMessageTouch,
Expand Down Expand Up @@ -166,7 +168,7 @@ export const useCreateMessagesContext = <
OverlayReactionList,
ReactionList,
removeMessage,
removeReaction,
deleteReaction,
Reply,
retrySendMessage,
ScrollToBottomButton,
Expand All @@ -188,8 +190,6 @@ export const useCreateMessagesContext = <
dismissKeyboardOnMessageTouch,
initialScrollToFirstUnreadMessage,
markdownRulesLength,
addReaction,
removeReaction,
messageContentOrderValue,
supportedReactionsLength,
targetedMessage,
Expand Down
Loading

0 comments on commit be79ba2

Please sign in to comment.