Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions libs/mobile/chat/features/use-edit-message/src/use-edit-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { FormValues } from '@open-webui-react-native/mobile/shared/utils/form';
import {
chatApi,
ChatResponse,
prepareUpdateMessageInChatPayload,
prepareCompleteChatPayload,
prepareUpdateMessageToSendPayload,
prepareEditAssistantMessagePayload,
prepareCopyEditedMessagePayload,
} from '@open-webui-react-native/shared/data-access/api';
import { Role } from '@open-webui-react-native/shared/data-access/common';
import { socketService } from '@open-webui-react-native/shared/data-access/websocket';

interface UseEditMessageProps {
Expand Down Expand Up @@ -47,7 +49,7 @@ export const useEditMessage = ({ chat, modelId }: UseEditMessageProps): typeof r
return;
}

const preparedChat = prepareUpdateMessageInChatPayload(chat, editingMessageId, message);
const preparedChat = prepareCopyEditedMessagePayload(chat, editingMessageId, message);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that due to changes in this logic, we can no longer change the text of the user's message when pressing the "Save" button.

Simulator.Screen.Recording.-.iPhone.17.-.2025-12-15.at.10.50.17.mov

Could you please check?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored this functionality


await updateChat(preparedChat);
cancelEditing();
Expand All @@ -60,10 +62,18 @@ export const useEditMessage = ({ chat, modelId }: UseEditMessageProps): typeof r
const chatHistory = chat.chat.history;
const editedMessage = chatHistory.messages[editingMessageId];

const preparedChat = prepareUpdateMessageToSendPayload(chat, message, modelId, editedMessage.parentId);
let preparedChat: ChatResponse;

if (editedMessage.role === Role.ASSISTANT) {
preparedChat = prepareEditAssistantMessagePayload(chat, editingMessageId, message);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Tomass673 Could you please check the logic for “Save as copy”? When the “Save as copy” button is clicked, the history and history.currentId should be updated (similar to what happens after clicking the “Submit” button when editing a user message).

Also, in order to update the history branch, the prepareEditAssistantMessagePayload should look approximately as follows:


import uuid from 'react-native-uuid';
import { Role } from '@open-webui-react-native/shared/data-access/common';
import { ChatResponse, History } from '../models';
import { createMessagesList } from './create-messages-list';

export function prepareEditAssistantMessagePayload(
  oldData: ChatResponse,
  messageId: string,
  newContent: string,
): ChatResponse {
  const history = oldData.chat.history;
  const messagesMap = { ...history.messages };
  const newAssistantMessageId = uuid.v4()
  const parentId = history?.messages?.[messageId]?.parentId

  const target = messagesMap[messageId];
  if (!target || target.role !== Role.ASSISTANT) return oldData;

  const updatedMessage = {
    ...target,
    childrenIs: [],
    id: newAssistantMessageId,
    content: newContent,
    done: true,
  };

  const updatedHistory: History = {
    ...history,
    currentId: newAssistantMessageId,
    messages: {
      ...history.messages,
      [newAssistantMessageId]: updatedMessage,
    },
    lastAssistantMessage:
      history.lastAssistantMessage?.id === messageId ? updatedMessage : history.lastAssistantMessage,
  };
  updatedHistory.messages[parentId || ''].childrenIds?.push(newAssistantMessageId);

  const lastAssistantMessage =
    updatedHistory.lastAssistantMessage?.id === messageId ? updatedMessage : updatedHistory.lastAssistantMessage;
  
  return {
    ...oldData,
    chat: {
      ...oldData.chat,
      history: {
        ...updatedHistory,
        lastAssistantMessage,
      },
      messages: createMessagesList(updatedHistory, newAssistantMessageId),
    },
  };
}

This comment briefly describes the flow for editing an AI message, with links to the relevant code in the web application – https://app.clickup.com/t/24336023/PRD-1965?comment=90150163295336
We need to implement it in a similar way.

If implemented correctly, "Save As Copy" should work like this:

Simulator.Screen.Recording.-.iPhone.17.-.2025-12-09.at.11.23.25.mov

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

} else {
preparedChat = prepareUpdateMessageToSendPayload(chat, message, modelId, editedMessage.parentId);
}

await updateChat(preparedChat, {
onSuccess: (data) => {
if (editedMessage.role === Role.ASSISTANT) return;

const completePayload = prepareCompleteChatPayload({
chatId: data.id,
messageId: data.chat!.history.currentId,
Expand Down
3 changes: 2 additions & 1 deletion libs/shared/data-access/api/src/lib/chats/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export * from './invalidate-archived-chat-list-query';
export * from './invalidate-search-chats-query';
export * from './create-messages-list';
export * from './patch-chat-with-selected-messages';
export * from './prepare-update-message-in-chat-payload';
export * from './prepare-update-message-to-send-payload';
export * from './prepare-edit-assistant-message-payload';
export * from './prepare-copy-edited-message-payload';
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Role } from '@open-webui-react-native/shared/data-access/common';
import { ChatResponse, Message } from '../models';

export function prepareCopyEditedMessagePayload(
oldData: ChatResponse,
messageId: string,
newContent: string,
): ChatResponse {
const history = oldData.chat.history;
const messagesMap = { ...history.messages };

const target = messagesMap[messageId];
if (!target) return oldData;

const isAIMessage = target.role === Role.ASSISTANT;

const updatedMessage: Message = {
...target,
content: newContent,
};
messagesMap[messageId] = updatedMessage;

if (!isAIMessage) {
const patchedMessagesList = oldData.chat.messages.map((msg) => (msg.id === messageId ? updatedMessage : msg));
const lastAssistantMessage = oldData.chat.history.lastAssistantMessage;

return {
...oldData,
chat: {
...oldData.chat,
history: {
...history,
messages: messagesMap,
lastAssistantMessage,
},
messages: patchedMessagesList,
},
};
}

const chain: Array<Message> = [];
let pointer: Message | undefined = updatedMessage;

while (pointer) {
chain.unshift(pointer);
pointer = pointer.parentId ? messagesMap[pointer.parentId] : undefined;
}

const newCurrentId = updatedMessage.id;

return {
...oldData,
chat: {
...oldData.chat,
history: {
...history,
messages: messagesMap,
currentId: newCurrentId,
lastAssistantMessage: updatedMessage,
},
messages: chain,
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Role } from '@open-webui-react-native/shared/data-access/common';
import { ChatResponse } from '../models';

export function prepareEditAssistantMessagePayload(
oldData: ChatResponse,
messageId: string,
newContent: string,
): ChatResponse {
const history = oldData.chat.history;
const messagesMap = { ...history.messages };

const target = messagesMap[messageId];
if (!target || target.role !== Role.ASSISTANT) return oldData;

const updatedMessage = {
...target,
content: newContent,
done: true,
};

messagesMap[messageId] = updatedMessage;

const updatedMessagesList = oldData.chat.messages.map((m) => (m.id === messageId ? updatedMessage : m));

const lastAssistantMessage =
history.lastAssistantMessage?.id === messageId ? updatedMessage : history.lastAssistantMessage;

return {
...oldData,
chat: {
...oldData.chat,
history: {
...history,
messages: messagesMap,
lastAssistantMessage,
},
messages: updatedMessagesList,
},
};
}

This file was deleted.

Loading