fix(web): DM_CHANNEL_UPDATE и DM_CHANNEL_DELETE обновляют список бесед

Сервер присылал эти события и раньше, но клиент перечитывал список бесед только
по `DM_CHANNEL_CREATE` и READY: добавление участника, переименование группы и
выход из неё не появлялись в сайдбаре до перезагрузки, а удалённая беседа
оставалась открытой.

Теперь все три события перечитывают список (`DM_CHANNEL_UPDATE` меняет состав,
имя и аватар группы сразу), а `DM_CHANNEL_DELETE` дополнительно убирает беседу
из стора сессии и закрывает её, если она была открыта.

Тесты в `web/tests/friends.test.tsx` падают на старом коде: переименование
группы видно второму участнику, удалённая беседа исчезает и закрывается.
This commit is contained in:
2026-09-26 16:16:10 +03:00
parent 45a5eaae64
commit 324d2aac72
3 changed files with 82 additions and 3 deletions
+13 -3
View File
@@ -378,11 +378,21 @@ export function dispatchGatewayEvent(event: GatewayDispatch): void {
}
return;
}
case 'DM_CHANNEL_CREATE': {
// В событии только channel_id: список бесед забираем по REST.
case 'DM_CHANNEL_CREATE':
case 'DM_CHANNEL_UPDATE':
case 'DM_CHANNEL_DELETE': {
// В событии только channel_id: список бесед забираем по REST. CREATE —
// новая беседа, UPDATE — изменился состав или имя группы, DELETE —
// беседа больше не наша (нас удалили). Список читается целиком, потому
// что от состава зависят и имя, и аватар, и шапка беседы.
const direct = parseDmChannelEvent(event.d);
if (direct !== null) {
void session.reloadDmChannels();
void session.reloadDmChannels().then(() => {
if (event.t === 'DM_CHANNEL_DELETE') {
// Удалённая беседа могла быть открыта: уводим в список бесед.
useSessionStore.getState().removeDmChannel(direct.channel_id);
}
});
}
return;
}
+11
View File
@@ -114,6 +114,8 @@ interface SessionState {
reloadDmChannels: () => Promise<void>;
/** CHANNEL_DELETE: удаляет комнату и переносит выбор на первую доступную. */
removeChannel: (guildId: string, channelId: string) => void;
/** DM_CHANNEL_DELETE: беседа пропала — убирает её из списка и из выбора. */
removeDmChannel: (channelId: string) => void;
/** GUILD_CHANNELS_SYNC: перечитать видимые комнаты сервера (права изменились). */
reloadGuildChannels: (guildId: string) => Promise<void>;
/** То же, но с объединением частых вызовов в один запрос. */
@@ -582,6 +584,15 @@ export const useSessionStore = create<SessionState>((set, get) => ({
});
},
removeDmChannel: (channelId) => {
const state = get();
set({
dmChannels: state.dmChannels.filter((channel) => channel.id !== channelId),
// Если пропала открытая беседа, показываем список бесед раздела друзей.
selectedChannelId: state.selectedChannelId === channelId ? null : state.selectedChannelId,
});
},
firstChannelId: (guildId) => {
const guild = get().guilds.find((item) => item.id === guildId);
return guild === undefined ? null : firstVisibleChannelId(guild);