mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-09 14:43:03 -04:00
Merge remote-tracking branch 'upstream/dev'
This commit is contained in:
commit
314b042532
17 changed files with 403 additions and 91 deletions
5
src/plugins/automodContext/README.md
Normal file
5
src/plugins/automodContext/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# AutomodContext
|
||||||
|
|
||||||
|
Allows you to jump to the messages surrounding an automod hit
|
||||||
|
|
||||||
|

|
73
src/plugins/automodContext/index.tsx
Normal file
73
src/plugins/automodContext/index.tsx
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
import { findByPropsLazy } from "@webpack";
|
||||||
|
import { Button, ChannelStore, Text } from "@webpack/common";
|
||||||
|
|
||||||
|
const { selectChannel } = findByPropsLazy("selectChannel", "selectVoiceChannel");
|
||||||
|
|
||||||
|
function jumpToMessage(channelId: string, messageId: string) {
|
||||||
|
const guildId = ChannelStore.getChannel(channelId)?.guild_id;
|
||||||
|
|
||||||
|
selectChannel({
|
||||||
|
guildId,
|
||||||
|
channelId,
|
||||||
|
messageId,
|
||||||
|
jumpType: "INSTANT"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function findChannelId(message: any): string | null {
|
||||||
|
const { embeds: [embed] } = message;
|
||||||
|
const channelField = embed.fields.find(({ rawName }) => rawName === "channel_id");
|
||||||
|
|
||||||
|
if (!channelField) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return channelField.rawValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "AutomodContext",
|
||||||
|
description: "Allows you to jump to the messages surrounding an automod hit.",
|
||||||
|
authors: [Devs.JohnyTheCarrot],
|
||||||
|
|
||||||
|
patches: [
|
||||||
|
{
|
||||||
|
find: ".Messages.GUILD_AUTOMOD_REPORT_ISSUES",
|
||||||
|
replacement: {
|
||||||
|
match: /\.Messages\.ACTIONS.+?}\)(?=,(\(0.{0,40}\.dot.*?}\)),)/,
|
||||||
|
replace: (m, dot) => `${m},${dot},$self.renderJumpButton({message:arguments[0].message})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
renderJumpButton: ErrorBoundary.wrap(({ message }: { message: any; }) => {
|
||||||
|
const channelId = findChannelId(message);
|
||||||
|
|
||||||
|
if (!channelId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
style={{ padding: "2px 8px" }}
|
||||||
|
look={Button.Looks.LINK}
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
color={Button.Colors.LINK}
|
||||||
|
onClick={() => jumpToMessage(channelId, message.id)}
|
||||||
|
>
|
||||||
|
<Text color="text-link" variant="text-xs/normal">
|
||||||
|
Jump to Surrounding
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}, { noop: true })
|
||||||
|
});
|
|
@ -25,7 +25,7 @@ import { Logger } from "@utils/Logger";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findStoreLazy, proxyLazyWebpack } from "@webpack";
|
import { findByPropsLazy, findStoreLazy, proxyLazyWebpack } from "@webpack";
|
||||||
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
||||||
import type { CustomEmoji } from "@webpack/types";
|
import type { Emoji } from "@webpack/types";
|
||||||
import type { Message } from "discord-types/general";
|
import type { Message } from "discord-types/general";
|
||||||
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
import { applyPalette, GIFEncoder, quantize } from "gifenc";
|
||||||
import type { ReactElement, ReactNode } from "react";
|
import type { ReactElement, ReactNode } from "react";
|
||||||
|
@ -54,16 +54,22 @@ const ClientThemeSettingsActionsCreators = proxyLazyWebpack(() => searchProtoCla
|
||||||
|
|
||||||
|
|
||||||
const enum EmojiIntentions {
|
const enum EmojiIntentions {
|
||||||
REACTION = 0,
|
REACTION,
|
||||||
STATUS = 1,
|
STATUS,
|
||||||
COMMUNITY_CONTENT = 2,
|
COMMUNITY_CONTENT,
|
||||||
CHAT = 3,
|
CHAT,
|
||||||
GUILD_STICKER_RELATED_EMOJI = 4,
|
GUILD_STICKER_RELATED_EMOJI,
|
||||||
GUILD_ROLE_BENEFIT_EMOJI = 5,
|
GUILD_ROLE_BENEFIT_EMOJI,
|
||||||
COMMUNITY_CONTENT_ONLY = 6,
|
COMMUNITY_CONTENT_ONLY,
|
||||||
SOUNDBOARD = 7
|
SOUNDBOARD,
|
||||||
|
VOICE_CHANNEL_TOPIC,
|
||||||
|
GIFT,
|
||||||
|
AUTO_SUGGESTION,
|
||||||
|
POLLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IS_BYPASSEABLE_INTENTION = `[${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)`;
|
||||||
|
|
||||||
const enum StickerType {
|
const enum StickerType {
|
||||||
PNG = 1,
|
PNG = 1,
|
||||||
APNG = 2,
|
APNG = 2,
|
||||||
|
@ -198,37 +204,43 @@ export default definePlugin({
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: ".PREMIUM_LOCKED;",
|
find: ".PREMIUM_LOCKED;",
|
||||||
|
group: true,
|
||||||
predicate: () => settings.store.enableEmojiBypass,
|
predicate: () => settings.store.enableEmojiBypass,
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
// Create a variable for the intention of listing the emoji
|
// Create a variable for the intention of using the emoji
|
||||||
match: /(?<=,intention:(\i).+?;)/,
|
match: /(?<=\.USE_EXTERNAL_EMOJIS.+?;)(?<=intention:(\i).+?)/,
|
||||||
replace: (_, intention) => `let fakeNitroIntention=${intention};`
|
replace: (_, intention) => `const fakeNitroIntention=${intention};`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Send the intention of listing the emoji to the nitro permission check functions
|
// Disallow the emoji for external if the intention doesn't allow it
|
||||||
match: /\.(?:canUseEmojisEverywhere|canUseAnimatedEmojis)\(\i(?=\))/g,
|
match: /&&!\i&&!\i(?=\)return \i\.\i\.DISALLOW_EXTERNAL;)/,
|
||||||
replace: '$&,typeof fakeNitroIntention!=="undefined"?fakeNitroIntention:void 0'
|
replace: m => `${m}&&!${IS_BYPASSEABLE_INTENTION}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Disallow the emoji if the intention doesn't allow it
|
// Disallow the emoji for unavailable if the intention doesn't allow it
|
||||||
match: /(&&!\i&&)!(\i)(?=\)return \i\.\i\.DISALLOW_EXTERNAL;)/,
|
match: /!\i\.available(?=\)return \i\.\i\.GUILD_SUBSCRIPTION_UNAVAILABLE;)/,
|
||||||
replace: (_, rest, canUseExternal) => `${rest}(!${canUseExternal}&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)))`
|
replace: m => `${m}&&!${IS_BYPASSEABLE_INTENTION}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Make the emoji always available if the intention allows it
|
// Disallow the emoji for premium locked if the intention doesn't allow it
|
||||||
match: /if\(!\i\.available/,
|
match: /!\i\.\i\.canUseEmojisEverywhere\(\i\)/,
|
||||||
replace: m => `${m}&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention))`
|
replace: m => `(${m}&&!${IS_BYPASSEABLE_INTENTION})`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Allow animated emojis to be used if the intention allows it
|
||||||
|
match: /(?<=\|\|)\i\.\i\.canUseAnimatedEmojis\(\i\)/,
|
||||||
|
replace: m => `(${m}||${IS_BYPASSEABLE_INTENTION})`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// Allow emojis and animated emojis to be sent everywhere
|
// Allows the usage of subscription-locked emojis
|
||||||
{
|
{
|
||||||
find: "canUseAnimatedEmojis:function",
|
find: "isUnusableRoleSubscriptionEmoji:function",
|
||||||
predicate: () => settings.store.enableEmojiBypass,
|
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /((?:canUseEmojisEverywhere|canUseAnimatedEmojis):function\(\i)\){(.+?\))(?=})/g,
|
match: /isUnusableRoleSubscriptionEmoji:function/,
|
||||||
replace: (_, rest, premiumCheck) => `${rest},fakeNitroIntention){${premiumCheck}||fakeNitroIntention==null||[${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)`
|
// Replace the original export with a func that always returns false and alias the original
|
||||||
|
replace: "isUnusableRoleSubscriptionEmoji:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Allow stickers to be sent everywhere
|
// Allow stickers to be sent everywhere
|
||||||
|
@ -242,10 +254,10 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
// Make stickers always available
|
// Make stickers always available
|
||||||
{
|
{
|
||||||
find: "\"SENDABLE\"",
|
find: '"SENDABLE"',
|
||||||
predicate: () => settings.store.enableStickerBypass,
|
predicate: () => settings.store.enableStickerBypass,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(\w+)\.available\?/,
|
match: /\i\.available\?/,
|
||||||
replace: "true?"
|
replace: "true?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -408,15 +420,6 @@ export default definePlugin({
|
||||||
match: /canUseCustomNotificationSounds:function\(\i\){/,
|
match: /canUseCustomNotificationSounds:function\(\i\){/,
|
||||||
replace: "$&return true;"
|
replace: "$&return true;"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
// Allows the usage of subscription-locked emojis
|
|
||||||
{
|
|
||||||
find: "isUnusableRoleSubscriptionEmoji:function",
|
|
||||||
replacement: {
|
|
||||||
match: /isUnusableRoleSubscriptionEmoji:function/,
|
|
||||||
// replace the original export with a func that always returns false and alias the original
|
|
||||||
replace: "isUnusableRoleSubscriptionEmoji:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -812,8 +815,8 @@ export default definePlugin({
|
||||||
UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage);
|
UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage);
|
||||||
},
|
},
|
||||||
|
|
||||||
canUseEmote(e: CustomEmoji, channelId: string) {
|
canUseEmote(e: Emoji, channelId: string) {
|
||||||
if (e.require_colons === false) return true;
|
if (e.type === "UNICODE") return true;
|
||||||
if (e.available === false) return false;
|
if (e.available === false) return false;
|
||||||
|
|
||||||
const isUnusableRoleSubEmoji = RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji;
|
const isUnusableRoleSubEmoji = RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji;
|
||||||
|
|
|
@ -170,13 +170,14 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p:
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
p.start();
|
p.start();
|
||||||
p.started = true;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(`Failed to start ${name}\n`, e);
|
logger.error(`Failed to start ${name}\n`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.started = true;
|
||||||
|
|
||||||
if (commands?.length) {
|
if (commands?.length) {
|
||||||
logger.debug("Registering commands of plugin", name);
|
logger.debug("Registering commands of plugin", name);
|
||||||
for (const cmd of commands) {
|
for (const cmd of commands) {
|
||||||
|
@ -206,6 +207,7 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p:
|
||||||
|
|
||||||
export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plugin) {
|
export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plugin) {
|
||||||
const { name, commands, flux, contextMenus } = p;
|
const { name, commands, flux, contextMenus } = p;
|
||||||
|
|
||||||
if (p.stop) {
|
if (p.stop) {
|
||||||
logger.info("Stopping plugin", name);
|
logger.info("Stopping plugin", name);
|
||||||
if (!p.started) {
|
if (!p.started) {
|
||||||
|
@ -214,13 +216,14 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
p.stop();
|
p.stop();
|
||||||
p.started = false;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(`Failed to stop ${name}\n`, e);
|
logger.error(`Failed to stop ${name}\n`, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.started = false;
|
||||||
|
|
||||||
if (commands?.length) {
|
if (commands?.length) {
|
||||||
logger.debug("Unregistering commands of plugin", name);
|
logger.debug("Unregistering commands of plugin", name);
|
||||||
for (const cmd of commands) {
|
for (const cmd of commands) {
|
||||||
|
|
|
@ -22,9 +22,10 @@ interface Diff {
|
||||||
hours: number,
|
hours: number,
|
||||||
minutes: number,
|
minutes: number,
|
||||||
seconds: number;
|
seconds: number;
|
||||||
|
milliseconds: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DISCORD_KT_DELAY = 1471228.928;
|
const DISCORD_KT_DELAY = 1471228928;
|
||||||
const HiddenVisually = findExportedComponentLazy("HiddenVisually");
|
const HiddenVisually = findExportedComponentLazy("HiddenVisually");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
|
@ -42,6 +43,11 @@ export default definePlugin({
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
description: "Detect old Discord Android clients",
|
description: "Detect old Discord Android clients",
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
showMillis: {
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
description: "Show milliseconds",
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -55,12 +61,13 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
stringDelta(delta: number) {
|
stringDelta(delta: number, showMillis: boolean) {
|
||||||
const diff: Diff = {
|
const diff: Diff = {
|
||||||
days: Math.round(delta / (60 * 60 * 24)),
|
days: Math.round(delta / (60 * 60 * 24 * 1000)),
|
||||||
hours: Math.round((delta / (60 * 60)) % 24),
|
hours: Math.round((delta / (60 * 60 * 1000)) % 24),
|
||||||
minutes: Math.round((delta / (60)) % 60),
|
minutes: Math.round((delta / (60 * 1000)) % 60),
|
||||||
seconds: Math.round(delta % 60),
|
seconds: Math.round(delta / 1000 % 60),
|
||||||
|
milliseconds: Math.round(delta % 1000)
|
||||||
};
|
};
|
||||||
|
|
||||||
const str = (k: DiffKey) => diff[k] > 0 ? `${diff[k]} ${diff[k] > 1 ? k : k.substring(0, k.length - 1)}` : null;
|
const str = (k: DiffKey) => diff[k] > 0 ? `${diff[k]} ${diff[k] > 1 ? k : k.substring(0, k.length - 1)}` : null;
|
||||||
|
@ -72,7 +79,7 @@ export default definePlugin({
|
||||||
return prev + (
|
return prev + (
|
||||||
isNonNullish(s)
|
isNonNullish(s)
|
||||||
? (prev !== ""
|
? (prev !== ""
|
||||||
? k === "seconds"
|
? (showMillis ? k === "milliseconds" : k === "seconds")
|
||||||
? " and "
|
? " and "
|
||||||
: " "
|
: " "
|
||||||
: "") + s
|
: "") + s
|
||||||
|
@ -84,18 +91,21 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
latencyTooltipData(message: Message) {
|
latencyTooltipData(message: Message) {
|
||||||
const { latency, detectDiscordKotlin } = this.settings.store;
|
const { latency, detectDiscordKotlin, showMillis } = this.settings.store;
|
||||||
const { id, nonce } = message;
|
const { id, nonce } = message;
|
||||||
|
|
||||||
// Message wasn't received through gateway
|
// Message wasn't received through gateway
|
||||||
if (!isNonNullish(nonce)) return null;
|
if (!isNonNullish(nonce)) return null;
|
||||||
|
|
||||||
let isDiscordKotlin = false;
|
let isDiscordKotlin = false;
|
||||||
let delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000);
|
let delta = SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce); // milliseconds
|
||||||
|
if (!showMillis) {
|
||||||
|
delta = Math.round(delta / 1000) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
// Old Discord Android clients have a delay of around 17 days
|
// Old Discord Android clients have a delay of around 17 days
|
||||||
// This is a workaround for that
|
// This is a workaround for that
|
||||||
if (-delta >= DISCORD_KT_DELAY - 86400) { // One day of padding for good measure
|
if (-delta >= DISCORD_KT_DELAY - 86400000) { // One day of padding for good measure
|
||||||
isDiscordKotlin = detectDiscordKotlin;
|
isDiscordKotlin = detectDiscordKotlin;
|
||||||
delta += DISCORD_KT_DELAY;
|
delta += DISCORD_KT_DELAY;
|
||||||
}
|
}
|
||||||
|
@ -105,22 +115,23 @@ export default definePlugin({
|
||||||
// Can't do anything if the clock is behind
|
// Can't do anything if the clock is behind
|
||||||
const abs = Math.abs(delta);
|
const abs = Math.abs(delta);
|
||||||
const ahead = abs !== delta;
|
const ahead = abs !== delta;
|
||||||
|
const latencyMillis = latency * 1000;
|
||||||
|
|
||||||
const stringDelta = abs >= latency ? this.stringDelta(abs) : null;
|
const stringDelta = abs >= latencyMillis ? this.stringDelta(abs, showMillis) : null;
|
||||||
|
|
||||||
// Also thanks dziurwa
|
// Also thanks dziurwa
|
||||||
// 2 minutes
|
// 2 minutes
|
||||||
const TROLL_LIMIT = 2 * 60;
|
const TROLL_LIMIT = 2 * 60 * 1000;
|
||||||
|
|
||||||
const fill: Fill = isDiscordKotlin
|
const fill: Fill = isDiscordKotlin
|
||||||
? ["status-positive", "status-positive", "text-muted"]
|
? ["status-positive", "status-positive", "text-muted"]
|
||||||
: delta >= TROLL_LIMIT || ahead
|
: delta >= TROLL_LIMIT || ahead
|
||||||
? ["text-muted", "text-muted", "text-muted"]
|
? ["text-muted", "text-muted", "text-muted"]
|
||||||
: delta >= (latency * 2)
|
: delta >= (latencyMillis * 2)
|
||||||
? ["status-danger", "text-muted", "text-muted"]
|
? ["status-danger", "text-muted", "text-muted"]
|
||||||
: ["status-warning", "status-warning", "text-muted"];
|
: ["status-warning", "status-warning", "text-muted"];
|
||||||
|
|
||||||
return (abs >= latency || isDiscordKotlin) ? { delta: stringDelta, ahead, fill, isDiscordKotlin } : null;
|
return (abs >= latencyMillis || isDiscordKotlin) ? { delta: stringDelta, ahead, fill, isDiscordKotlin } : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
Tooltip() {
|
Tooltip() {
|
||||||
|
|
5
src/plugins/noDefaultHangStatus/README.md
Normal file
5
src/plugins/noDefaultHangStatus/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# NoDefaultHangStatus
|
||||||
|
|
||||||
|
Disable the default hang status when joining voice channels
|
||||||
|
|
||||||
|

|
24
src/plugins/noDefaultHangStatus/index.ts
Normal file
24
src/plugins/noDefaultHangStatus/index.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "NoDefaultHangStatus",
|
||||||
|
description: "Disable the default hang status when joining voice channels",
|
||||||
|
authors: [Devs.D3SOX],
|
||||||
|
|
||||||
|
patches: [
|
||||||
|
{
|
||||||
|
find: "HangStatusTypes.CHILLING)",
|
||||||
|
replacement: {
|
||||||
|
match: /{enableHangStatus:(\i),/,
|
||||||
|
replace: "{_enableHangStatus:$1=false,"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings, migratePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { FluxDispatcher } from "@webpack/common";
|
import { FluxDispatcher } from "@webpack/common";
|
||||||
|
@ -41,8 +41,9 @@ const settings = definePluginSettings({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migratePluginSettings("PartyMode", "Party mode 🎉");
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "Party mode 🎉",
|
name: "PartyMode",
|
||||||
description: "Allows you to use party mode cause the party never ends ✨",
|
description: "Allows you to use party mode cause the party never ends ✨",
|
||||||
authors: [Devs.UwUDev],
|
authors: [Devs.UwUDev],
|
||||||
settings,
|
settings,
|
||||||
|
|
|
@ -22,14 +22,34 @@ import { addServerListElement, removeServerListElement, ServerListRenderPosition
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs, EquicordDevs } from "@utils/constants";
|
import { Devs, EquicordDevs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
|
import { findStoreLazy } from "@webpack";
|
||||||
import { Button, FluxDispatcher, GuildChannelStore, GuildStore, React, ReadStateStore } from "@webpack/common";
|
import { Button, FluxDispatcher, GuildChannelStore, GuildStore, React, ReadStateStore } from "@webpack/common";
|
||||||
|
import { Channel } from "discord-types/general";
|
||||||
|
|
||||||
|
interface ThreadJoined {
|
||||||
|
channel: Channel;
|
||||||
|
joinTimestamp: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThreadsJoined = Record<string, ThreadJoined>;
|
||||||
|
type ThreadsJoinedByParent = Record<string, ThreadsJoined>;
|
||||||
|
|
||||||
|
interface ActiveJoinedThreadsStore {
|
||||||
|
getActiveJoinedThreadsForGuild(guildId: string): ThreadsJoinedByParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ActiveJoinedThreadsStore: ActiveJoinedThreadsStore = findStoreLazy("ActiveJoinedThreadsStore");
|
||||||
|
|
||||||
function onClick() {
|
function onClick() {
|
||||||
const channels: Array<any> = [];
|
const channels: Array<any> = [];
|
||||||
|
|
||||||
Object.values(GuildStore.getGuilds()).forEach(guild => {
|
Object.values(GuildStore.getGuilds()).forEach(guild => {
|
||||||
GuildChannelStore.getChannels(guild.id).SELECTABLE
|
GuildChannelStore.getChannels(guild.id).SELECTABLE // Array<{ channel, comparator }>
|
||||||
.concat(GuildChannelStore.getChannels(guild.id).VOCAL)
|
.concat(GuildChannelStore.getChannels(guild.id).VOCAL) // Array<{ channel, comparator }>
|
||||||
|
.concat(
|
||||||
|
Object.values(ActiveJoinedThreadsStore.getActiveJoinedThreadsForGuild(guild.id))
|
||||||
|
.flatMap(threadChannels => Object.values(threadChannels))
|
||||||
|
)
|
||||||
.forEach((c: { channel: { id: string; }; }) => {
|
.forEach((c: { channel: { id: string; }; }) => {
|
||||||
if (!ReadStateStore.hasUnread(c.channel.id)) return;
|
if (!ReadStateStore.hasUnread(c.channel.id)) return;
|
||||||
|
|
||||||
|
|
5
src/plugins/replaceGoogleSearch/README.md
Normal file
5
src/plugins/replaceGoogleSearch/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# ReplaceGoogleSearch
|
||||||
|
|
||||||
|
Replaces the Google search with different Engines
|
||||||
|
|
||||||
|

|
107
src/plugins/replaceGoogleSearch/index.tsx
Normal file
107
src/plugins/replaceGoogleSearch/index.tsx
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||||
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
import { Flex, Menu } from "@webpack/common";
|
||||||
|
|
||||||
|
const DefaultEngines = {
|
||||||
|
Google: "https://www.google.com/search?q=",
|
||||||
|
DuckDuckGo: "https://duckduckgo.com/",
|
||||||
|
Bing: "https://www.bing.com/search?q=",
|
||||||
|
Yahoo: "https://search.yahoo.com/search?p=",
|
||||||
|
Github: "https://github.com/search?q=",
|
||||||
|
Kagi: "https://kagi.com/search?q=",
|
||||||
|
Yandex: "https://yandex.com/search/?text=",
|
||||||
|
AOL: "https://search.aol.com/aol/search?q=",
|
||||||
|
Baidu: "https://www.baidu.com/s?wd=",
|
||||||
|
Wikipedia: "https://wikipedia.org/w/index.php?search=",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const settings = definePluginSettings({
|
||||||
|
customEngineName: {
|
||||||
|
description: "Name of the custom search engine",
|
||||||
|
type: OptionType.STRING,
|
||||||
|
placeholder: "Google"
|
||||||
|
},
|
||||||
|
customEngineURL: {
|
||||||
|
description: "The URL of your Engine",
|
||||||
|
type: OptionType.STRING,
|
||||||
|
placeholder: "https://google.com/search?q="
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function search(src: string, engine: string) {
|
||||||
|
open(engine + encodeURIComponent(src), "_blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeSearchItem(src: string) {
|
||||||
|
let Engines = {};
|
||||||
|
|
||||||
|
if (settings.store.customEngineName && settings.store.customEngineURL) {
|
||||||
|
Engines[settings.store.customEngineName] = settings.store.customEngineURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Engines = { ...Engines, ...DefaultEngines };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu.MenuItem
|
||||||
|
label="Search Text"
|
||||||
|
key="search-text"
|
||||||
|
id="vc-search-text"
|
||||||
|
>
|
||||||
|
{Object.keys(Engines).map((engine, i) => {
|
||||||
|
const key = "vc-search-content-" + engine;
|
||||||
|
return (
|
||||||
|
<Menu.MenuItem
|
||||||
|
key={key}
|
||||||
|
id={key}
|
||||||
|
label={
|
||||||
|
<Flex style={{ alignItems: "center", gap: "0.5em" }}>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
borderRadius: "50%"
|
||||||
|
}}
|
||||||
|
aria-hidden="true"
|
||||||
|
height={16}
|
||||||
|
width={16}
|
||||||
|
src={`https://www.google.com/s2/favicons?domain=${Engines[engine]}`}
|
||||||
|
/>
|
||||||
|
{engine}
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
action={() => search(src, Engines[engine])}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Menu.MenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageContextMenuPatch: NavContextMenuPatchCallback = (children, _props) => {
|
||||||
|
const selection = document.getSelection()?.toString();
|
||||||
|
if (!selection) return;
|
||||||
|
|
||||||
|
const group = findGroupChildrenByChildId("search-google", children);
|
||||||
|
if (group) {
|
||||||
|
const idx = group.findIndex(c => c?.props?.id === "search-google");
|
||||||
|
if (idx !== -1) group[idx] = makeSearchItem(selection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "ReplaceGoogleSearch",
|
||||||
|
description: "Replaces the Google search with different Engines",
|
||||||
|
authors: [Devs.Moxxie, Devs.Ethan],
|
||||||
|
|
||||||
|
settings,
|
||||||
|
|
||||||
|
contextMenus: {
|
||||||
|
"message": messageContextMenuPatch
|
||||||
|
}
|
||||||
|
});
|
|
@ -9,11 +9,11 @@ import "./styles.css";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { Margins } from "@utils/margins";
|
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findComponentLazy } from "@webpack";
|
import { findComponentLazy } from "@webpack";
|
||||||
import { ChannelStore, Forms, GuildMemberStore, i18n, Text, Tooltip } from "@webpack/common";
|
import { ChannelStore, GuildMemberStore, i18n, Text, Tooltip } from "@webpack/common";
|
||||||
import { Message } from "discord-types/general";
|
import { Message } from "discord-types/general";
|
||||||
|
import { FunctionComponent, ReactNode } from "react";
|
||||||
|
|
||||||
const CountDown = findComponentLazy(m => m.prototype?.render?.toString().includes(".MAX_AGE_NEVER"));
|
const CountDown = findComponentLazy(m => m.prototype?.render?.toString().includes(".MAX_AGE_NEVER"));
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ const settings = definePluginSettings({
|
||||||
displayStyle: {
|
displayStyle: {
|
||||||
description: "How to display the timeout duration",
|
description: "How to display the timeout duration",
|
||||||
type: OptionType.SELECT,
|
type: OptionType.SELECT,
|
||||||
restartNeeded: true,
|
|
||||||
options: [
|
options: [
|
||||||
{ label: "In the Tooltip", value: DisplayStyle.Tooltip },
|
{ label: "In the Tooltip", value: DisplayStyle.Tooltip },
|
||||||
{ label: "Next to the timeout icon", value: DisplayStyle.Inline, default: true },
|
{ label: "Next to the timeout icon", value: DisplayStyle.Inline, default: true },
|
||||||
|
@ -60,7 +59,7 @@ function renderTimeout(message: Message, inline: boolean) {
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "ShowTimeoutDuration",
|
name: "ShowTimeoutDuration",
|
||||||
description: "Shows how much longer a user's timeout will last, either in the timeout icon tooltip or next to it",
|
description: "Shows how much longer a user's timeout will last, either in the timeout icon tooltip or next to it",
|
||||||
authors: [Devs.Ven],
|
authors: [Devs.Ven, Devs.Sqaaakoi],
|
||||||
|
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
|
@ -70,33 +69,20 @@ export default definePlugin({
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
match: /(\i)\.Tooltip,{(text:.{0,30}\.Messages\.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY)/,
|
match: /(\i)\.Tooltip,{(text:.{0,30}\.Messages\.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY)/,
|
||||||
get replace() {
|
replace: "$self.TooltipWrapper,{message:arguments[0].message,$2"
|
||||||
if (settings.store.displayStyle === DisplayStyle.Inline)
|
|
||||||
return "$self.TooltipWrapper,{vcProps:arguments[0],$2";
|
|
||||||
|
|
||||||
return "$1.Tooltip,{text:$self.renderTimeoutDuration(arguments[0])";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
renderTimeoutDuration: ErrorBoundary.wrap(({ message }: { message: Message; }) => {
|
TooltipWrapper: ErrorBoundary.wrap(({ message, children, text }: { message: Message; children: FunctionComponent<any>; text: ReactNode; }) => {
|
||||||
return (
|
if (settings.store.displayStyle === DisplayStyle.Tooltip) return <Tooltip
|
||||||
<>
|
children={children}
|
||||||
<Forms.FormText>{i18n.Messages.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY}</Forms.FormText>
|
text={renderTimeout(message, false)}
|
||||||
<Forms.FormText className={Margins.top8}>
|
/>;
|
||||||
{renderTimeout(message, false)}
|
|
||||||
</Forms.FormText>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}, { noop: true }),
|
|
||||||
|
|
||||||
TooltipWrapper: ErrorBoundary.wrap(({ vcProps: { message }, ...tooltipProps }: { vcProps: { message: Message; }; }) => {
|
|
||||||
return (
|
return (
|
||||||
<div className="vc-std-wrapper">
|
<div className="vc-std-wrapper">
|
||||||
<Tooltip {...tooltipProps as any} />
|
<Tooltip text={text} children={children} />
|
||||||
|
|
||||||
<Text variant="text-md/normal" color="status-danger">
|
<Text variant="text-md/normal" color="status-danger">
|
||||||
{renderTimeout(message, true)} timeout remaining
|
{renderTimeout(message, true)} timeout remaining
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -2,3 +2,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vc-std-wrapper [class*="communicationDisabled"] {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,10 @@ interface GuildContextProps {
|
||||||
guild?: Guild;
|
guild?: Guild;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GroupDMContextProps {
|
||||||
|
channel: Channel;
|
||||||
|
}
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
format: {
|
format: {
|
||||||
type: OptionType.SELECT,
|
type: OptionType.SELECT,
|
||||||
|
@ -145,10 +149,27 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild }: GuildCon
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const GroupDMContext: NavContextMenuPatchCallback = (children, { channel }: GroupDMContextProps) => {
|
||||||
|
if (!channel) return;
|
||||||
|
|
||||||
|
children.splice(-1, 0, (
|
||||||
|
<Menu.MenuGroup>
|
||||||
|
<Menu.MenuItem
|
||||||
|
id="view-group-channel-icon"
|
||||||
|
label="View Icon"
|
||||||
|
action={() =>
|
||||||
|
openImage(IconUtils.getChannelIconURL(channel)!)
|
||||||
|
}
|
||||||
|
icon={ImageIcon}
|
||||||
|
/>
|
||||||
|
</Menu.MenuGroup>
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "ViewIcons",
|
name: "ViewIcons",
|
||||||
authors: [Devs.Ven, Devs.TheKodeToad, Devs.Nuckyz],
|
authors: [Devs.Ven, Devs.TheKodeToad, Devs.Nuckyz, Devs.nyx],
|
||||||
description: "Makes avatars and banners in user profiles clickable, and adds View Icon/Banner entries in the user and server context menu",
|
description: "Makes avatars and banners in user profiles clickable, adds View Icon/Banner entries in the user, server and group channel context menu.",
|
||||||
tags: ["ImageUtilities"],
|
tags: ["ImageUtilities"],
|
||||||
|
|
||||||
settings,
|
settings,
|
||||||
|
@ -157,11 +178,12 @@ export default definePlugin({
|
||||||
|
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
"user-context": UserContext,
|
"user-context": UserContext,
|
||||||
"guild-context": GuildContext
|
"guild-context": GuildContext,
|
||||||
|
"gdm-context": GroupDMContext
|
||||||
},
|
},
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
// Make pfps clickable
|
// Profiles Modal pfp
|
||||||
{
|
{
|
||||||
find: "User Profile Modal - Context Menu",
|
find: "User Profile Modal - Context Menu",
|
||||||
replacement: {
|
replacement: {
|
||||||
|
@ -169,7 +191,7 @@ export default definePlugin({
|
||||||
replace: "{src:$1,onClick:()=>$self.openImage($1)"
|
replace: "{src:$1,onClick:()=>$self.openImage($1)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Make banners clickable
|
// Banners
|
||||||
{
|
{
|
||||||
find: ".NITRO_BANNER,",
|
find: ".NITRO_BANNER,",
|
||||||
replacement: {
|
replacement: {
|
||||||
|
@ -180,12 +202,38 @@ export default definePlugin({
|
||||||
'onClick:ev=>$1&&ev.target.style.backgroundImage&&$self.openImage($2),style:{cursor:$1?"pointer":void 0,'
|
'onClick:ev=>$1&&ev.target.style.backgroundImage&&$self.openImage($2),style:{cursor:$1?"pointer":void 0,'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// User DMs "User Profile" popup in the right
|
||||||
{
|
{
|
||||||
find: ".avatarPositionPanel",
|
find: ".avatarPositionPanel",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?<=avatarWrapperNonUserBot.{0,50})onClick:(\i\|\|\i)\?void 0(?<=,avatarSrc:(\i).+?)/,
|
match: /(?<=avatarWrapperNonUserBot.{0,50})onClick:(\i\|\|\i)\?void 0(?<=,avatarSrc:(\i).+?)/,
|
||||||
replace: "style:($1)?{cursor:\"pointer\"}:{},onClick:$1?()=>{$self.openImage($2)}"
|
replace: "style:($1)?{cursor:\"pointer\"}:{},onClick:$1?()=>{$self.openImage($2)}"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// Group DMs top small & large icon
|
||||||
|
{
|
||||||
|
find: ".recipients.length>=2",
|
||||||
|
all: true,
|
||||||
|
replacement: {
|
||||||
|
match: /null==\i\.icon\?.+?src:(\(0,\i\.getChannelIconURL\).+?\))(?=[,}])/,
|
||||||
|
replace: (m, iconUrl) => `${m},onClick:()=>$self.openImage(${iconUrl})`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// User DMs top small icon
|
||||||
|
{
|
||||||
|
find: ".cursorPointer:null,children",
|
||||||
|
replacement: {
|
||||||
|
match: /.Avatar,.+?src:(.+?\))(?=[,}])/,
|
||||||
|
replace: (m, avatarUrl) => `${m},onClick:()=>$self.openImage(${avatarUrl})`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// User Dms top large icon
|
||||||
|
{
|
||||||
|
find: 'experimentLocation:"empty_messages"',
|
||||||
|
replacement: {
|
||||||
|
match: /.Avatar,.+?src:(.+?\))(?=[,}])/,
|
||||||
|
replace: (m, avatarUrl) => `${m},onClick:()=>$self.openImage(${avatarUrl})`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
|
@ -444,6 +444,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
||||||
name: "newwares",
|
name: "newwares",
|
||||||
id: 421405303951851520n
|
id: 421405303951851520n
|
||||||
},
|
},
|
||||||
|
JohnyTheCarrot: {
|
||||||
|
name: "JohnyTheCarrot",
|
||||||
|
id: 132819036282159104n
|
||||||
|
},
|
||||||
puv: {
|
puv: {
|
||||||
name: "puv",
|
name: "puv",
|
||||||
id: 469441552251355137n
|
id: 469441552251355137n
|
||||||
|
@ -492,6 +496,18 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
||||||
name: "ScattrdBlade",
|
name: "ScattrdBlade",
|
||||||
id: 678007540608532491n
|
id: 678007540608532491n
|
||||||
},
|
},
|
||||||
|
Moxxie: {
|
||||||
|
name: "Moxxie",
|
||||||
|
id: 712653921692155965n,
|
||||||
|
},
|
||||||
|
Ethan: {
|
||||||
|
name: "Ethan",
|
||||||
|
id: 721717126523781240n,
|
||||||
|
},
|
||||||
|
nyx: {
|
||||||
|
name: "verticalsync",
|
||||||
|
id: 328165170536775680n
|
||||||
|
},
|
||||||
} satisfies Record<string, Dev>);
|
} satisfies Record<string, Dev>);
|
||||||
|
|
||||||
export const EquicordDevs = Object.freeze({
|
export const EquicordDevs = Object.freeze({
|
||||||
|
|
3
src/webpack/common/types/stores.d.ts
vendored
3
src/webpack/common/types/stores.d.ts
vendored
|
@ -63,7 +63,7 @@ export interface CustomEmoji {
|
||||||
originalName?: string;
|
originalName?: string;
|
||||||
require_colons: boolean;
|
require_colons: boolean;
|
||||||
roles: string[];
|
roles: string[];
|
||||||
url: string;
|
type: "GUILD_EMOJI";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UnicodeEmoji {
|
export interface UnicodeEmoji {
|
||||||
|
@ -75,6 +75,7 @@ export interface UnicodeEmoji {
|
||||||
};
|
};
|
||||||
index: number;
|
index: number;
|
||||||
surrogates: string;
|
surrogates: string;
|
||||||
|
type: "UNICODE";
|
||||||
uniqueName: string;
|
uniqueName: string;
|
||||||
useSpriteSheet: boolean;
|
useSpriteSheet: boolean;
|
||||||
get allNamesString(): string;
|
get allNamesString(): string;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { proxyLazy } from "@utils/lazy";
|
import { makeLazy, proxyLazy } from "@utils/lazy";
|
||||||
import { LazyComponent } from "@utils/lazyReact";
|
import { LazyComponent } from "@utils/lazyReact";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { canonicalizeMatch } from "@utils/patches";
|
import { canonicalizeMatch } from "@utils/patches";
|
||||||
|
@ -462,7 +462,7 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = Def
|
||||||
export function extractAndLoadChunksLazy(code: string[], matcher: RegExp = DefaultExtractAndLoadChunksRegex) {
|
export function extractAndLoadChunksLazy(code: string[], matcher: RegExp = DefaultExtractAndLoadChunksRegex) {
|
||||||
if (IS_DEV) lazyWebpackSearchHistory.push(["extractAndLoadChunks", [code, matcher]]);
|
if (IS_DEV) lazyWebpackSearchHistory.push(["extractAndLoadChunks", [code, matcher]]);
|
||||||
|
|
||||||
return () => extractAndLoadChunks(code, matcher);
|
return makeLazy(() => extractAndLoadChunks(code, matcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue