Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
5d7ede34d8 | ||
|
cd61354998 | ||
|
a452945ac8 | ||
|
b577660800 | ||
|
4f57c7eded | ||
|
e3e5da10a9 | ||
|
998ce72f3b | ||
|
188d12d1a3 | ||
|
a522eab40d | ||
|
c2721f158f | ||
|
61cd7b4d99 | ||
|
926af0d1cd | ||
|
dcaf4aec97 | ||
|
5a97adb435 |
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "vencord",
|
"name": "vencord",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"version": "1.5.6",
|
"version": "1.5.7",
|
||||||
"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": {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
text-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-author-modal-name::before {
|
.vc-author-modal-name::before {
|
||||||
|
@ -62,6 +62,10 @@ if (IS_VESKTOP || !IS_VANILLA) {
|
|||||||
} catch { }
|
} catch { }
|
||||||
|
|
||||||
|
|
||||||
|
const findHeader = (headers: Record<string, string[]>, headerName: Lowercase<string>) => {
|
||||||
|
return Object.keys(headers).find(h => h.toLowerCase() === headerName);
|
||||||
|
};
|
||||||
|
|
||||||
// Remove CSP
|
// Remove CSP
|
||||||
type PolicyResult = Record<string, string[]>;
|
type PolicyResult = Record<string, string[]>;
|
||||||
|
|
||||||
@ -73,6 +77,7 @@ if (IS_VESKTOP || !IS_VANILLA) {
|
|||||||
result[directiveKey] = directiveValue;
|
result[directiveKey] = directiveValue;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
const stringifyPolicy = (policy: PolicyResult): string =>
|
const stringifyPolicy = (policy: PolicyResult): string =>
|
||||||
@ -81,31 +86,39 @@ if (IS_VESKTOP || !IS_VANILLA) {
|
|||||||
.map(directive => directive.flat().join(" "))
|
.map(directive => directive.flat().join(" "))
|
||||||
.join("; ");
|
.join("; ");
|
||||||
|
|
||||||
function patchCsp(headers: Record<string, string[]>, header: string) {
|
const patchCsp = (headers: Record<string, string[]>) => {
|
||||||
if (header in headers) {
|
const header = findHeader(headers, "content-security-policy");
|
||||||
|
|
||||||
|
if (header) {
|
||||||
const csp = parsePolicy(headers[header][0]);
|
const csp = parsePolicy(headers[header][0]);
|
||||||
|
|
||||||
for (const directive of ["style-src", "connect-src", "img-src", "font-src", "media-src", "worker-src"]) {
|
for (const directive of ["style-src", "connect-src", "img-src", "font-src", "media-src", "worker-src"]) {
|
||||||
csp[directive] = ["*", "blob:", "data:", "vencord:", "'unsafe-inline'"];
|
csp[directive] ??= [];
|
||||||
|
csp[directive].push("*", "blob:", "data:", "vencord:", "'unsafe-inline'");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Restrict this to only imported packages with fixed version.
|
// TODO: Restrict this to only imported packages with fixed version.
|
||||||
// Perhaps auto generate with esbuild
|
// Perhaps auto generate with esbuild
|
||||||
csp["script-src"] ??= [];
|
csp["script-src"] ??= [];
|
||||||
csp["script-src"].push("'unsafe-eval'", "https://unpkg.com", "https://cdnjs.cloudflare.com");
|
csp["script-src"].push("'unsafe-eval'", "https://unpkg.com", "https://cdnjs.cloudflare.com");
|
||||||
headers[header] = [stringifyPolicy(csp)];
|
headers[header] = [stringifyPolicy(csp)];
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, resourceType }, cb) => {
|
session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, resourceType }, cb) => {
|
||||||
if (responseHeaders) {
|
if (responseHeaders) {
|
||||||
if (resourceType === "mainFrame")
|
if (resourceType === "mainFrame")
|
||||||
patchCsp(responseHeaders, "content-security-policy");
|
patchCsp(responseHeaders);
|
||||||
|
|
||||||
// Fix hosts that don't properly set the css content type, such as
|
// Fix hosts that don't properly set the css content type, such as
|
||||||
// raw.githubusercontent.com
|
// raw.githubusercontent.com
|
||||||
if (resourceType === "stylesheet")
|
if (resourceType === "stylesheet") {
|
||||||
responseHeaders["content-type"] = ["text/css"];
|
const header = findHeader(responseHeaders, "content-type");
|
||||||
|
if (header)
|
||||||
|
responseHeaders[header] = ["text/css"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cb({ cancel: false, responseHeaders });
|
cb({ cancel: false, responseHeaders });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -58,6 +58,26 @@ export default definePlugin({
|
|||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
|
||||||
|
async handleEvent(e: MessageEvent<any>) {
|
||||||
|
const data = JSON.parse(e.data);
|
||||||
|
|
||||||
|
const { activity } = data;
|
||||||
|
const assets = activity?.assets;
|
||||||
|
|
||||||
|
if (assets?.large_image) assets.large_image = await lookupAsset(activity.application_id, assets.large_image);
|
||||||
|
if (assets?.small_image) assets.small_image = await lookupAsset(activity.application_id, assets.small_image);
|
||||||
|
|
||||||
|
if (activity) {
|
||||||
|
const appId = activity.application_id;
|
||||||
|
apps[appId] ||= await lookupApp(appId);
|
||||||
|
|
||||||
|
const app = apps[appId];
|
||||||
|
activity.name ||= app.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
FluxDispatcher.dispatch({ type: "LOCAL_ACTIVITY_UPDATE", ...data });
|
||||||
|
},
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
// ArmCord comes with its own arRPC implementation, so this plugin just confuses users
|
// ArmCord comes with its own arRPC implementation, so this plugin just confuses users
|
||||||
if ("armcord" in window) return;
|
if ("armcord" in window) return;
|
||||||
@ -65,22 +85,7 @@ export default definePlugin({
|
|||||||
if (ws) ws.close();
|
if (ws) ws.close();
|
||||||
ws = new WebSocket("ws://127.0.0.1:1337"); // try to open WebSocket
|
ws = new WebSocket("ws://127.0.0.1:1337"); // try to open WebSocket
|
||||||
|
|
||||||
ws.onmessage = async e => { // on message, set status to data
|
ws.onmessage = this.handleEvent;
|
||||||
const data = JSON.parse(e.data);
|
|
||||||
|
|
||||||
if (data.activity?.assets?.large_image) data.activity.assets.large_image = await lookupAsset(data.activity.application_id, data.activity.assets.large_image);
|
|
||||||
if (data.activity?.assets?.small_image) data.activity.assets.small_image = await lookupAsset(data.activity.application_id, data.activity.assets.small_image);
|
|
||||||
|
|
||||||
if (data.activity) {
|
|
||||||
const appId = data.activity.application_id;
|
|
||||||
apps[appId] ||= await lookupApp(appId);
|
|
||||||
|
|
||||||
const app = apps[appId];
|
|
||||||
data.activity.name ||= app.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
FluxDispatcher.dispatch({ type: "LOCAL_ACTIVITY_UPDATE", ...data });
|
|
||||||
};
|
|
||||||
|
|
||||||
const connectionSuccessful = await new Promise(res => setTimeout(() => res(ws.readyState === WebSocket.OPEN), 1000)); // check if open after 1s
|
const connectionSuccessful = await new Promise(res => setTimeout(() => res(ws.readyState === WebSocket.OPEN), 1000)); // check if open after 1s
|
||||||
if (!connectionSuccessful) {
|
if (!connectionSuccessful) {
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
import { Settings } from "@api/Settings";
|
import { Settings } 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 { findByPropsLazy } from "@webpack";
|
||||||
|
|
||||||
|
const UserPopoutSectionCssClasses = findByPropsLazy("section", "lastSection");
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "BetterNotesBox",
|
name: "BetterNotesBox",
|
||||||
@ -34,12 +37,20 @@ export default definePlugin({
|
|||||||
match: /hideNote:.+?(?=[,}])/g,
|
match: /hideNote:.+?(?=[,}])/g,
|
||||||
replace: "hideNote:true",
|
replace: "hideNote:true",
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
find: "Messages.NOTE_PLACEHOLDER",
|
find: "Messages.NOTE_PLACEHOLDER",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /\.NOTE_PLACEHOLDER,/,
|
match: /\.NOTE_PLACEHOLDER,/,
|
||||||
replace: "$&spellCheck:!Vencord.Settings.plugins.BetterNotesBox.noSpellCheck,"
|
replace: "$&spellCheck:!Vencord.Settings.plugins.BetterNotesBox.noSpellCheck,"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: ".Messages.NOTE}",
|
||||||
|
replacement: {
|
||||||
|
match: /(\i)\.hideNote\?null/,
|
||||||
|
replace: "$1.hideNote?$self.patchPadding($1)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -56,5 +67,12 @@ export default definePlugin({
|
|||||||
disabled: () => Settings.plugins.BetterNotesBox.hide,
|
disabled: () => Settings.plugins.BetterNotesBox.hide,
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
patchPadding(e: any) {
|
||||||
|
if (!e.lastSection) return;
|
||||||
|
return (
|
||||||
|
<div className={UserPopoutSectionCssClasses.lastSection}></div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -19,6 +19,7 @@
|
|||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { GuildStore } from "@webpack/common";
|
import { GuildStore } from "@webpack/common";
|
||||||
|
import { Channel, User } from "discord-types/general";
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "ForceOwnerCrown",
|
name: "ForceOwnerCrown",
|
||||||
@ -34,25 +35,15 @@ export default definePlugin({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
isGuildOwner(props) {
|
isGuildOwner(props: { user: User, channel: Channel, guildId?: string; }) {
|
||||||
// Check if channel is a Group DM, if so return false
|
if (!props?.user?.id) return false;
|
||||||
if (props?.channel?.type === 3) {
|
if (props.channel?.type === 3 /* GROUP_DM */)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// guild id is in props twice, fallback if the first is undefined
|
// guild id is in props twice, fallback if the first is undefined
|
||||||
const guildId = props?.guildId ?? props?.channel?.guild_id;
|
const guildId = props.guildId ?? props.channel?.guild_id;
|
||||||
const userId = props?.user?.id;
|
const userId = props.user.id;
|
||||||
|
|
||||||
if (guildId && userId) {
|
return GuildStore.getGuild(guildId)?.ownerId === userId;
|
||||||
const guild = GuildStore.getGuild(guildId);
|
|
||||||
if (guild) {
|
|
||||||
return guild.ownerId === userId;
|
|
||||||
}
|
|
||||||
console.error("[ForceOwnerCrown] failed to get guild", { guildId, guild, props });
|
|
||||||
} else {
|
|
||||||
console.error("[ForceOwnerCrown] no guildId or userId", { guildId, userId, props });
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -106,7 +106,7 @@ export default definePlugin({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
find: ".overlayBadge",
|
find: ".Messages.EMBEDDED_ACTIVITIES_HAVE_PLAYED_ONE_KNOWN",
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
match: /(?<=\(\)\.activityTitleText.+?children:(\i)\.name.*?}\),)/,
|
match: /(?<=\(\)\.activityTitleText.+?children:(\i)\.name.*?}\),)/,
|
||||||
|
@ -174,8 +174,8 @@ export default definePlugin({
|
|||||||
find: "handleImageLoad=",
|
find: "handleImageLoad=",
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
match: /(render=function\(\){.{1,500}limitResponsiveWidth.{1,600})onMouseEnter:/,
|
match: /showThumbhashPlaceholder:/,
|
||||||
replace: "$1...$self.makeProps(this),onMouseEnter:"
|
replace: "...$self.makeProps(this),$&"
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -189,7 +189,6 @@ export default definePlugin({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
find: ".carouselModal,",
|
find: ".carouselModal,",
|
||||||
replacement: {
|
replacement: {
|
||||||
|
@ -53,8 +53,6 @@ interface TagSettings {
|
|||||||
[k: string]: TagSetting;
|
[k: string]: TagSetting;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CLYDE_ID = "1081004946872352958";
|
|
||||||
|
|
||||||
// PermissionStore.computePermissions is not the same function and doesn't work here
|
// PermissionStore.computePermissions is not the same function and doesn't work here
|
||||||
const PermissionUtil = findByPropsLazy("computePermissions", "canEveryoneRole") as {
|
const PermissionUtil = findByPropsLazy("computePermissions", "canEveryoneRole") as {
|
||||||
computePermissions({ ...args }): bigint;
|
computePermissions({ ...args }): bigint;
|
||||||
@ -215,7 +213,7 @@ export default definePlugin({
|
|||||||
},
|
},
|
||||||
// add HTML data attributes (for easier theming)
|
// add HTML data attributes (for easier theming)
|
||||||
{
|
{
|
||||||
match: /children:\[(?=\i,\(0,\i\.jsx\)\("span",{className:\i\(\)\.botText,children:(\i)}\)\])/,
|
match: /children:\[(?=\i\?null:\i,\i,\(0,\i\.jsx\)\("span",{className:\i\(\)\.botText,children:(\i)}\)\])/,
|
||||||
replace: "'data-tag':$1.toLowerCase(),children:["
|
replace: "'data-tag':$1.toLowerCase(),children:["
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -230,10 +228,10 @@ export default definePlugin({
|
|||||||
},
|
},
|
||||||
// in the member list
|
// in the member list
|
||||||
{
|
{
|
||||||
find: ".renderBot=function(){",
|
find: ".Messages.GUILD_OWNER,",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /\.BOT;return null!=(\i)&&.{0,10}\?(.{0,50})\.botTag,type:\i/,
|
match: /(?<type>\i)=\(null==.{0,50}\.BOT,null!=(?<user>\i)&&\i\.bot/,
|
||||||
replace: ".BOT;var type=$self.getTag({...this.props,origType:$1.bot?0:null,location:'not-chat'});return type!==null?$2.botTag,type"
|
replace: "$<type> = $self.getTag({user: $<user>, channel: arguments[0].channel, origType: $<user>.bot ? 0 : null, location: 'not-chat' }), typeof $<type> === 'number'"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// pass channel id down props to be used in profiles
|
// pass channel id down props to be used in profiles
|
||||||
@ -253,7 +251,7 @@ export default definePlugin({
|
|||||||
},
|
},
|
||||||
// in profiles
|
// in profiles
|
||||||
{
|
{
|
||||||
find: ",botType:",
|
find: "showStreamerModeTooltip:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /,botType:(\i\((\i)\)),/g,
|
match: /,botType:(\i\((\i)\)),/g,
|
||||||
replace: ",botType:$self.getTag({user:$2,channelId:arguments[0].moreTags_channelId,origType:$1,location:'not-chat'}),"
|
replace: ",botType:$self.getTag({user:$2,channelId:arguments[0].moreTags_channelId,origType:$1,location:'not-chat'}),"
|
||||||
@ -341,15 +339,17 @@ export default definePlugin({
|
|||||||
message, user, channelId, origType, location, channel
|
message, user, channelId, origType, location, channel
|
||||||
}: {
|
}: {
|
||||||
message?: Message,
|
message?: Message,
|
||||||
user: User,
|
user: User & { isClyde(): boolean; },
|
||||||
channel?: Channel & { isForumPost(): boolean; },
|
channel?: Channel & { isForumPost(): boolean; },
|
||||||
channelId?: string;
|
channelId?: string;
|
||||||
origType?: number;
|
origType?: number;
|
||||||
location: "chat" | "not-chat";
|
location: "chat" | "not-chat";
|
||||||
}): number | null {
|
}): number | null {
|
||||||
|
if (!user)
|
||||||
|
return null;
|
||||||
if (location === "chat" && user.id === "1")
|
if (location === "chat" && user.id === "1")
|
||||||
return Tag.Types.OFFICIAL;
|
return Tag.Types.OFFICIAL;
|
||||||
if (user.id === CLYDE_ID)
|
if (user.isClyde())
|
||||||
return Tag.Types.AI;
|
return Tag.Types.AI;
|
||||||
|
|
||||||
let type = typeof origType === "number" ? origType : null;
|
let type = typeof origType === "number" ? origType : null;
|
||||||
|
41
src/plugins/noMosaic/index.ts
Normal file
41
src/plugins/noMosaic/index.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { disableStyle, enableStyle } from "@api/Styles";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
|
||||||
|
import style from "./styles.css?managed";
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "NoMosaic",
|
||||||
|
authors: [Devs.AutumnVN],
|
||||||
|
description: "Removes Discord new image mosaic",
|
||||||
|
tags: ["image", "mosaic", "media"],
|
||||||
|
patches: [{
|
||||||
|
find: "Media Mosaic",
|
||||||
|
replacement: [
|
||||||
|
{
|
||||||
|
match: /mediaLayoutType:\i\.\i\.MOSAIC/,
|
||||||
|
replace: 'mediaLayoutType:"RESPONSIVE"',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /\i===\i\.\i\.MOSAIC/,
|
||||||
|
replace: "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match: /null!==\(\i=\i\.get\(\i\)\)&&void 0!==\i\?\i:"INVALID"/,
|
||||||
|
replace: '"INVALID"',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
start() {
|
||||||
|
enableStyle(style);
|
||||||
|
},
|
||||||
|
stop() {
|
||||||
|
disableStyle(style);
|
||||||
|
}
|
||||||
|
});
|
3
src/plugins/noMosaic/styles.css
Normal file
3
src/plugins/noMosaic/styles.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[class^="nonMediaAttachmentsContainer-"] [class*="messageAttachment-"] {
|
||||||
|
position: relative;
|
||||||
|
}
|
21
src/plugins/noTypingAnimation/index.ts
Normal file
21
src/plugins/noTypingAnimation/index.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 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: "NoTypingAnimation",
|
||||||
|
authors: [Devs.AutumnVN],
|
||||||
|
description: "Disables the CPU-intensive typing dots animation",
|
||||||
|
patches: [{
|
||||||
|
find: "dotCycle",
|
||||||
|
replacement: {
|
||||||
|
match: /document.hasFocus\(\)/,
|
||||||
|
replace: "false"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
@ -44,7 +44,7 @@ const settings = definePluginSettings({
|
|||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "RoleColorEverywhere",
|
name: "RoleColorEverywhere",
|
||||||
authors: [Devs.KingFish, Devs.lewisakura],
|
authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN],
|
||||||
description: "Adds the top role color anywhere possible",
|
description: "Adds the top role color anywhere possible",
|
||||||
patches: [
|
patches: [
|
||||||
// Chat Mentions
|
// Chat Mentions
|
||||||
@ -78,6 +78,10 @@ export default definePlugin({
|
|||||||
match: /(memo\(\(function\((\i)\).{300,500}CHANNEL_MEMBERS_A11Y_LABEL.{100,200}roleIcon.{5,20}null,).," \u2014 ",.\]/,
|
match: /(memo\(\(function\((\i)\).{300,500}CHANNEL_MEMBERS_A11Y_LABEL.{100,200}roleIcon.{5,20}null,).," \u2014 ",.\]/,
|
||||||
replace: "$1$self.roleGroupColor($2)]"
|
replace: "$1$self.roleGroupColor($2)]"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
match: /children:\[.," \u2014 ",.\]/,
|
||||||
|
replace: "children:[$self.roleGroupColor(arguments[0])]"
|
||||||
|
},
|
||||||
],
|
],
|
||||||
predicate: () => settings.store.memberList,
|
predicate: () => settings.store.memberList,
|
||||||
},
|
},
|
||||||
@ -105,7 +109,7 @@ export default definePlugin({
|
|||||||
return colorString && parseInt(colorString.slice(1), 16);
|
return colorString && parseInt(colorString.slice(1), 16);
|
||||||
},
|
},
|
||||||
|
|
||||||
roleGroupColor({ id, count, title, guildId }: { id: string; count: number; title: string; guildId: string; }) {
|
roleGroupColor({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) {
|
||||||
const guild = GuildStore.getGuild(guildId);
|
const guild = GuildStore.getGuild(guildId);
|
||||||
const role = guild?.roles[id];
|
const role = guild?.roles[id];
|
||||||
|
|
||||||
@ -113,7 +117,7 @@ export default definePlugin({
|
|||||||
color: role?.colorString,
|
color: role?.colorString,
|
||||||
fontWeight: "unset",
|
fontWeight: "unset",
|
||||||
letterSpacing: ".05em"
|
letterSpacing: ".05em"
|
||||||
}}>{title} — {count}</span>;
|
}}>{title ?? label} — {count}</span>;
|
||||||
},
|
},
|
||||||
|
|
||||||
getVoiceProps({ user: { id: userId }, guildId }: { user: { id: string; }; guildId: string; }) {
|
getVoiceProps({ user: { id: userId }, guildId }: { user: { id: string; }; guildId: string; }) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.vc-uvs-button > div {
|
.vc-uvs-button>div {
|
||||||
white-space: normal !important;
|
white-space: normal !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,6 +21,7 @@
|
|||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-uvs-popout-margin > [class^="section"] {
|
.vc-uvs-popout-margin-self>[class^="section"] {
|
||||||
margin-top: -12px;
|
padding-top: 0;
|
||||||
|
padding-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,13 @@ 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 definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
import { findStoreLazy } from "@webpack";
|
||||||
import { ChannelStore, GuildStore, UserStore } from "@webpack/common";
|
import { ChannelStore, GuildStore, UserStore } from "@webpack/common";
|
||||||
import { User } from "discord-types/general";
|
import { User } from "discord-types/general";
|
||||||
|
|
||||||
import { VoiceChannelSection } from "./components/VoiceChannelSection";
|
import { VoiceChannelSection } from "./components/VoiceChannelSection";
|
||||||
|
|
||||||
const VoiceStateStore = findStoreLazy("VoiceStateStore");
|
const VoiceStateStore = findStoreLazy("VoiceStateStore");
|
||||||
const UserPopoutSectionCssClasses = findByPropsLazy("section", "lastSection");
|
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
showInUserProfileModal: {
|
showInUserProfileModal: {
|
||||||
@ -88,7 +87,7 @@ export default definePlugin({
|
|||||||
patchPopout: ({ user }: UserProps) => {
|
patchPopout: ({ user }: UserProps) => {
|
||||||
const isSelfUser = user.id === UserStore.getCurrentUser().id;
|
const isSelfUser = user.id === UserStore.getCurrentUser().id;
|
||||||
return (
|
return (
|
||||||
<div className={isSelfUser ? `vc-uvs-popout-margin ${UserPopoutSectionCssClasses.lastSection}` : ""}>
|
<div className={isSelfUser ? "vc-uvs-popout-margin-self" : ""}>
|
||||||
<VoiceChannelField user={user} />
|
<VoiceChannelField user={user} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -24,7 +24,7 @@ import { Margins } from "@utils/margins";
|
|||||||
import { wordsToTitle } from "@utils/text";
|
import { wordsToTitle } from "@utils/text";
|
||||||
import definePlugin, { OptionType, PluginOptionsItem } from "@utils/types";
|
import definePlugin, { OptionType, PluginOptionsItem } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { Button, ChannelStore, Forms, SelectedChannelStore, useMemo, UserStore } from "@webpack/common";
|
import { Button, ChannelStore, Forms, GuildMemberStore, SelectedChannelStore, SelectedGuildStore, useMemo, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
interface VoiceState {
|
interface VoiceState {
|
||||||
userId: string;
|
userId: string;
|
||||||
@ -70,10 +70,12 @@ function clean(str: string) {
|
|||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatText(str: string, user: string, channel: string) {
|
function formatText(str: string, user: string, channel: string, displayName: string, nickname: string) {
|
||||||
return str
|
return str
|
||||||
.replaceAll("{{USER}}", clean(user) || (user ? "Someone" : ""))
|
.replaceAll("{{USER}}", clean(user) || (user ? "Someone" : ""))
|
||||||
.replaceAll("{{CHANNEL}}", clean(channel) || "channel");
|
.replaceAll("{{CHANNEL}}", clean(channel) || "channel")
|
||||||
|
.replaceAll("{{DISPLAY_NAME}}", clean(displayName) || (displayName ? "Someone" : ""))
|
||||||
|
.replaceAll("{{NICKNAME}}", clean(nickname) || (nickname ? "Someone" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -143,8 +145,10 @@ function updateStatuses(type: string, { deaf, mute, selfDeaf, selfMute, userId,
|
|||||||
|
|
||||||
function playSample(tempSettings: any, type: string) {
|
function playSample(tempSettings: any, type: string) {
|
||||||
const settings = Object.assign({}, Settings.plugins.VcNarrator, tempSettings);
|
const settings = Object.assign({}, Settings.plugins.VcNarrator, tempSettings);
|
||||||
|
const currentUser = UserStore.getCurrentUser();
|
||||||
|
const myGuildId = SelectedGuildStore.getGuildId();
|
||||||
|
|
||||||
speak(formatText(settings[type + "Message"], UserStore.getCurrentUser().username, "general"), settings);
|
speak(formatText(settings[type + "Message"], currentUser.username, "general", (currentUser as any).globalName ?? currentUser.username, GuildMemberStore.getNick(myGuildId, currentUser.id) ?? currentUser.username), settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
@ -154,6 +158,7 @@ export default definePlugin({
|
|||||||
|
|
||||||
flux: {
|
flux: {
|
||||||
VOICE_STATE_UPDATES({ voiceStates }: { voiceStates: VoiceState[]; }) {
|
VOICE_STATE_UPDATES({ voiceStates }: { voiceStates: VoiceState[]; }) {
|
||||||
|
const myGuildId = SelectedGuildStore.getGuildId();
|
||||||
const myChanId = SelectedChannelStore.getVoiceChannelId();
|
const myChanId = SelectedChannelStore.getVoiceChannelId();
|
||||||
const myId = UserStore.getCurrentUser().id;
|
const myId = UserStore.getCurrentUser().id;
|
||||||
|
|
||||||
@ -172,9 +177,11 @@ export default definePlugin({
|
|||||||
|
|
||||||
const template = Settings.plugins.VcNarrator[type + "Message"];
|
const template = Settings.plugins.VcNarrator[type + "Message"];
|
||||||
const user = isMe && !Settings.plugins.VcNarrator.sayOwnName ? "" : UserStore.getUser(userId).username;
|
const user = isMe && !Settings.plugins.VcNarrator.sayOwnName ? "" : UserStore.getUser(userId).username;
|
||||||
|
const displayName = user && ((UserStore.getUser(userId) as any).globalName ?? user);
|
||||||
|
const nickname = user && (GuildMemberStore.getNick(myGuildId, userId) ?? user);
|
||||||
const channel = ChannelStore.getChannel(id).name;
|
const channel = ChannelStore.getChannel(id).name;
|
||||||
|
|
||||||
speak(formatText(template, user, channel));
|
speak(formatText(template, user, channel, displayName, nickname));
|
||||||
|
|
||||||
// updateStatuses(type, state, isMe);
|
// updateStatuses(type, state, isMe);
|
||||||
}
|
}
|
||||||
@ -186,7 +193,7 @@ export default definePlugin({
|
|||||||
if (!s) return;
|
if (!s) return;
|
||||||
|
|
||||||
const event = s.mute || s.selfMute ? "unmute" : "mute";
|
const event = s.mute || s.selfMute ? "unmute" : "mute";
|
||||||
speak(formatText(Settings.plugins.VcNarrator[event + "Message"], "", ChannelStore.getChannel(chanId).name));
|
speak(formatText(Settings.plugins.VcNarrator[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
|
||||||
},
|
},
|
||||||
|
|
||||||
AUDIO_TOGGLE_SELF_DEAF() {
|
AUDIO_TOGGLE_SELF_DEAF() {
|
||||||
@ -195,7 +202,7 @@ export default definePlugin({
|
|||||||
if (!s) return;
|
if (!s) return;
|
||||||
|
|
||||||
const event = s.deaf || s.selfDeaf ? "undeafen" : "deafen";
|
const event = s.deaf || s.selfDeaf ? "undeafen" : "deafen";
|
||||||
speak(formatText(Settings.plugins.VcNarrator[event + "Message"], "", ChannelStore.getChannel(chanId).name));
|
speak(formatText(Settings.plugins.VcNarrator[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -312,8 +319,8 @@ export default definePlugin({
|
|||||||
You can customise the spoken messages below. You can disable specific messages by setting them to nothing
|
You can customise the spoken messages below. You can disable specific messages by setting them to nothing
|
||||||
</Forms.FormText>
|
</Forms.FormText>
|
||||||
<Forms.FormText>
|
<Forms.FormText>
|
||||||
The special placeholders <code>{"{{USER}}"}</code> and <code>{"{{CHANNEL}}"}</code>{" "}
|
The special placeholders <code>{"{{USER}}"}</code>, <code>{"{{DISPLAY_NAME}}"}</code>, <code>{"{{NICKNAME}}"}</code> and <code>{"{{CHANNEL}}"}</code>{" "}
|
||||||
will be replaced with the user's name (nothing if it's yourself) and the channel's name respectively
|
will be replaced with the user's name (nothing if it's yourself), the user's display name, the user's nickname on current server and the channel's name respectively
|
||||||
</Forms.FormText>
|
</Forms.FormText>
|
||||||
{hasEnglishVoices && (
|
{hasEnglishVoices && (
|
||||||
<>
|
<>
|
||||||
|
Reference in New Issue
Block a user