Every message has a row under it to reply or react. Replying quotes the message above the composer, and the sent message stores reply_to_message_id (a plain id, not a foreign key, so deleting the quoted message only drops the quote). send-message accepts a quote from any session of the same conversation, so a rollover or a thread that moved on still sends; the conversation drops a picked quote when its session changes. The bot reads the quote as "[Replying to ...]" before the user's turn, file-only replies included, and relayed messages carry it too. Reactions are a fixed set (BotMessageReactions) in bot_message_reactions, one per message, emoji and user or bot. Users toggle their own through api/admin/bots/react-message, and every bot gets react_to_message for the session it answers (the user's latest message by default). Both push the fresh list as server:bot-reaction, with mine worked out for the session's user. Co-Authored-By: Claude Opus 5.5 <[email protected]>
26 lines
803 B
TypeScript
26 lines
803 B
TypeScript
import Stack from "@moduletrace/twui/layout/Stack";
|
|
import type { BotWithLastMessage } from "@/src/types";
|
|
import type { MessageGroup } from "../(utils)/group-messages";
|
|
import UserMessage from "./user-message";
|
|
import GroupTimestamp from "./group-timestamp";
|
|
|
|
type Props = {
|
|
bot: BotWithLastMessage;
|
|
group: MessageGroup;
|
|
};
|
|
|
|
/**
|
|
* Right-aligned ink bubbles (each message's files above it), one
|
|
* timestamp under the group.
|
|
*/
|
|
export default function UserMessageGroup({ bot, group }: Props) {
|
|
return (
|
|
<Stack className="w-full gap-1! items-end">
|
|
{group.messages.map((message) => (
|
|
<UserMessage key={message.id} message={message} bot_name={bot.name || "the bot"} />
|
|
))}
|
|
<GroupTimestamp at={group.at} />
|
|
</Stack>
|
|
);
|
|
}
|