fix: channel ordering

This commit is contained in:
Hampus Kraft
2026-02-20 22:36:48 +00:00
parent fcc8463cd8
commit e11f9bc52e
10 changed files with 438 additions and 19 deletions

View File

@@ -234,6 +234,9 @@ export const ChannelPositionUpdateRequest = z.array(
id: SnowflakeType.describe('The ID of the channel to reposition'),
position: z.number().int().nonnegative().optional().describe('New position for the channel'),
parent_id: SnowflakeType.nullish().describe('New parent category ID'),
preceding_sibling_id: SnowflakeType.nullish().describe(
'ID of the sibling channel that should directly precede this channel after reordering',
),
lock_permissions: z.boolean().optional().describe('Whether to sync permissions with the new parent'),
}),
);

View File

@@ -67,7 +67,52 @@ export function compareChannelOrdering<Id extends string | bigint>(
export function sortChannelsForOrdering<Id extends string | bigint, Channel extends ChannelOrderingChannel<Id>>(
channels: ReadonlyArray<Channel>,
): Array<Channel> {
return [...channels].sort(compareChannelOrdering);
const channelById = new Map<Id, Channel>(channels.map((channel) => [channel.id, channel]));
const childrenByParent = new Map<Id, Array<Channel>>();
const rootChannels: Array<Channel> = [];
for (const channel of channels) {
const parentId = channel.parentId ?? null;
if (parentId === null || !channelById.has(parentId)) {
rootChannels.push(channel);
continue;
}
const existingChildren = childrenByParent.get(parentId);
if (existingChildren) {
existingChildren.push(channel);
} else {
childrenByParent.set(parentId, [channel]);
}
}
const orderedChannels: Array<Channel> = [];
const seen = new Set<Id>();
const sortedRoots = [...rootChannels].sort(compareChannelOrdering);
for (const root of sortedRoots) {
orderedChannels.push(root);
seen.add(root.id);
if (root.type !== ChannelTypes.GUILD_CATEGORY) {
continue;
}
const children = childrenByParent.get(root.id);
if (!children) {
continue;
}
for (const child of [...children].sort(compareChannelOrdering)) {
orderedChannels.push(child);
seen.add(child.id);
}
}
const remaining = channels.filter((channel) => !seen.has(channel.id)).sort(compareChannelOrdering);
orderedChannels.push(...remaining);
return orderedChannels;
}
export function computeChannelMoveBlockIds<Id extends string | bigint, Channel extends ChannelOrderingChannel<Id>>({