-
Notifications
You must be signed in to change notification settings - Fork 339
Description
Proposal: Improving ChatInput Logic by Avoiding Heavy String Manipulation
Summary
While working on bugs in ChatInput.js (especially the quote-related ones), I noticed that the current approach relies heavily on direct string manipulation. This makes the code harder to maintain and is likely the reason behind several cursor, formatting, and editing bugs.
I want to propose refactoring the input logic to use a state-based approach (or a small state machine) instead of modifying the raw textarea string directly.
Current Problem
At the moment, ChatInput.js handles features like quotes and formatting by inserting or modifying text inside the input field itself. This works, but it’s fragile and easy to break.
Example 1: Quotes
When a user quotes a message, we insert a hidden markdown link directly into the message text:
const quoteLinks = await Promise.all(quoteMessage.map(...));
quotedMessages = quoteLinks.join('');
pendingMessage = createPendingMessage(${quotedMessages}\n${message});
The problem is that this quote becomes part of the plain text. If a user edits or deletes part of it, the link can break. Handling multiple quotes also becomes messy and harder to manage.
Example 2: Formatting
For bold, italics, and other formatting, we manually slice and rebuild the string using cursor positions. This works, but it can behave unexpectedly when text already contains formatting or when the cursor is moved in unusual ways.
Overall, this makes the input logic feel brittle and difficult to extend.
Proposed Idea: Manage Input as Structured State
Instead of treating the input as just a string, we could store it as a structured state object.
For example:
{
text: "User's message here",
cursorPosition: 12,
quotes: [
{ id: "msg_123", author: "UserA" }
],
isEditingId: null
}
This allows us to keep quotes, cursor position, and text separate instead of mixing everything into one string.
How It Could Work
We could use a reducer or a custom hook (like useChatInputState) that handles specific actions:
ADD_QUOTE → Adds a quote to the quotes array without changing the text
SET_TEXT → Updates only the message text
SEND_MESSAGE → Combines quotes and text into the final markdown format when sending
This keeps editing safer and avoids breaking structured content while typing.
Benefits of This Approach
More stable behavior: Editing text won’t accidentally corrupt quotes or links
Cleaner UI options: Quotes could appear as visual “chips” above the input instead of hidden text
Easier to extend later: Adding features like slash commands or rich text becomes simpler
Improved maintainability: The logic becomes more predictable and easier to debug
Next Steps
I plan to build a small prototype hook called useChatInputState as part of my GSoC work to test this idea.
I’d also love to understand if there was a specific reason the original string-based approach was chosen, in case there are constraints I should keep in mind.