From 09b0382c458ed0f3df5b8fa778c504b3e658ac49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aura=20Rom=C3=A1n?= Date: Sun, 9 Jul 2023 22:57:33 +0200 Subject: [PATCH] perf(Channel): linear speed position getter (#9497) * perf(Channel): linear speed position getter * fix: add another set of parens * perf: lower memory and CPU usage * refactor: add shared private utility for group types * perf: improve readability and performance Co-authored-by: Vlad Frangu * feat: add support for voice sortables --------- Co-authored-by: Vlad Frangu Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- packages/discord.js/src/structures/Guild.js | 12 +++----- .../discord.js/src/structures/GuildChannel.js | 21 +++++++++++-- packages/discord.js/src/util/Util.js | 30 +++++++++++++++++++ 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/packages/discord.js/src/structures/Guild.js b/packages/discord.js/src/structures/Guild.js index 489ca93393f7..f07e9b4e1e86 100644 --- a/packages/discord.js/src/structures/Guild.js +++ b/packages/discord.js/src/structures/Guild.js @@ -28,7 +28,7 @@ const VoiceStateManager = require('../managers/VoiceStateManager'); const DataResolver = require('../util/DataResolver'); const Status = require('../util/Status'); const SystemChannelFlagsBitField = require('../util/SystemChannelFlagsBitField'); -const { discordSort } = require('../util/Util'); +const { discordSort, getSortableGroupTypes } = require('../util/Util'); /** * Represents a guild (or a server) on Discord. @@ -1351,14 +1351,10 @@ class Guild extends AnonymousGuild { * @private */ _sortedChannels(channel) { - const category = channel.type === ChannelType.GuildCategory; - const channelTypes = [ChannelType.GuildText, ChannelType.GuildAnnouncement]; + const channelIsCategory = channel.type === ChannelType.GuildCategory; + const types = getSortableGroupTypes(channel.type); return discordSort( - this.channels.cache.filter( - c => - (channelTypes.includes(channel.type) ? channelTypes.includes(c.type) : c.type === channel.type) && - (category || c.parent === channel.parent), - ), + this.channels.cache.filter(c => types.includes(c.type) && (channelIsCategory || c.parentId === channel.parentId)), ); } } diff --git a/packages/discord.js/src/structures/GuildChannel.js b/packages/discord.js/src/structures/GuildChannel.js index 6de224a3f0f2..c066c71d6d37 100644 --- a/packages/discord.js/src/structures/GuildChannel.js +++ b/packages/discord.js/src/structures/GuildChannel.js @@ -1,11 +1,13 @@ 'use strict'; -const { PermissionFlagsBits } = require('discord-api-types/v10'); +const { Snowflake } = require('@sapphire/snowflake'); +const { PermissionFlagsBits, ChannelType } = require('discord-api-types/v10'); const { BaseChannel } = require('./BaseChannel'); const { DiscordjsError, ErrorCodes } = require('../errors'); const PermissionOverwriteManager = require('../managers/PermissionOverwriteManager'); const { VoiceBasedChannelTypes } = require('../util/Constants'); const PermissionsBitField = require('../util/PermissionsBitField'); +const { getSortableGroupTypes } = require('../util/Util'); /** * Represents a guild channel from any of the following: @@ -145,8 +147,21 @@ class GuildChannel extends BaseChannel { * @readonly */ get position() { - const sorted = this.guild._sortedChannels(this); - return [...sorted.values()].indexOf(sorted.get(this.id)); + const selfIsCategory = this.type === ChannelType.GuildCategory; + const types = getSortableGroupTypes(this.type); + + let count = 0; + for (const channel of this.guild.channels.cache.values()) { + if (!types.includes(channel.type)) continue; + if (!selfIsCategory && channel.parentId !== this.parentId) continue; + if (this.rawPosition === channel.rawPosition) { + if (Snowflake.compare(channel.id, this.id) === -1) count++; + } else if (this.rawPosition > channel.rawPosition) { + count++; + } + } + + return count; } /** diff --git a/packages/discord.js/src/util/Util.js b/packages/discord.js/src/util/Util.js index 220b8a3b38da..e42bc5a11a6c 100644 --- a/packages/discord.js/src/util/Util.js +++ b/packages/discord.js/src/util/Util.js @@ -163,6 +163,35 @@ function makePlainError(err) { }; } +const TextSortableGroupTypes = [ChannelType.GuildText, ChannelType.GuildAnnouncement, ChannelType.GuildForum]; +const VoiceSortableGroupTypes = [ChannelType.GuildVoice, ChannelType.GuildStageVoice]; +const CategorySortableGroupTypes = [ChannelType.GuildCategory]; + +/** + * Gets an array of the channel types that can be moved in the channel group. For example, a GuildText channel would + * return an array containing the types that can be ordered within the text channels (always at the top), and a voice + * channel would return an array containing the types that can be ordered within the voice channels (always at the + * bottom). + * @param {ChannelType} type The type of the channel + * @returns {ChannelType[]} + * @private + */ +function getSortableGroupTypes(type) { + switch (type) { + case ChannelType.GuildText: + case ChannelType.GuildAnnouncement: + case ChannelType.GuildForum: + return TextSortableGroupTypes; + case ChannelType.GuildVoice: + case ChannelType.GuildStageVoice: + return VoiceSortableGroupTypes; + case ChannelType.GuildCategory: + return CategorySortableGroupTypes; + default: + return [type]; + } +} + /** * Moves an element in an array *in place*. * @param {Array<*>} array Array to modify @@ -379,6 +408,7 @@ module.exports = { mergeDefault, makeError, makePlainError, + getSortableGroupTypes, moveElementInArray, verifyString, resolveColor,