Skip to content

Commit

Permalink
fix: removeMessage not working due to outdated messages state (#124)
Browse files Browse the repository at this point in the history
Co-authored-by: Tan Jin <[email protected]>
  • Loading branch information
tanasebutcaru and tjtanjin authored Sep 29, 2024
1 parent b1676ef commit eed543d
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 68 deletions.
5 changes: 4 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
},
"plugins": [
"@typescript-eslint",
"react"
"react",
"react-hooks"
],
"extends": [
"eslint:recommended",
Expand All @@ -20,6 +21,8 @@
"indent": ["error", "tab"],
"react/jsx-indent": ["error", "tab"],
"react/jsx-indent-props": ["error", "tab"],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"max-len": ["error", { "code": 120 }]
}
}
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.2",
"husky": "^8.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
124 changes: 62 additions & 62 deletions src/hooks/internal/useMessagesInternal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,64 @@ export const useMessagesInternal = () => {
// handles rcb events
const { callRcbEvent } = useRcbEventInternal();

/**
* Simulates the streaming of a message from the bot.
*
* @param message message to stream
* @param streamSpeed speed to stream the message
* @param useMarkup boolean indicating whether markup is used
*/
const simulateStream = useCallback(async (message: Message, streamSpeed: number, useMarkup: boolean) => {
// stop bot typing when simulating stream
setIsBotTyping(false);

// set an initial empty message to be used for streaming
setMessages(prevMessages => [...prevMessages, message]);
streamMessageMap.current.set("bot", message.id);

// initialize default message to empty with stream index position 0
let streamMessage = message.content as string | string[];
if (useMarkup) {
streamMessage = parseMarkupMessage(streamMessage as string);
}
let streamIndex = 0;
const endStreamIndex = streamMessage.length;
message.content = "";

const simStreamDoneTask: Promise<void> = new Promise(resolve => {
const intervalId = setInterval(() => {
// consider streaming done once end index is reached or exceeded
// when streaming is done, remove task and resolve the promise
if (streamIndex >= endStreamIndex) {
clearInterval(intervalId);
resolve();
return;
}

setMessages((prevMessages) => {
const updatedMessages = [...prevMessages];
for (let i = updatedMessages.length - 1; i >= 0; i--) {
if (updatedMessages[i].sender === message.sender
&& typeof updatedMessages[i].content === "string") {
const character = streamMessage[streamIndex];
if (character) {
message.content += character;
updatedMessages[i] = message;
}
streamIndex++;
break;
}
}
return updatedMessages;
});
}, streamSpeed);
});

await simStreamDoneTask;
streamMessageMap.current.delete("bot");
saveChatHistory(messages);
}, [messages, streamMessageMap]);

/**
* Injects a message at the end of the messages array.
*
Expand Down Expand Up @@ -76,7 +134,7 @@ export const useMessagesInternal = () => {
}

return message.id;
}, [settings, audioToggledOn, callRcbEvent]);
}, [settings, audioToggledOn, isChatWindowOpen, callRcbEvent, simulateStream]);

/**
* Removes a message with the given id.
Expand All @@ -100,65 +158,7 @@ export const useMessagesInternal = () => {
setMessages((prevMessages) => prevMessages.filter(message => message.id !== messageId));
setUnreadCount((prevCount) => Math.max(prevCount - 1, 0));
return messageId;
}, []);

/**
* Simulates the streaming of a message from the bot.
*
* @param message message to stream
* @param streamSpeed speed to stream the message
* @param useMarkup boolean indicating whether markup is used
*/
const simulateStream = useCallback(async (message: Message, streamSpeed: number, useMarkup: boolean) => {
// stop bot typing when simulating stream
setIsBotTyping(false);

// set an initial empty message to be used for streaming
setMessages(prevMessages => [...prevMessages, message]);
streamMessageMap.current.set("bot", message.id);

// initialize default message to empty with stream index position 0
let streamMessage = message.content as string | string[];
if (useMarkup) {
streamMessage = parseMarkupMessage(streamMessage as string);
}
let streamIndex = 0;
const endStreamIndex = streamMessage.length;
message.content = "";

const simStreamDoneTask: Promise<void> = new Promise(resolve => {
const intervalId = setInterval(() => {
// consider streaming done once end index is reached or exceeded
// when streaming is done, remove task and resolve the promise
if (streamIndex >= endStreamIndex) {
clearInterval(intervalId);
resolve();
return;
}

setMessages((prevMessages) => {
const updatedMessages = [...prevMessages];
for (let i = updatedMessages.length - 1; i >= 0; i--) {
if (updatedMessages[i].sender === message.sender
&& typeof updatedMessages[i].content === "string") {
const character = streamMessage[streamIndex];
if (character) {
message.content += character;
updatedMessages[i] = message;
}
streamIndex++;
break;
}
}
return updatedMessages;
});
}, streamSpeed);
});

await simStreamDoneTask;
streamMessageMap.current.delete("bot");
saveChatHistory(messages);
}, []);
}, [callRcbEvent, messages, settings.event?.rcbRemoveMessage]);

/**
* Streams data into the last message at the end of the messages array with given type.
Expand Down Expand Up @@ -211,7 +211,7 @@ export const useMessagesInternal = () => {
return updatedMessages;
});
return streamMessageMap.current.get(sender) ?? null;
},[]);
},[callRcbEvent, settings.event?.rcbChunkStreamMessage, settings.event?.rcbStartStreamMessage, streamMessageMap]);

/**
* Sets the streaming mode of the chatbot.
Expand Down Expand Up @@ -248,7 +248,7 @@ export const useMessagesInternal = () => {
streamMessageMap.current.delete(sender);
saveChatHistory(messages);
return true;
}, [messages])
}, [callRcbEvent, messages, settings.event?.rcbStopStreamMessage, streamMessageMap])

return {
endStreamMessage,
Expand Down
10 changes: 5 additions & 5 deletions src/hooks/internal/useSubmitInputInternal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const useSubmitInputInternal = () => {
const { endStreamMessage, injectMessage, removeMessage, streamMessage } = useMessagesInternal();

// handles paths
const { getCurrPath, getPrevPath, goToPath, setPaths } = usePathsInternal();
const { getCurrPath, getPrevPath, goToPath } = usePathsInternal();

// handles bot states
const {
Expand Down Expand Up @@ -165,9 +165,9 @@ export const useSubmitInputInternal = () => {
setIsBotTyping(false);
}
}, settings.chatInput?.botDelay);
}, [timeoutId, voiceToggledOn, settings, flowRef, getPrevPath, injectMessage, streamMessage, openChat,
postProcessBlock, setPaths, handleSendUserInput, showToast
]);
}, [timeoutId, settings.chatInput?.blockSpam, settings.chatInput?.botDelay, settings.chatInput?.disabled,
keepVoiceOnRef, voiceToggledOn, syncVoice, handleSendUserInput, getPrevPath, getCurrPath, goToPath,
injectMessage, streamMessage, removeMessage, endStreamMessage, openChat, showToast, dismissToast, flowRef]);

/**
* Handles submission of user input via enter key or send button.
Expand All @@ -191,7 +191,7 @@ export const useSubmitInputInternal = () => {
return;
}
handleActionInput(currPath, inputText, sendInChat);
}, [getCurrPath, handleActionInput, setInputLength])
}, [callRcbEvent, getCurrPath, handleActionInput, inputRef, settings.event?.rcbUserSubmitText])

return { handleSubmitText }
};

0 comments on commit eed543d

Please sign in to comment.