Skip to content

[Proposal] Refactoring ChatInput: Moving from string manipulation to structured state #1132

@vivekyadav-3

Description

@vivekyadav-3

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions