Merge branch 'dev'

This commit is contained in:
thororen1234 2025-01-22 14:56:53 -05:00
commit 4891f09e24
6 changed files with 90 additions and 74 deletions

View file

@ -5,21 +5,21 @@
*/ */
import { classNameFactory } from "@api/Styles"; import { classNameFactory } from "@api/Styles";
import { makeRange } from "@components/PluginSettings/components";
import { Margins } from "@utils/margins"; import { Margins } from "@utils/margins";
import { classes } from "@utils/misc"; import { classes } from "@utils/misc";
import { useForceUpdater } from "@utils/react"; import { useForceUpdater } from "@utils/react";
import { findByCodeLazy, findLazy } from "@webpack"; import { findByCodeLazy, findLazy } from "@webpack";
import { Button, Card, Forms, Slider, Switch, useRef } from "@webpack/common"; import { Button, Card, Forms, Slider, Switch, Tooltip, useRef } from "@webpack/common";
import { ComponentType, Ref, SyntheticEvent } from "react"; import { ComponentType, Ref, SyntheticEvent } from "react";
import { SoundOverride, SoundPlayer, SoundType } from "../types"; import { SoundOverride, SoundPlayer, SoundType } from "../types";
type FileInput = ComponentType<{ type FileInput = ComponentType<{
ref: Ref<HTMLInputElement>; ref: Ref<HTMLInputElement>;
onChange: (e: SyntheticEvent<HTMLInputElement>) => void; onChange: (event: SyntheticEvent<HTMLInputElement>) => void;
multiple?: boolean; multiple?: boolean;
filters?: { name?: string; extensions: string[]; }[]; filters?: { name?: string; extensions: string[]; }[];
disabled?: boolean;
}>; }>;
const playSound: (id: string) => SoundPlayer = findByCodeLazy(".playWithListener().then"); const playSound: (id: string) => SoundPlayer = findByCodeLazy(".playWithListener().then");
@ -43,29 +43,23 @@ export function SoundOverrideComponent({ type, override, onChange }: { type: Sou
className={Margins.bottom16} className={Margins.bottom16}
hideBorder={true} hideBorder={true}
> >
{type.name} <span className={cl("id")}>({type.id})</span> <Tooltip text={type.id}>
{tooltipProps => <span {...tooltipProps}>{type.name}</span>}
</Tooltip>
</Switch> </Switch>
<Forms.FormTitle>Sound File</Forms.FormTitle>
<div className={classes(cl("file"), Margins.bottom16)} >
<Forms.FormText className={cl("file-name")}>{override.url.length === 0 ? "Discord Default" : (override.fileName || "Custom Sound")}</Forms.FormText>
<Button <Button
color={Button.Colors.PRIMARY} color={Button.Colors.PRIMARY}
className={Margins.bottom16} size={Button.Sizes.SMALL}
onClick={() => {
if (sound.current != null)
sound.current.stop();
sound.current = playSound(type.id);
}}
disabled={!override.enabled} disabled={!override.enabled}
className={cl("file-replace")}
> >
Preview Replace
</Button>
<Forms.FormTitle>Replacement Sound</Forms.FormTitle>
<Button
color={Button.Colors.PRIMARY}
disabled={!override.enabled}
className={classes(Margins.right8, Margins.bottom16, cl("upload"))}
>
Upload
<FileInput <FileInput
ref={fileInputRef} ref={fileInputRef}
disabled={!override.enabled}
onChange={event => { onChange={event => {
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
@ -80,6 +74,7 @@ export function SoundOverrideComponent({ type, override, onChange }: { type: Sou
const reader = new FileReader; const reader = new FileReader;
reader.onload = () => { reader.onload = () => {
override.url = reader.result as string; override.url = reader.result as string;
override.fileName = file.name;
onChange(); onChange();
update(); update();
}; };
@ -91,20 +86,20 @@ export function SoundOverrideComponent({ type, override, onChange }: { type: Sou
</Button> </Button>
<Button <Button
color={Button.Colors.RED} color={Button.Colors.RED}
size={Button.Sizes.SMALL}
onClick={() => { onClick={() => {
override.url = ""; override.url = "";
onChange(); onChange();
update(); update();
}} }}
disabled={!(override.enabled && override.url.length !== 0)} disabled={!(override.enabled && override.url.length !== 0)}
style={{ display: "inline" }} className={cl("file-reset")}
className={classes(Margins.right8, Margins.bottom16)}
> >
Clear Reset
</Button> </Button>
</div>
<Forms.FormTitle>Volume</Forms.FormTitle> <Forms.FormTitle>Volume</Forms.FormTitle>
<Slider <Slider
markers={makeRange(0, 100, 10)}
initialValue={override.volume} initialValue={override.volume}
onValueChange={value => { onValueChange={value => {
override.volume = value; override.volume = value;
@ -114,6 +109,18 @@ export function SoundOverrideComponent({ type, override, onChange }: { type: Sou
className={Margins.bottom16} className={Margins.bottom16}
disabled={!override.enabled} disabled={!override.enabled}
/> />
<Button
color={Button.Colors.PRIMARY}
className={Margins.bottom16}
onClick={() => {
if (sound.current != null)
sound.current.stop();
sound.current = playSound(type.id);
}}
disabled={!override.enabled}
>
Preview
</Button>
</Card> </Card>
); );
} }

View file

@ -2,10 +2,17 @@
padding: 1em 1em 0; padding: 1em 1em 0;
} }
.vc-custom-sounds-id { .vc-custom-sounds-file {
color: var(--text-muted); display: flex;
align-items: center;
gap: 0.5em;
} }
.vc-custom-sounds-upload { .vc-custom-sounds-file-name {
flex-grow: 1;
}
.vc-custom-sounds-file-replace,
.vc-custom-sounds-file-reset {
display: inline; display: inline;
} }

View file

@ -11,6 +11,7 @@ export interface SoundType {
export interface SoundOverride { export interface SoundOverride {
enabled: boolean; enabled: boolean;
fileName: string;
url: string; url: string;
volume: number; volume: number;
} }
@ -51,6 +52,7 @@ export const soundTypes: readonly SoundType[] = [
export function makeEmptyOverride(): SoundOverride { export function makeEmptyOverride(): SoundOverride {
return { return {
enabled: false, enabled: false,
fileName: "",
url: "", url: "",
volume: 100 volume: 100
}; };

View file

@ -76,7 +76,7 @@ export default definePlugin({
{ {
find: "useGenerateUserSettingsSections", find: "useGenerateUserSettingsSections",
replacement: { replacement: {
match: /(\.FRIEND_REQUESTS)/, match: /(\.CLIPS)/,
replace: "$1,\"SCAN_QR_CODE\"" replace: "$1,\"SCAN_QR_CODE\""
} }
}, },

View file

@ -34,19 +34,19 @@ export default definePlugin({
{ {
find: "#{intl::STICKER_BUTTON_LABEL}", find: "#{intl::STICKER_BUTTON_LABEL}",
replacement: [{ replacement: [{
match: /(children:\(0,\w\.jsx\)\()([\w.]+?)(,{innerClassName.{10,30}\.stickerButton)/, match: /(children:\(0,\i\.jsx\)\()([\w.]+?)(,{innerClassName.{10,30}\.stickerButton)/,
replace: (_, head, button, tail) => { replace: (_, head, button, tail) => {
const isMoreStickers = "arguments[0]?.stickersType"; const isMoreStickers = "arguments[0]?.stickersType";
return `${head}${isMoreStickers}?$self.stickerButton:${button}${tail}`; return `${head}${isMoreStickers}?$self.stickerButton:${button}${tail}`;
} }
}, { }, {
match: /(\w=)(\w\.useCallback\(\(\)=>\{\(0,\w+\.\w+\)\([\w.]*?\.STICKER,.*?);/, match: /(\i=)(\i\.useCallback\(\(\)=>\{\(0,\w+\.\w+\)\([\w.]*?\.STICKER,.*?);/,
replace: (_, decl, cb) => { replace: (_, decl, cb) => {
const newCb = cb.replace(/(?<=\(\)=>\{\(.*?\)\().+?\.STICKER/, "\"stickers+\""); const newCb = cb.replace(/(?<=\(\)=>\{\(.*?\)\().+?\.STICKER/, "\"stickers+\"");
return `${decl}arguments[0]?.stickersType?${newCb}:${cb};`; return `${decl}arguments[0]?.stickersType?${newCb}:${cb};`;
} }
}, { }, {
match: /(\w)=((\w)===\w+?\.\w+?\.STICKER)/, match: /(\i)=((\i)===\w+?\.\w+?\.STICKER)/,
replace: (_, isActive, isStickerTab, currentTab) => { replace: (_, isActive, isStickerTab, currentTab) => {
const c = "arguments[0].stickersType"; const c = "arguments[0].stickersType";
return `${isActive}=${c}?(${currentTab}===${c}):(${isStickerTab})`; return `${isActive}=${c}?(${currentTab}===${c}):(${isStickerTab})`;
@ -56,7 +56,7 @@ export default definePlugin({
{ {
find: ".gifts)", find: ".gifts)",
replacement: { replacement: {
match: /,\(null===\(\w=\w\.stickers\)\|\|void 0.*?(\w)\.push\((\(0,\w\.jsx\))\((.+?),{disabled:\w,type:(\w)},"sticker"\)\)/, match: /\(null===\(\i=\i\.stickers\).*?(\i)\.push\((\(0,\i\.jsx\))\((.+?),{disabled:\w,type:(\i)},"sticker"\)\)/,
replace: (m, _, jsx, compo, type) => { replace: (m, _, jsx, compo, type) => {
const c = "arguments[0].type"; const c = "arguments[0].type";
return `${m},${c}?.submit?.button&&${_}.push(${jsx}(${compo},{disabled:!${c}?.submit?.button,type:${type},stickersType:"stickers+"},"stickers+"))`; return `${m},${c}?.submit?.button&&${_}.push(${jsx}(${compo},{disabled:!${c}?.submit?.button,type:${type},stickersType:"stickers+"},"stickers+"))`;
@ -87,7 +87,7 @@ export default definePlugin({
{ {
find: '==="remove_text"', find: '==="remove_text"',
replacement: { replacement: {
match: /,\w\.insertText=\w=>{[\w ;]*?1===\w\.length&&.+?==="remove_text"/, match: /,\i\.insertText=\i=>{[\w ;]*?1===\i\.length&&.+?==="remove_text"/,
replace: ",$self.textEditor=arguments[0]$&" replace: ",$self.textEditor=arguments[0]$&"
} }
} }

View file

@ -31,7 +31,7 @@ export default definePlugin({
replace: (_, rest1, rest2, args) => "" + replace: (_, rest1, rest2, args) => "" +
`${rest1}async ${rest2}` + `${rest1}async ${rest2}` +
`if(await Vencord.Api.MessageEvents._handlePreEdit(${args}))` + `if(await Vencord.Api.MessageEvents._handlePreEdit(${args}))` +
"return Promise.resolve({shouldClear:false,shouldRefocus:true});" "return Promise.resolve({shouldClear:true,shouldRefocus:true});"
} }
}, },
{ {
@ -39,12 +39,12 @@ export default definePlugin({
replacement: { replacement: {
// props.chatInputType...then((function(isMessageValid)... var parsedMessage = b.c.parse(channel,... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply); // props.chatInputType...then((function(isMessageValid)... var parsedMessage = b.c.parse(channel,... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply);
// Lookbehind: validateMessage)({openWarningPopout:..., type: i.props.chatInputType, content: t, stickers: r, ...}).then((function(isMessageValid) // Lookbehind: validateMessage)({openWarningPopout:..., type: i.props.chatInputType, content: t, stickers: r, ...}).then((function(isMessageValid)
match: /(\{openWarningPopout:.{0,100}type:this.props.chatInputType.+?\.then\()(\i=>\{.+?let (\i)=\i\.\i\.parse\((\i),.+?let (\i)=\i\.\i\.getSendMessageOptions\(\{.+?\}\);)(?<=\)\(({.+?})\)\.then.+?)/, match: /(\((\{openWarningPopout:.{0,200}?\})\)\.then\()(\i=>\{.+?let (\i)=\i\.\i\.parse\((\i),.+?let (\i)=\i\.\i\.getSendMessageOptions\(\{.+?\}\);)/,
// props.chatInputType...then((async function(isMessageValid)... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply); if(await Vencord.api...) return { shoudClear:true, shouldRefocus:true }; // props.chatInputType...then((async function(isMessageValid)... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply); if(await Vencord.api...) return { shoudClear:true, shouldRefocus:true };
replace: (_, rest1, rest2, parsedMessage, channel, replyOptions, extra) => "" + replace: (_, rest1, extra, rest2, parsedMessage, channel, replyOptions) => "" +
`${rest1}async ${rest2}` + `${rest1}async ${rest2}` +
`if(await Vencord.Api.MessageEvents._handlePreSend(${channel}.id,${parsedMessage},${extra},${replyOptions}))` + `if(await Vencord.Api.MessageEvents._handlePreSend(${channel}.id,${parsedMessage},${extra},${replyOptions}))` +
"return{shouldClear:false,shouldRefocus:true};" "return{shouldClear:true,shouldRefocus:true};"
} }
}, },
{ {