feat: add reply/forward/pin message flow across backend and web
Some checks failed
CI / test (push) Failing after 24s

- add reply_to/forwarded_from message fields and chat pinned_message field

- add forward and pin APIs plus reply support in message create

- wire web actions: Reply, Fwd, Pin and reply composer state

- fix spam policy bug: allow repeated identical messages, keep rate limiting
This commit is contained in:
2026-03-08 00:28:43 +03:00
parent 4d704fc279
commit e1d0375392
18 changed files with 287 additions and 29 deletions

View File

@@ -7,6 +7,7 @@ interface ChatState {
activeChatId: number | null;
messagesByChat: Record<number, Message[]>;
typingByChat: Record<number, number[]>;
replyToByChat: Record<number, Message | null>;
loadChats: (query?: string) => Promise<void>;
setActiveChatId: (chatId: number | null) => void;
loadMessages: (chatId: number) => Promise<void>;
@@ -22,6 +23,8 @@ interface ChatState {
removeOptimisticMessage: (chatId: number, clientMessageId: string) => void;
setMessageDeliveryStatus: (chatId: number, messageId: number, status: DeliveryStatus) => void;
setTypingUsers: (chatId: number, userIds: number[]) => void;
setReplyToMessage: (chatId: number, message: Message | null) => void;
updateChatPinnedMessage: (chatId: number, pinnedMessageId: number | null) => void;
}
export const useChatStore = create<ChatState>((set, get) => ({
@@ -29,6 +32,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
activeChatId: null,
messagesByChat: {},
typingByChat: {},
replyToByChat: {},
loadChats: async (query) => {
const chats = await getChats(query);
const currentActive = get().activeChatId;
@@ -134,5 +138,11 @@ export const useChatStore = create<ChatState>((set, get) => ({
}));
},
setTypingUsers: (chatId, userIds) =>
set((state) => ({ typingByChat: { ...state.typingByChat, [chatId]: userIds } }))
set((state) => ({ typingByChat: { ...state.typingByChat, [chatId]: userIds } })),
setReplyToMessage: (chatId, message) =>
set((state) => ({ replyToByChat: { ...state.replyToByChat, [chatId]: message } })),
updateChatPinnedMessage: (chatId, pinnedMessageId) =>
set((state) => ({
chats: state.chats.map((chat) => (chat.id === chatId ? { ...chat, pinned_message_id: pinnedMessageId } : chat))
}))
}));