111 lines
2.9 KiB
TypeScript
111 lines
2.9 KiB
TypeScript
import { create } from "zustand";
|
|
import { api } from "../lib/api.ts";
|
|
|
|
export interface Message {
|
|
id: string;
|
|
channel_id: string;
|
|
author_id: string;
|
|
author_username: string;
|
|
author_display_name: string | null;
|
|
content: string;
|
|
created_at: string;
|
|
edited_at: string | null;
|
|
}
|
|
|
|
interface MessageState {
|
|
messagesByChannel: Record<string, Message[]>;
|
|
isLoading: boolean;
|
|
error: string | null;
|
|
fetchMessages: (channelId: string, before?: string) => Promise<void>;
|
|
sendMessage: (channelId: string, content: string) => Promise<Message>;
|
|
addMessage: (message: Message) => void;
|
|
updateMessage: (message: Message) => void;
|
|
removeMessage: (channelId: string, messageId: string) => void;
|
|
}
|
|
|
|
export const useMessageStore = create<MessageState>((set) => ({
|
|
messagesByChannel: {},
|
|
isLoading: false,
|
|
error: null,
|
|
|
|
fetchMessages: async (channelId, before) => {
|
|
set({ isLoading: true, error: null });
|
|
try {
|
|
const params = before ? `?before=${encodeURIComponent(before)}` : "";
|
|
const messages = await api.get<Message[]>(
|
|
`/channels/${channelId}/messages${params}`,
|
|
);
|
|
set((state) => ({
|
|
messagesByChannel: {
|
|
...state.messagesByChannel,
|
|
[channelId]: Array.isArray(messages) ? messages : [],
|
|
},
|
|
isLoading: false,
|
|
}));
|
|
} catch (error) {
|
|
set({
|
|
isLoading: false,
|
|
error:
|
|
error instanceof Error
|
|
? error.message
|
|
: "Failed to fetch messages",
|
|
});
|
|
}
|
|
},
|
|
|
|
sendMessage: async (channelId, content) => {
|
|
const message = await api.post<Message>(
|
|
`/channels/${channelId}/messages`,
|
|
{ content },
|
|
);
|
|
set((state) => {
|
|
const list = state.messagesByChannel[channelId] || [];
|
|
return {
|
|
messagesByChannel: {
|
|
...state.messagesByChannel,
|
|
[channelId]: [...list, message],
|
|
},
|
|
};
|
|
});
|
|
return message;
|
|
},
|
|
|
|
addMessage: (message) =>
|
|
set((state) => {
|
|
const list = state.messagesByChannel[message.channel_id] || [];
|
|
if (list.some((m) => m.id === message.id)) {
|
|
return state;
|
|
}
|
|
return {
|
|
messagesByChannel: {
|
|
...state.messagesByChannel,
|
|
[message.channel_id]: [...list, message],
|
|
},
|
|
};
|
|
}),
|
|
|
|
updateMessage: (message) =>
|
|
set((state) => {
|
|
const list = state.messagesByChannel[message.channel_id] || [];
|
|
return {
|
|
messagesByChannel: {
|
|
...state.messagesByChannel,
|
|
[message.channel_id]: list.map((m) =>
|
|
m.id === message.id ? message : m,
|
|
),
|
|
},
|
|
};
|
|
}),
|
|
|
|
removeMessage: (channelId, messageId) =>
|
|
set((state) => {
|
|
const list = state.messagesByChannel[channelId] || [];
|
|
return {
|
|
messagesByChannel: {
|
|
...state.messagesByChannel,
|
|
[channelId]: list.filter((m) => m.id !== messageId),
|
|
},
|
|
};
|
|
}),
|
|
}));
|