add group chat
This commit is contained in:
@@ -19,7 +19,8 @@ export interface ChatMessage {
|
||||
interface FetchMessagesParams {
|
||||
groupId: number;
|
||||
limit?: number;
|
||||
afterMessageId?: number | null;
|
||||
afterMessageId?: number;
|
||||
timeoutSeconds?: number;
|
||||
}
|
||||
|
||||
interface SendMessageParams {
|
||||
@@ -33,8 +34,7 @@ interface SendMessageParams {
|
||||
|
||||
interface GroupChatState {
|
||||
messages: Record<number, ChatMessage[]>; // по группам
|
||||
hasMore: Record<number, boolean>; // есть ли ещё старые сообщения
|
||||
isInitialLoaded: Record<number, boolean>; // загружена ли первая порция
|
||||
lastMessage: Record<number, number>;
|
||||
|
||||
fetchMessages: {
|
||||
status: Status;
|
||||
@@ -48,8 +48,7 @@ interface GroupChatState {
|
||||
|
||||
const initialState: GroupChatState = {
|
||||
messages: {},
|
||||
hasMore: {},
|
||||
isInitialLoaded: {},
|
||||
lastMessage: {},
|
||||
fetchMessages: {
|
||||
status: 'idle',
|
||||
error: undefined,
|
||||
@@ -73,13 +72,13 @@ export const fetchGroupMessages = createAsyncThunk(
|
||||
params: {
|
||||
limit: params.limit,
|
||||
afterMessageId: params.afterMessageId,
|
||||
timeoutSeconds: params.timeoutSeconds,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
groupId: params.groupId,
|
||||
messages: response.data as ChatMessage[],
|
||||
afterMessageId: params.afterMessageId,
|
||||
};
|
||||
} catch (err: any) {
|
||||
return rejectWithValue(
|
||||
@@ -117,8 +116,18 @@ const groupChatSlice = createSlice({
|
||||
reducers: {
|
||||
clearChat(state, action: PayloadAction<number>) {
|
||||
delete state.messages[action.payload];
|
||||
delete state.hasMore[action.payload];
|
||||
delete state.isInitialLoaded[action.payload];
|
||||
},
|
||||
setGroupChatStatus: (
|
||||
state,
|
||||
action: PayloadAction<{
|
||||
key: keyof GroupChatState;
|
||||
status: Status;
|
||||
}>,
|
||||
) => {
|
||||
const { key, status } = action.payload;
|
||||
if (state[key]) {
|
||||
(state[key] as any).status = status;
|
||||
}
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
@@ -134,28 +143,22 @@ const groupChatSlice = createSlice({
|
||||
action: PayloadAction<{
|
||||
groupId: number;
|
||||
messages: ChatMessage[];
|
||||
afterMessageId?: number | null;
|
||||
}>,
|
||||
) => {
|
||||
const { groupId, messages, afterMessageId } = action.payload;
|
||||
const { groupId, messages } = action.payload;
|
||||
const existing = state.messages[groupId] || [];
|
||||
|
||||
// первичная загрузка
|
||||
if (!afterMessageId) {
|
||||
state.messages[groupId] = messages;
|
||||
state.isInitialLoaded[groupId] = true;
|
||||
state.hasMore[groupId] = messages.length > 0;
|
||||
}
|
||||
// догружаем старые (scroll up)
|
||||
else if (afterMessageId) {
|
||||
const ids = new Set(existing.map((m) => m.id));
|
||||
const filtered = messages.filter((m) => !ids.has(m.id));
|
||||
console.log('messages', messages);
|
||||
console.log('filtered', filtered);
|
||||
console.log('ids', ids);
|
||||
console.log('existing', existing);
|
||||
state.messages[groupId] = [...existing, ...filtered];
|
||||
state.hasMore[groupId] = filtered.length > 0;
|
||||
const ids = new Set(existing.map((m) => m.id));
|
||||
const filtered = messages.filter((m) => !ids.has(m.id));
|
||||
|
||||
state.messages[groupId] = [...existing, ...filtered].sort(
|
||||
(a, b) => a.id - b.id,
|
||||
);
|
||||
if (state.messages[groupId].length) {
|
||||
state.lastMessage[groupId] =
|
||||
state.messages[groupId][
|
||||
state.messages[groupId].length - 1
|
||||
].id;
|
||||
}
|
||||
|
||||
state.fetchMessages.status = 'successful';
|
||||
@@ -190,5 +193,5 @@ const groupChatSlice = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export const { clearChat } = groupChatSlice.actions;
|
||||
export const { clearChat, setGroupChatStatus } = groupChatSlice.actions;
|
||||
export const groupChatReducer = groupChatSlice.reducer;
|
||||
|
||||
Reference in New Issue
Block a user