Skip to content

Commit

Permalink
perf(Channel): linear speed position getter (#9497)
Browse files Browse the repository at this point in the history
* 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 <kingdgrizzle@gmail.com>

* feat: add support for voice sortables

---------

Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 9, 2023
1 parent 719e54a commit 09b0382
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 11 deletions.
12 changes: 4 additions & 8 deletions packages/discord.js/src/structures/Guild.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)),
);
}
}
Expand Down
21 changes: 18 additions & 3 deletions packages/discord.js/src/structures/GuildChannel.js
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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;
}

/**
Expand Down
30 changes: 30 additions & 0 deletions packages/discord.js/src/util/Util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -379,6 +408,7 @@ module.exports = {
mergeDefault,
makeError,
makePlainError,
getSortableGroupTypes,
moveElementInArray,
verifyString,
resolveColor,
Expand Down

0 comments on commit 09b0382

Please sign in to comment.