fix(guild): invalidate member sidebar on role changes (#2369)

This commit is contained in:
Hampus
2026-09-02 17:28:44 +02:00
committed by GitHub
parent cc92f37f0c
commit 1598f48edd
5 changed files with 52 additions and 0 deletions
@@ -3,6 +3,7 @@
import type {GatewayHandlerContext} from '@app/features/gateway/events/EventRouter';
import GuildReadState from '@app/features/guild/state/GuildReadState';
import Guilds from '@app/features/guild/state/Guilds';
import MemberSidebar from '@app/features/member/state/MemberSidebar';
import Permission from '@app/features/permissions/state/Permission';
import type {GuildRole} from '@fluxer/schema/src/domains/guild/GuildRoleSchemas';
@@ -13,6 +14,7 @@ interface GuildRoleCreatePayload {
export function handleGuildRoleCreate(data: GuildRoleCreatePayload, _context: GatewayHandlerContext): void {
Guilds.handleGuildRoleCreate({guildId: data.guild_id, role: data.role});
MemberSidebar.handleGuildStorageIdentityChange(data.guild_id);
Permission.handleGuildRole(data.guild_id);
GuildReadState.handleGuildUpdate(data.guild_id);
}
@@ -5,6 +5,7 @@ import type {GatewayHandlerContext} from '@app/features/gateway/events/EventRout
import GuildReadState from '@app/features/guild/state/GuildReadState';
import Guilds from '@app/features/guild/state/Guilds';
import GuildMembers from '@app/features/member/state/GuildMembers';
import MemberSidebar from '@app/features/member/state/MemberSidebar';
import Permission from '@app/features/permissions/state/Permission';
interface GuildRoleDeletePayload {
@@ -16,6 +17,7 @@ export function handleGuildRoleDelete(data: GuildRoleDeletePayload, _context: Ga
Guilds.handleGuildRoleDelete({guildId: data.guild_id, roleId: data.role_id});
GuildMembers.handleGuildRoleDelete(data.guild_id, data.role_id);
Channels.handleGuildRoleDelete({guildId: data.guild_id, roleId: data.role_id});
MemberSidebar.handleGuildStorageIdentityChange(data.guild_id);
Permission.handleGuildRole(data.guild_id);
GuildReadState.handleGuildUpdate(data.guild_id);
}
@@ -3,6 +3,7 @@
import type {GatewayHandlerContext} from '@app/features/gateway/events/EventRouter';
import GuildReadState from '@app/features/guild/state/GuildReadState';
import Guilds from '@app/features/guild/state/Guilds';
import MemberSidebar from '@app/features/member/state/MemberSidebar';
import Permission from '@app/features/permissions/state/Permission';
import type {GuildRole} from '@fluxer/schema/src/domains/guild/GuildRoleSchemas';
@@ -13,6 +14,7 @@ interface GuildRoleUpdatePayload {
export function handleGuildRoleUpdate(data: GuildRoleUpdatePayload, _context: GatewayHandlerContext): void {
Guilds.handleGuildRoleUpdate({guildId: data.guild_id, role: data.role});
MemberSidebar.handleGuildStorageIdentityChange(data.guild_id);
Permission.handleGuildRole(data.guild_id);
GuildReadState.handleGuildUpdate(data.guild_id);
}
@@ -3,6 +3,7 @@
import type {GatewayHandlerContext} from '@app/features/gateway/events/EventRouter';
import GuildReadState from '@app/features/guild/state/GuildReadState';
import Guilds from '@app/features/guild/state/Guilds';
import MemberSidebar from '@app/features/member/state/MemberSidebar';
import Permission from '@app/features/permissions/state/Permission';
import type {GuildRole} from '@fluxer/schema/src/domains/guild/GuildRoleSchemas';
@@ -14,6 +15,7 @@ interface GuildRoleUpdateBulkPayload {
export function handleGuildRoleUpdateBulk(data: GuildRoleUpdateBulkPayload, _context: GatewayHandlerContext): void {
if (data.roles.length > 0) {
Guilds.handleGuildRoleUpdateBulk({guildId: data.guild_id, roles: data.roles});
MemberSidebar.handleGuildStorageIdentityChange(data.guild_id);
}
Permission.handleGuildRole(data.guild_id);
GuildReadState.handleGuildUpdate(data.guild_id);
@@ -342,6 +342,50 @@ class MemberSidebar {
}
}
handleGuildStorageIdentityChange(guildId: string): void {
const subscribedChannels = this.listSubscribedChannelIds[guildId];
if (subscribedChannels == null) {
return;
}
const existingGuildLists = this.lists[guildId] ?? {};
const nextSubscribedChannels: Record<string, string> = {};
const changedStorageKeys = new Set<string>();
const rekeyedRequestedRanges = new Map<string, NormalizedMemberListRanges>();
for (const [previousStorageKey, channelId] of Object.entries(subscribedChannels)) {
const storageKey = this.resolveStorageKey(guildId, channelId);
nextSubscribedChannels[storageKey] = channelId;
if (storageKey === previousStorageKey) {
continue;
}
changedStorageKeys.add(previousStorageKey);
changedStorageKeys.add(storageKey);
rekeyedRequestedRanges.set(
storageKey,
existingGuildLists[previousStorageKey]?.requestedRanges ?? EMPTY_MEMBER_LIST_RANGES,
);
}
if (changedStorageKeys.size === 0) {
return;
}
for (const storageKey of changedStorageKeys) {
this.clearPendingListUpdateBatch(guildId, storageKey);
}
const guildLists: Record<string, MemberListState> = {...existingGuildLists};
for (const storageKey of changedStorageKeys) {
delete guildLists[storageKey];
}
for (const [storageKey, requestedRanges] of rekeyedRequestedRanges) {
guildLists[storageKey] = this.createEmptyListState(requestedRanges);
}
this.lists = {...this.lists, [guildId]: guildLists};
this.listSubscribedChannelIds = {...this.listSubscribedChannelIds, [guildId]: nextSubscribedChannels};
this.syncedMemberListGuildIds.delete(guildId);
if (this.sentMemberListGuildId === guildId) {
this.clearSentMemberListSubscription();
}
this.memberListSubscriptionGeneration += 1;
}
handleListUpdate(params: MemberListUpdateParams): void {
const {guildId} = params;
if (this.isMemberListUpdatesDisabled(guildId)) {