mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-01-10 01:46:23 +00:00
Merge branch 'dev' into feat/vcnarrator-ignoreself
This commit is contained in:
commit
e6a8601178
15 changed files with 156 additions and 59 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "vencord",
|
"name": "vencord",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"version": "1.6.9",
|
"version": "1.7.0",
|
||||||
"description": "The cutest Discord client mod",
|
"description": "The cutest Discord client mod",
|
||||||
"homepage": "https://github.com/Vendicated/Vencord#readme",
|
"homepage": "https://github.com/Vendicated/Vencord#readme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
|
@ -74,7 +74,7 @@ export interface MessageExtra {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SendListener = (channelId: string, messageObj: MessageObject, extra: MessageExtra) => Promisable<void | { cancel: boolean; }>;
|
export type SendListener = (channelId: string, messageObj: MessageObject, extra: MessageExtra) => Promisable<void | { cancel: boolean; }>;
|
||||||
export type EditListener = (channelId: string, messageId: string, messageObj: MessageObject) => Promisable<void>;
|
export type EditListener = (channelId: string, messageId: string, messageObj: MessageObject) => Promisable<void | { cancel: boolean; }>;
|
||||||
|
|
||||||
const sendListeners = new Set<SendListener>();
|
const sendListeners = new Set<SendListener>();
|
||||||
const editListeners = new Set<EditListener>();
|
const editListeners = new Set<EditListener>();
|
||||||
|
@ -84,7 +84,7 @@ export async function _handlePreSend(channelId: string, messageObj: MessageObjec
|
||||||
for (const listener of sendListeners) {
|
for (const listener of sendListeners) {
|
||||||
try {
|
try {
|
||||||
const result = await listener(channelId, messageObj, extra);
|
const result = await listener(channelId, messageObj, extra);
|
||||||
if (result && result.cancel === true) {
|
if (result?.cancel) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -97,11 +97,15 @@ export async function _handlePreSend(channelId: string, messageObj: MessageObjec
|
||||||
export async function _handlePreEdit(channelId: string, messageId: string, messageObj: MessageObject) {
|
export async function _handlePreEdit(channelId: string, messageId: string, messageObj: MessageObject) {
|
||||||
for (const listener of editListeners) {
|
for (const listener of editListeners) {
|
||||||
try {
|
try {
|
||||||
await listener(channelId, messageId, messageObj);
|
const result = await listener(channelId, messageId, messageObj);
|
||||||
|
if (result?.cancel) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
MessageEventsLogger.error("MessageEditHandler: Listener encountered an unknown error\n", e);
|
MessageEventsLogger.error("MessageEditHandler: Listener encountered an unknown error\n", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,10 +25,13 @@ export default definePlugin({
|
||||||
authors: [Devs.Arjix, Devs.hunt, Devs.Ven],
|
authors: [Devs.Arjix, Devs.hunt, Devs.Ven],
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: '"MessageActionCreators"',
|
find: ".Messages.EDIT_TEXTAREA_HELP",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /async editMessage\(.+?\)\{/,
|
match: /(?<=,channel:\i\}\)\.then\().+?(?=return \i\.content!==this\.props\.message\.content&&\i\((.+?)\))/,
|
||||||
replace: "$&await Vencord.Api.MessageEvents._handlePreEdit(...arguments);"
|
replace: (match, args) => "" +
|
||||||
|
`async ${match}` +
|
||||||
|
`if(await Vencord.Api.MessageEvents._handlePreEdit(${args}))` +
|
||||||
|
"return Promise.resolve({shoudClear:true,shouldRefocus:true});"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -72,7 +72,7 @@ export default definePlugin({
|
||||||
replacement: [
|
replacement: [
|
||||||
// Add Decor avatar decoration hook to avatar decoration hook
|
// Add Decor avatar decoration hook to avatar decoration hook
|
||||||
{
|
{
|
||||||
match: /(?<=TryItOut:\i}\),)(?<=user:(\i).+?)/,
|
match: /(?<=TryItOut:\i,guildId:\i}\),)(?<=user:(\i).+?)/,
|
||||||
replace: "vcDecorAvatarDecoration=$self.useUserDecorAvatarDecoration($1),"
|
replace: "vcDecorAvatarDecoration=$self.useUserDecorAvatarDecoration($1),"
|
||||||
},
|
},
|
||||||
// Use added hook
|
// Use added hook
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { addPreEditListener, addPreSendListener, removePreEditListener, removePreSendListener } from "@api/MessageEvents";
|
import { addPreEditListener, addPreSendListener, removePreEditListener, removePreSendListener } from "@api/MessageEvents";
|
||||||
import { definePluginSettings, Settings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { ApngBlendOp, ApngDisposeOp, importApngJs } from "@utils/dependencies";
|
import { ApngBlendOp, ApngDisposeOp, importApngJs } from "@utils/dependencies";
|
||||||
import { getCurrentGuild } from "@utils/discord";
|
import { getCurrentGuild } from "@utils/discord";
|
||||||
import { Logger } from "@utils/Logger";
|
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 { ChannelStore, EmojiStore, FluxDispatcher, lodash, Parser, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
import { Alerts, ChannelStore, EmojiStore, FluxDispatcher, Forms, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common";
|
||||||
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";
|
||||||
|
@ -51,8 +51,6 @@ const PreloadedUserSettingsActionCreators = proxyLazyWebpack(() => UserSettingsA
|
||||||
const AppearanceSettingsActionCreators = proxyLazyWebpack(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators.ProtoClass));
|
const AppearanceSettingsActionCreators = proxyLazyWebpack(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators.ProtoClass));
|
||||||
const ClientThemeSettingsActionsCreators = proxyLazyWebpack(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators));
|
const ClientThemeSettingsActionsCreators = proxyLazyWebpack(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators));
|
||||||
|
|
||||||
const USE_EXTERNAL_EMOJIS = 1n << 18n;
|
|
||||||
const USE_EXTERNAL_STICKERS = 1n << 37n;
|
|
||||||
|
|
||||||
const enum EmojiIntentions {
|
const enum EmojiIntentions {
|
||||||
REACTION = 0,
|
REACTION = 0,
|
||||||
|
@ -162,8 +160,28 @@ const settings = definePluginSettings({
|
||||||
description: "Whether to use hyperlinks when sending fake emojis and stickers",
|
description: "Whether to use hyperlinks when sending fake emojis and stickers",
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
hyperLinkText: {
|
||||||
|
description: "What text the hyperlink should use. {{NAME}} will be replaced with the emoji name.",
|
||||||
|
type: OptionType.STRING,
|
||||||
|
default: "{{NAME}}"
|
||||||
}
|
}
|
||||||
});
|
}).withPrivateSettings<{
|
||||||
|
disableEmbedPermissionCheck: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
function hasPermission(channelId: string, permission: bigint) {
|
||||||
|
const channel = ChannelStore.getChannel(channelId);
|
||||||
|
|
||||||
|
if (!channel || channel.isPrivate()) return true;
|
||||||
|
|
||||||
|
return PermissionStore.can(permission, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasExternalEmojiPerms = (channelId: string) => hasPermission(channelId, PermissionsBits.USE_EXTERNAL_EMOJIS);
|
||||||
|
const hasExternalStickerPerms = (channelId: string) => hasPermission(channelId, PermissionsBits.USE_EXTERNAL_STICKERS);
|
||||||
|
const hasEmbedPerms = (channelId: string) => hasPermission(channelId, PermissionsBits.EMBED_LINKS);
|
||||||
|
const hasAttachmentPerms = (channelId: string) => hasPermission(channelId, PermissionsBits.ATTACH_FILES);
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "FakeNitro",
|
name: "FakeNitro",
|
||||||
|
@ -696,22 +714,6 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hasPermissionToUseExternalEmojis(channelId: string): boolean {
|
|
||||||
const channel = ChannelStore.getChannel(channelId);
|
|
||||||
|
|
||||||
if (!channel || channel.isDM() || channel.isGroupDM() || channel.isMultiUserDM()) return true;
|
|
||||||
|
|
||||||
return PermissionStore.can(USE_EXTERNAL_EMOJIS, channel);
|
|
||||||
},
|
|
||||||
|
|
||||||
hasPermissionToUseExternalStickers(channelId: string) {
|
|
||||||
const channel = ChannelStore.getChannel(channelId);
|
|
||||||
|
|
||||||
if (!channel || channel.isDM() || channel.isGroupDM() || channel.isMultiUserDM()) return true;
|
|
||||||
|
|
||||||
return PermissionStore.can(USE_EXTERNAL_STICKERS, channel);
|
|
||||||
},
|
|
||||||
|
|
||||||
getStickerLink(stickerId: string) {
|
getStickerLink(stickerId: string) {
|
||||||
return `https://media.discordapp.net/stickers/${stickerId}.png?size=${settings.store.stickerSize}`;
|
return `https://media.discordapp.net/stickers/${stickerId}.png?size=${settings.store.stickerSize}`;
|
||||||
},
|
},
|
||||||
|
@ -722,7 +724,7 @@ export default definePlugin({
|
||||||
const { frames, width, height } = await parseURL(stickerLink);
|
const { frames, width, height } = await parseURL(stickerLink);
|
||||||
|
|
||||||
const gif = GIFEncoder();
|
const gif = GIFEncoder();
|
||||||
const resolution = Settings.plugins.FakeNitro.stickerSize;
|
const resolution = settings.store.stickerSize;
|
||||||
|
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
canvas.width = resolution;
|
canvas.width = resolution;
|
||||||
|
@ -783,9 +785,38 @@ export default definePlugin({
|
||||||
return (!origStr[offset] || /\s/.test(origStr[offset])) ? "" : " ";
|
return (!origStr[offset] || /\s/.test(origStr[offset])) ? "" : " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.preSend = addPreSendListener((channelId, messageObj, extra) => {
|
function cannotEmbedNotice() {
|
||||||
|
return new Promise<boolean>(resolve => {
|
||||||
|
Alerts.show({
|
||||||
|
title: "Hold on!",
|
||||||
|
body: <div>
|
||||||
|
<Forms.FormText>
|
||||||
|
You are trying to send/edit a message that contains a FakeNitro emoji or sticker
|
||||||
|
, however you do not have permissions to embed links in the current channel.
|
||||||
|
Are you sure you want to send this message? Your FakeNitro items will appear as a link only.
|
||||||
|
</Forms.FormText>
|
||||||
|
<Forms.FormText type={Forms.FormText.Types.DESCRIPTION}>
|
||||||
|
You can disable this notice in the plugin settings.
|
||||||
|
</Forms.FormText>
|
||||||
|
</div>,
|
||||||
|
confirmText: "Send Anyway",
|
||||||
|
cancelText: "Cancel",
|
||||||
|
secondaryConfirmText: "Do not show again",
|
||||||
|
onConfirm: () => resolve(true),
|
||||||
|
onCloseCallback: () => setImmediate(() => resolve(false)),
|
||||||
|
onConfirmSecondary() {
|
||||||
|
settings.store.disableEmbedPermissionCheck = true;
|
||||||
|
resolve(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.preSend = addPreSendListener(async (channelId, messageObj, extra) => {
|
||||||
const { guildId } = this;
|
const { guildId } = this;
|
||||||
|
|
||||||
|
let hasBypass = false;
|
||||||
|
|
||||||
stickerBypass: {
|
stickerBypass: {
|
||||||
if (!s.enableStickerBypass)
|
if (!s.enableStickerBypass)
|
||||||
break stickerBypass;
|
break stickerBypass;
|
||||||
|
@ -798,7 +829,7 @@ export default definePlugin({
|
||||||
if ("pack_id" in sticker)
|
if ("pack_id" in sticker)
|
||||||
break stickerBypass;
|
break stickerBypass;
|
||||||
|
|
||||||
const canUseStickers = this.canUseStickers && this.hasPermissionToUseExternalStickers(channelId);
|
const canUseStickers = this.canUseStickers && hasExternalStickerPerms(channelId);
|
||||||
if (sticker.available !== false && (canUseStickers || sticker.guild_id === guildId))
|
if (sticker.available !== false && (canUseStickers || sticker.guild_id === guildId))
|
||||||
break stickerBypass;
|
break stickerBypass;
|
||||||
|
|
||||||
|
@ -812,9 +843,24 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sticker.format_type === StickerType.APNG) {
|
if (sticker.format_type === StickerType.APNG) {
|
||||||
|
if (!hasAttachmentPerms(channelId)) {
|
||||||
|
Alerts.show({
|
||||||
|
title: "Hold on!",
|
||||||
|
body: <div>
|
||||||
|
<Forms.FormText>
|
||||||
|
You cannot send this message because it contains an animated FakeNitro sticker,
|
||||||
|
and you do not have permissions to attach files in the current channel. Please remove the sticker to proceed.
|
||||||
|
</Forms.FormText>
|
||||||
|
</div>
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.sendAnimatedSticker(link, sticker.id, channelId);
|
this.sendAnimatedSticker(link, sticker.id, channelId);
|
||||||
|
}
|
||||||
|
|
||||||
return { cancel: true };
|
return { cancel: true };
|
||||||
} else {
|
} else {
|
||||||
|
hasBypass = true;
|
||||||
|
|
||||||
const url = new URL(link);
|
const url = new URL(link);
|
||||||
url.searchParams.set("name", sticker.name);
|
url.searchParams.set("name", sticker.name);
|
||||||
|
|
||||||
|
@ -824,35 +870,47 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.enableEmojiBypass) {
|
if (s.enableEmojiBypass) {
|
||||||
const canUseEmotes = this.canUseEmotes && this.hasPermissionToUseExternalEmojis(channelId);
|
const canUseEmotes = this.canUseEmotes && hasExternalEmojiPerms(channelId);
|
||||||
|
|
||||||
for (const emoji of messageObj.validNonShortcutEmojis) {
|
for (const emoji of messageObj.validNonShortcutEmojis) {
|
||||||
if (!emoji.require_colons) continue;
|
if (!emoji.require_colons) continue;
|
||||||
if (emoji.available !== false && canUseEmotes) continue;
|
if (emoji.available !== false && canUseEmotes) continue;
|
||||||
if (emoji.guildId === guildId && !emoji.animated) continue;
|
if (emoji.guildId === guildId && !emoji.animated) continue;
|
||||||
|
|
||||||
|
hasBypass = true;
|
||||||
|
|
||||||
const emojiString = `<${emoji.animated ? "a" : ""}:${emoji.originalName || emoji.name}:${emoji.id}>`;
|
const emojiString = `<${emoji.animated ? "a" : ""}:${emoji.originalName || emoji.name}:${emoji.id}>`;
|
||||||
|
|
||||||
const url = new URL(emoji.url);
|
const url = new URL(emoji.url);
|
||||||
url.searchParams.set("size", s.emojiSize.toString());
|
url.searchParams.set("size", s.emojiSize.toString());
|
||||||
url.searchParams.set("name", emoji.name);
|
url.searchParams.set("name", emoji.name);
|
||||||
|
|
||||||
|
const linkText = s.hyperLinkText.replaceAll("{{NAME}}", emoji.name);
|
||||||
|
|
||||||
messageObj.content = messageObj.content.replace(emojiString, (match, offset, origStr) => {
|
messageObj.content = messageObj.content.replace(emojiString, (match, offset, origStr) => {
|
||||||
return `${getWordBoundary(origStr, offset - 1)}${s.useHyperLinks ? `[${emoji.name}](${url})` : url}${getWordBoundary(origStr, offset + match.length)}`;
|
return `${getWordBoundary(origStr, offset - 1)}${s.useHyperLinks ? `[${linkText}](${url})` : url}${getWordBoundary(origStr, offset + match.length)}`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasBypass && !s.disableEmbedPermissionCheck && !hasEmbedPerms(channelId)) {
|
||||||
|
if (!await cannotEmbedNotice()) {
|
||||||
|
return { cancel: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { cancel: false };
|
return { cancel: false };
|
||||||
});
|
});
|
||||||
|
|
||||||
this.preEdit = addPreEditListener((channelId, __, messageObj) => {
|
this.preEdit = addPreEditListener(async (channelId, __, messageObj) => {
|
||||||
if (!s.enableEmojiBypass) return;
|
if (!s.enableEmojiBypass) return;
|
||||||
|
|
||||||
const canUseEmotes = this.canUseEmotes && this.hasPermissionToUseExternalEmojis(channelId);
|
|
||||||
|
|
||||||
const { guildId } = this;
|
const { guildId } = this;
|
||||||
|
|
||||||
|
let hasBypass = false;
|
||||||
|
|
||||||
|
const canUseEmotes = this.canUseEmotes && hasExternalEmojiPerms(channelId);
|
||||||
|
|
||||||
messageObj.content = messageObj.content.replace(/(?<!\\)<a?:(?:\w+):(\d+)>/ig, (emojiStr, emojiId, offset, origStr) => {
|
messageObj.content = messageObj.content.replace(/(?<!\\)<a?:(?:\w+):(\d+)>/ig, (emojiStr, emojiId, offset, origStr) => {
|
||||||
const emoji = EmojiStore.getCustomEmojiById(emojiId);
|
const emoji = EmojiStore.getCustomEmojiById(emojiId);
|
||||||
if (emoji == null) return emojiStr;
|
if (emoji == null) return emojiStr;
|
||||||
|
@ -860,12 +918,24 @@ export default definePlugin({
|
||||||
if (emoji.available !== false && canUseEmotes) return emojiStr;
|
if (emoji.available !== false && canUseEmotes) return emojiStr;
|
||||||
if (emoji.guildId === guildId && !emoji.animated) return emojiStr;
|
if (emoji.guildId === guildId && !emoji.animated) return emojiStr;
|
||||||
|
|
||||||
|
hasBypass = true;
|
||||||
|
|
||||||
const url = new URL(emoji.url);
|
const url = new URL(emoji.url);
|
||||||
url.searchParams.set("size", s.emojiSize.toString());
|
url.searchParams.set("size", s.emojiSize.toString());
|
||||||
url.searchParams.set("name", emoji.name);
|
url.searchParams.set("name", emoji.name);
|
||||||
|
|
||||||
return `${getWordBoundary(origStr, offset - 1)}${s.useHyperLinks ? `[${emoji.name}](${url})` : url}${getWordBoundary(origStr, offset + emojiStr.length)}`;
|
const linkText = s.hyperLinkText.replaceAll("{{NAME}}", emoji.name);
|
||||||
|
|
||||||
|
return `${getWordBoundary(origStr, offset - 1)}${s.useHyperLinks ? `[${linkText}](${url})` : url}${getWordBoundary(origStr, offset + emojiStr.length)}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (hasBypass && !s.disableEmbedPermissionCheck && !hasEmbedPerms(channelId)) {
|
||||||
|
if (!await cannotEmbedNotice()) {
|
||||||
|
return { cancel: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { cancel: false };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
box-shadow: inset 0 0 10px 2px grey;
|
box-shadow: inset 0 0 10px 2px grey;
|
||||||
filter: drop-shadow(0 0 2px grey);
|
filter: drop-shadow(0 0 2px grey);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
|
/* negate the border offsetting the lens */
|
||||||
|
margin: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-imgzoom-square {
|
.vc-imgzoom-square {
|
||||||
|
|
|
@ -170,6 +170,11 @@ const settings = definePluginSettings({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
showLastFmLogo: {
|
||||||
|
description: "show the Last.fm logo by the album cover",
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: true,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
|
@ -276,8 +281,10 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
large_image: await getApplicationAsset(largeImage),
|
large_image: await getApplicationAsset(largeImage),
|
||||||
large_text: trackData.album || undefined,
|
large_text: trackData.album || undefined,
|
||||||
|
...(settings.store.showLastFmLogo && {
|
||||||
small_image: await getApplicationAsset("lastfm-small"),
|
small_image: await getApplicationAsset("lastfm-small"),
|
||||||
small_text: "Last.fm",
|
small_text: "Last.fm"
|
||||||
|
}),
|
||||||
} : {
|
} : {
|
||||||
large_image: await getApplicationAsset("lastfm-large"),
|
large_image: await getApplicationAsset("lastfm-large"),
|
||||||
large_text: trackData.album || undefined,
|
large_text: trackData.album || undefined,
|
||||||
|
|
|
@ -32,6 +32,7 @@ const { Editor, Transforms } = findByPropsLazy("Editor", "Transforms");
|
||||||
const { ChatInputTypes } = findByPropsLazy("ChatInputTypes");
|
const { ChatInputTypes } = findByPropsLazy("ChatInputTypes");
|
||||||
|
|
||||||
const InputComponent = LazyComponent(() => find(m => m.default?.type?.render?.toString().includes("default.CHANNEL_TEXT_AREA")).default);
|
const InputComponent = LazyComponent(() => find(m => m.default?.type?.render?.toString().includes("default.CHANNEL_TEXT_AREA")).default);
|
||||||
|
const { createChannelRecordFromServer } = findByPropsLazy("createChannelRecordFromServer");
|
||||||
|
|
||||||
interface UserProps {
|
interface UserProps {
|
||||||
discordId: string;
|
discordId: string;
|
||||||
|
@ -125,19 +126,7 @@ export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: {
|
||||||
const inputType = ChatInputTypes.FORM;
|
const inputType = ChatInputTypes.FORM;
|
||||||
inputType.disableAutoFocus = true;
|
inputType.disableAutoFocus = true;
|
||||||
|
|
||||||
const channel = {
|
const channel = createChannelRecordFromServer({ id: "0", type: 1 });
|
||||||
flags_: 256,
|
|
||||||
guild_id_: null,
|
|
||||||
id: "0",
|
|
||||||
getGuildId: () => null,
|
|
||||||
isPrivate: () => true,
|
|
||||||
isActiveThread: () => false,
|
|
||||||
isArchivedLockedThread: () => false,
|
|
||||||
isDM: () => true,
|
|
||||||
roles: { "0": { permissions: 0n } },
|
|
||||||
getRecipientId: () => "0",
|
|
||||||
hasFlag: () => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -371,6 +371,10 @@ export function Player() {
|
||||||
if (!track || !device?.is_active || shouldHide)
|
if (!track || !device?.is_active || shouldHide)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
const exportTrackImageStyle = {
|
||||||
|
"--vc-spotify-track-image": `url(${track?.album?.image?.url || ""})`,
|
||||||
|
} as React.CSSProperties;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary fallback={() => (
|
<ErrorBoundary fallback={() => (
|
||||||
<div className="vc-spotify-fallback">
|
<div className="vc-spotify-fallback">
|
||||||
|
@ -378,7 +382,7 @@ export function Player() {
|
||||||
<p >Check the console for errors</p>
|
<p >Check the console for errors</p>
|
||||||
</div>
|
</div>
|
||||||
)}>
|
)}>
|
||||||
<div id={cl("player")}>
|
<div id={cl("player")} style={exportTrackImageStyle}>
|
||||||
<Info track={track} />
|
<Info track={track} />
|
||||||
<SeekBar />
|
<SeekBar />
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|
|
@ -31,7 +31,7 @@ function toggleHoverControls(value: boolean) {
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "SpotifyControls",
|
name: "SpotifyControls",
|
||||||
description: "Adds a Spotify player above the account panel",
|
description: "Adds a Spotify player above the account panel",
|
||||||
authors: [Devs.Ven, Devs.afn, Devs.KraXen72],
|
authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000],
|
||||||
options: {
|
options: {
|
||||||
hoverControls: {
|
hoverControls: {
|
||||||
description: "Show controls on hover",
|
description: "Show controls on hover",
|
||||||
|
|
|
@ -170,9 +170,16 @@
|
||||||
/* these importants are necessary, it applies a width and height through inline styles */
|
/* these importants are necessary, it applies a width and height through inline styles */
|
||||||
height: 10px !important;
|
height: 10px !important;
|
||||||
width: 10px !important;
|
width: 10px !important;
|
||||||
|
margin-top: 4px;
|
||||||
background-color: var(--interactive-normal);
|
background-color: var(--interactive-normal);
|
||||||
border-color: var(--interactive-normal);
|
border-color: var(--interactive-normal);
|
||||||
color: var(--interactive-normal);
|
color: var(--interactive-normal);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#vc-spotify-progress-bar:hover > [class^="slider"] [class^="grabber"] {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#vc-spotify-progress-text {
|
#vc-spotify-progress-text {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } 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 { UserStore } from "@webpack/common";
|
||||||
|
|
||||||
export const settings = definePluginSettings({
|
export const settings = definePluginSettings({
|
||||||
superReactByDefault: {
|
superReactByDefault: {
|
||||||
|
@ -49,7 +50,7 @@ export default definePlugin({
|
||||||
find: ".trackEmojiSearchEmpty,200",
|
find: ".trackEmojiSearchEmpty,200",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(\.trackEmojiSearchEmpty,200(?=.+?isBurstReaction:(\i).+?(\i===\i\.EmojiIntention.REACTION)).+?\[\2,\i\]=\i\.useState\().+?\)/,
|
match: /(\.trackEmojiSearchEmpty,200(?=.+?isBurstReaction:(\i).+?(\i===\i\.EmojiIntention.REACTION)).+?\[\2,\i\]=\i\.useState\().+?\)/,
|
||||||
replace: (_, rest, isBurstReactionVariable, isReactionIntention) => `${rest}$self.settings.store.superReactByDefault&&${isReactionIntention})`
|
replace: (_, rest, isBurstReactionVariable, isReactionIntention) => `${rest}$self.shouldSuperReactByDefault&&${isReactionIntention})`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -59,5 +60,9 @@ export default definePlugin({
|
||||||
if (settings.store.unlimitedSuperReactionPlaying) return true;
|
if (settings.store.unlimitedSuperReactionPlaying) return true;
|
||||||
if (playingCount <= settings.store.superReactionPlayingLimit) return true;
|
if (playingCount <= settings.store.superReactionPlayingLimit) return true;
|
||||||
return false;
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
get shouldSuperReactByDefault() {
|
||||||
|
return settings.store.superReactByDefault && UserStore.getCurrentUser().premiumType != null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -69,14 +69,14 @@ function getReactionsWithQueue(msg: Message, e: ReactionEmoji, type: number) {
|
||||||
function makeRenderMoreUsers(users: User[]) {
|
function makeRenderMoreUsers(users: User[]) {
|
||||||
return function renderMoreUsers(_label: string, _count: number) {
|
return function renderMoreUsers(_label: string, _count: number) {
|
||||||
return (
|
return (
|
||||||
<Tooltip text={users.slice(5).map(u => u.username).join(", ")} >
|
<Tooltip text={users.slice(4).map(u => u.username).join(", ")} >
|
||||||
{({ onMouseEnter, onMouseLeave }) => (
|
{({ onMouseEnter, onMouseLeave }) => (
|
||||||
<div
|
<div
|
||||||
className={AvatarStyles.moreUsers}
|
className={AvatarStyles.moreUsers}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
>
|
>
|
||||||
+{users.length - 5}
|
+{users.length - 4}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Tooltip >
|
</Tooltip >
|
||||||
|
|
|
@ -414,6 +414,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
||||||
coolelectronics: {
|
coolelectronics: {
|
||||||
name: "coolelectronics",
|
name: "coolelectronics",
|
||||||
id: 696392247205298207n,
|
id: 696392247205298207n,
|
||||||
|
},
|
||||||
|
Av32000: {
|
||||||
|
name: "Av32000",
|
||||||
|
id: 593436735380127770n,
|
||||||
}
|
}
|
||||||
} satisfies Record<string, Dev>);
|
} satisfies Record<string, Dev>);
|
||||||
|
|
||||||
|
|
1
src/webpack/common/types/utils.d.ts
vendored
1
src/webpack/common/types/utils.d.ts
vendored
|
@ -59,6 +59,7 @@ export interface Alerts {
|
||||||
onCancel?(): void;
|
onCancel?(): void;
|
||||||
onConfirm?(): void;
|
onConfirm?(): void;
|
||||||
onConfirmSecondary?(): void;
|
onConfirmSecondary?(): void;
|
||||||
|
onCloseCallback?(): void;
|
||||||
}): void;
|
}): void;
|
||||||
/** This is a noop, it does nothing. */
|
/** This is a noop, it does nothing. */
|
||||||
close(): void;
|
close(): void;
|
||||||
|
|
Loading…
Reference in a new issue