Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
thororen1234 2026-01-28 18:35:13 -05:00
commit 9fc100fa9b
No known key found for this signature in database
29 changed files with 206 additions and 69 deletions

View file

@ -5,7 +5,7 @@ export class AuthenticationStore extends FluxStore {
* Gets the id of the current user
*/
getId(): string;
getSessionId(): string;
// This Store has a lot more methods related to everything Auth, but they really should
// not be needed, so they are not typed
}

View file

@ -136,6 +136,6 @@
}
.vc-notification-log-danger-btn {
color: var(--white-500);
background-color: var(--status-danger);
color: var(--control-critical-primary-text-default);
background-color: var(--control-critical-primary-background-default);
}

View file

@ -144,11 +144,11 @@
}
.vc-btn-positive {
background-color: var(--status-positive-background);
background-color: var(--control-connected-background-default, var(--green-430));
color: var(--white);
&:hover {
background-color: var(--redesign-button-positive-pressed-background, var(--green-460));
background-color: var(--control-connected-background-hover, var(--green-460));
}
}

View file

@ -14,8 +14,8 @@
.vc-settings-quickActions-pill {
all: unset;
background: var(--channeltextarea-background);
color: var(--text-default);
background: var(--control-secondary-background-default);
color: var(--control-secondary-text-default, var(--text-default));
display: flex;
align-items: center;
justify-content: center;
@ -29,7 +29,7 @@
}
.vc-settings-quickActions-pill:hover {
background: var(--redesign-button-tertiary-pressed-background);
background: var(--control-secondary-background-hover);
transform: translateY(-1px);
box-shadow: var(--elevation-high);
}

View file

@ -42,7 +42,7 @@
gap: var(--space-8, 8px);
}
.vc-plugin-modal-confirm [class*="footer"]>button {
.vc-plugin-modal-confirm [class*="footer"] > button {
flex: 1;
margin: 0;
width: 100%;
@ -54,3 +54,11 @@
gap: 4px;
color: var(--text-feedback-critical);
}
.vc-settings-modal-content {
padding-bottom: 24px;
}
.vc-plugin-modal-info {
align-items: center;
}

View file

@ -78,7 +78,8 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
const pluginSettings = useSettings([`plugins.${plugin.name}.*`]).plugins[plugin.name];
const hasSettings = Boolean(pluginSettings && plugin.options && !isObjectEmpty(plugin.options));
const [authors, setAuthors] = useState<Partial<User>[]>([]);
// prefill dummy user to avoid layout shift
const [authors, setAuthors] = useState<Partial<User>[]>(() => [makeDummyUser({ username: "Loading...", id: "-1465912127305809920" })]);
useEffect(() => {
(async () => {
@ -178,7 +179,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
</div>
</ModalHeader>
<ModalContent className={Margins.bottom16}>
<ModalContent className={"vc-settings-modal-content"}>
<section>
<BaseText size="lg" weight="semibold" color="text-strong" className={Margins.bottom8}>Authors</BaseText>
<div style={{ width: "fit-content" }}>

View file

@ -55,28 +55,35 @@ function Section(props: {
}) {
const { buttonMap, description, title, settings } = props;
const switches = Array.from(buttonMap, ([name, { icon }]) => {
const Icon = icon ?? PlaceholderIcon;
return (
<Paragraph size="md" weight="semibold" key={name} className={cl("switches-row")}>
<Icon height={20} width={20} />
{name}
<Switch
checked={settings[name]?.enabled ?? true}
onChange={v => {
settings[name] ??= {} as any;
settings[name].enabled = v;
}}
/>
</Paragraph>
);
});
return (
<section>
<BaseText tag="h3" size="xl" weight="bold">{title}</BaseText>
<Paragraph size="sm" className={classes(Margins.top8, Margins.bottom20)}>{description}</Paragraph>
<div className={cl("switches")}>
{Array.from(buttonMap, ([name, { icon }]) => {
const Icon = icon ?? PlaceholderIcon;
return (
<Paragraph size="md" weight="semibold" key={name} className={cl("switches-row")}>
<Icon height={20} width={20} />
{name}
<Switch
checked={settings[name]?.enabled ?? true}
onChange={v => {
settings[name] ??= {} as any;
settings[name].enabled = v;
}}
/>
</Paragraph>
);
})}
{switches.length === 0 && (
<Paragraph weight="medium" className={cl("switches-row")} style={{ color: "var(--text-muted)" }}>
Buttons of enabled plugins will appear here.
</Paragraph>
)}
{switches}
</div>
</section>
);

View file

@ -17,7 +17,7 @@
*/
import { PluginOptionString } from "@utils/types";
import { React, TextInput, useState } from "@webpack/common";
import { React, TextArea, TextInput, useState } from "@webpack/common";
import { resolveError, SettingProps, SettingsSection } from "./Common";
@ -38,15 +38,23 @@ export function TextSetting({ option, pluginSettings, definedSettings, id, onCha
return (
<SettingsSection name={id} description={option.description} error={error}>
<TextInput
type="text"
placeholder={option.placeholder ?? "Enter a value"}
value={state}
onChange={handleChange}
maxLength={null}
disabled={option.disabled?.call(definedSettings) ?? false}
{...option.componentProps}
/>
{option.multiline
? <TextArea
placeholder={option.placeholder ?? "Enter a value"}
value={state}
onChange={handleChange}
disabled={option.disabled?.call(definedSettings) ?? false}
{...option.componentProps} />
: <TextInput
type="text"
placeholder={option.placeholder ?? "Enter a value"}
value={state}
onChange={handleChange}
maxLength={null}
disabled={option.disabled?.call(definedSettings) ?? false}
{...option.componentProps}
/>
}
</SettingsSection>
);
}

View file

@ -76,8 +76,8 @@
}
.vc-cloud-erase-data-danger-btn {
color: var(--white-500);
background-color: var(--status-danger);
color: var(--control-critical-primary-text-default);
background-color: var(--control-critical-primary-background-default);
}
.vc-cloud-icon-with-button {

View file

@ -16,8 +16,8 @@ export default definePlugin({
{
find: '"sticker")',
replacement: {
match: /let (\i)=\(0,\i\.chain\).{0,150}?;(?=return 0===\1\.length)/,
replace: "$&Vencord.Api.ChatButtons._injectButtons($1,arguments[0]);"
match: /0===(\i)\.length(?=.{0,25}?\(0,\i\.jsxs?\)\(.{0,75}?children:\1)/,
replace: "(Vencord.Api.ChatButtons._injectButtons($1,arguments[0]),$&)"
}
}
]

View file

@ -83,8 +83,9 @@ const settings = definePluginSettings({
},
whitelistedLoggers: {
type: OptionType.STRING,
description: "Semi colon separated list of loggers to allow even if others are hidden",
description: "Semicolon (;) separated list of loggers to allow even if others are hidden",
default: "GatewaySocket; Routing/Utils",
multiline: true,
onChange(newVal: string) {
logAllow.clear();
newVal.split(";").map(x => x.trim()).forEach(logAllow.add.bind(logAllow));

View file

@ -27,7 +27,7 @@ export default definePlugin({
{
find: "#{intl::PREVIEW_BYTES_LEFT}",
replacement: {
match: /url:\i,fileName:\i,fileSize:\i}\),(?=.{0,25}setLanguage:)(?<=fileContents:(\i),bytesLeft:(\i).+?)/g,
match: /fileName:\i,fileSize:\i}\),(?=.{0,75}?setLanguage:)(?<=fileContents:(\i),bytesLeft:(\i).+?)/g,
replace: "$&$self.addCopyButton({fileContents:$1,bytesLeft:$2}),"
}
}

View file

@ -76,6 +76,13 @@ export default definePlugin({
],
handleCrash(_this: any, errorState: any) {
if (IS_DEV) {
try {
if (errorState?.info && "componentStack" in errorState.info) {
console.error("Component Stack:", errorState.info.componentStack);
}
} catch { }
}
_this.setState(errorState);
// Already recovering, prevent error which happens more than once too fast to trigger another recover

View file

@ -1,6 +1,6 @@
.vc-decor-danger-btn {
color: var(--white-500);
background-color: var(--status-danger);
color: var(--control-critical-primary-text-default);
background-color: var(--control-critical-primary-background-default);
}
.vc-decor-change-decoration-modal-content {

View file

@ -13,7 +13,7 @@ import { Paragraph } from "@components/Paragraph";
import { Devs } from "@utils/constants";
import { Margins } from "@utils/margins";
import definePlugin, { OptionType } from "@utils/types";
import { Button, RunningGameStore, showToast, TextInput, Toasts, Tooltip, useEffect, useState } from "@webpack/common";
import { Button, RunningGameStore, showToast, TextArea, Toasts, Tooltip, useEffect, useState } from "@webpack/common";
const enum ActivitiesTypes {
Game,
@ -133,7 +133,7 @@ function IdsListComponent(props: { setValue: (value: string) => void; }) {
<section>
<HeadingSecondary>Filter List</HeadingSecondary>
<Paragraph className={Margins.bottom8}>Comma separated list of activity IDs to filter (Useful for filtering specific RPC activities and CustomRPC</Paragraph>
<TextInput
<TextArea
type="text"
value={idsList}
onChange={handleChange}

View file

@ -21,7 +21,7 @@ import { definePluginSettings } from "@api/Settings";
import { debounce } from "@shared/debounce";
import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import definePlugin, { makeRange, OptionType } from "@utils/types";
import definePlugin, { OptionType } from "@utils/types";
import { createRoot, Menu } from "@webpack/common";
import { JSX } from "react";
import type { Root } from "react-dom/client";
@ -58,14 +58,14 @@ export const settings = definePluginSettings({
zoom: {
description: "Zoom of the lens",
type: OptionType.SLIDER,
markers: makeRange(1, 50, 4),
markers: [1, 5, 10, 20, 30, 40, 50],
default: 2,
stickToMarkers: false,
},
size: {
description: "Radius / Size of the lens",
type: OptionType.SLIDER,
markers: makeRange(50, 1000, 50),
markers: [50, 100, 250, 500, 750, 1000],
default: 100,
stickToMarkers: false,
},
@ -73,7 +73,7 @@ export const settings = definePluginSettings({
zoomSpeed: {
description: "How fast the zoom / lens size changes",
type: OptionType.SLIDER,
markers: makeRange(0.1, 5, 0.2),
markers: [0.1, 0.5, 1, 2, 3, 4, 5],
default: 0.5,
stickToMarkers: false,
},

View file

@ -45,6 +45,7 @@ const settings = definePluginSettings({
description: "Additional custom quotes to possibly appear, separated by the below delimiter",
type: OptionType.STRING,
default: "",
multiline: true
},
additionalQuotesDelimiter: {
description: "Delimiter for additional quotes",

View file

@ -115,7 +115,8 @@ const settings = definePluginSettings({
idList: {
description: "Guild/channel/user IDs to blacklist or whitelist (separate with comma)",
type: OptionType.STRING,
default: ""
default: "",
multiline: true,
},
clearMessageCache: {
type: OptionType.COMPONENT,

View file

@ -367,16 +367,19 @@ const settings = definePluginSettings({
type: OptionType.STRING,
description: "Comma-separated list of user IDs to ignore",
default: "",
multiline: true,
},
ignoreChannels: {
type: OptionType.STRING,
description: "Comma-separated list of channel IDs to ignore",
default: "",
multiline: true,
},
ignoreGuilds: {
type: OptionType.STRING,
description: "Comma-separated list of guild IDs to ignore",
default: "",
multiline: true,
},
showEditDiffs: {
type: OptionType.BOOLEAN,

View file

@ -25,15 +25,17 @@ import { ChannelStore, GuildMemberStore } from "@webpack/common";
const settings = definePluginSettings({
userList: {
description:
"List of users to allow or exempt pings for (separated by commas or spaces)",
"List of user ids to allow or exempt pings for (separated by commas or spaces)",
type: OptionType.STRING,
default: "1234567890123445,1234567890123445",
multiline: true
},
roleList: {
description:
"List of roles to allow or exempt pings for (separated by commas or spaces)",
"List of role ids to allow or exempt pings for (separated by commas or spaces)",
type: OptionType.STRING,
default: "1234567890123445,1234567890123445",
multiline: true
},
shouldPingListed: {
description: "Behaviour",

View file

@ -17,8 +17,9 @@
*/
import { definePluginSettings } from "@api/Settings";
import { Button } from "@components/Button";
import { openInviteModal } from "@utils/discord";
import { OptionType } from "@utils/types";
import { Button } from "@webpack/common";
import { authorize, getToken } from "./auth";
import { openBlockModal } from "./components/BlockedUserModal";
@ -60,14 +61,15 @@ export const settings = definePluginSettings({
<Button onClick={openBlockModal}>Manage Blocked Users</Button>
<Button
color={Button.Colors.GREEN}
variant="positive"
onClick={() => {
VencordNative.native.openExternal("https://github.com/sponsors/mantikafasi");
}}
>
Support ReviewDB development
</Button>
<Button onClick={async () => {
<Button variant="link" onClick={async () => {
let url = "https://reviewdb.mantikafasi.dev";
const token = await getToken();
if (token)
@ -78,9 +80,7 @@ export const settings = definePluginSettings({
ReviewDB website
</Button>
<Button onClick={() => {
VencordNative.native.openExternal("https://discord.gg/eWPBSbvznt");
}}>
<Button variant="link" onClick={() => openInviteModal("eWPBSbvznt")}>
ReviewDB Support Server
</Button>
</div >

View file

@ -166,7 +166,7 @@ export default definePlugin({
patches: [
{
find: "UserProfilePopoutBody",
find: /\.POPOUT,onClose:\i}\),nicknameIcons:.+?\.isProvisional/,
replacement: {
match: /userId:\i\.id,guild:\i\}\)(?=])/,
replace: "$&,$self.profilePopoutComponent(arguments[0])"

View file

@ -27,7 +27,7 @@ export default definePlugin({
authors: [Devs.Megu],
patches: [{
find: "#{intl::ACTIVITY_SETTINGS}",
find: ".SEARCH_NO_RESULTS&&0===",
replacement: [
{
match: /(?<=}\)([,;])(\i\.settings)\.forEach.+?(\i)\.push.+\)\)\}\))(?=\)\})/,

View file

@ -173,39 +173,132 @@ export const GoogleLanguages = {
export const DeeplLanguages = {
"": "Detect language",
"ace": "Acehnese",
"af": "Afrikaans",
"sq": "Albanian",
"ar": "Arabic",
"an": "Aragonese",
"hy": "Armenian",
"as": "Assamese",
"ay": "Aymara",
"az": "Azerbaijani",
"ba": "Bashkir",
"eu": "Basque",
"be": "Belarusian",
"bn": "Bengali",
"bho": "Bhojpuri",
"bs": "Bosnian",
"br": "Breton",
"bg": "Bulgarian",
"my": "Burmese",
"yue": "Cantonese",
"ca": "Catalan",
"ceb": "Cebuano",
"zh-hans": "Chinese (Simplified)",
"zh-hant": "Chinese (Traditional)",
"hr": "Croatian",
"cs": "Czech",
"da": "Danish",
"prs": "Dari",
"nl": "Dutch",
"en-us": "English (American)",
"en-gb": "English (British)",
"eo": "Esperanto",
"et": "Estonian",
"fi": "Finnish",
"fr": "French",
"gl": "Galician",
"ka": "Georgian",
"de": "German",
"el": "Greek",
"gn": "Guarani",
"gu": "Gujarati",
"ht": "Haitian Creole",
"ha": "Hausa",
"he": "Hebrew",
"hi": "Hindi",
"hu": "Hungarian",
"is": "Icelandic",
"ig": "Igbo",
"id": "Indonesian",
"ga": "Irish",
"it": "Italian",
"ja": "Japanese",
"ko": "Korean",
"jv": "Javanese",
"pam": "Kapampangan",
"kk": "Kazakh",
"kmr": "Kurdish (Kurmanji)",
"ckb": "Kurdish (Sorani)",
"ky": "Kyrgyz",
"lo": "Lao",
"la": "Latin",
"lv": "Latvian",
"ln": "Lingala",
"lt": "Lithuanian",
"nb": "Norwegian",
"lmo": "Lombard",
"lb": "Luxembourgish",
"mk": "Macedonian",
"mai": "Maithili",
"mg": "Malagasy",
"ms": "Malay",
"ml": "Malayalam",
"mt": "Maltese",
"mi": "Maori",
"mr": "Marathi",
"mn": "Mongolian",
"ne": "Nepali",
"nb": "Norwegian (Bokmål)",
"oc": "Occitan",
"om": "Oromo",
"pag": "Pangasinan",
"ps": "Pashto",
"fa": "Persian",
"pl": "Polish",
"pt-br": "Portuguese (Brazilian)",
"pt-pt": "Portuguese (European)",
"pa": "Punjabi",
"qu": "Quechua",
"ro": "Romanian",
"ru": "Russian",
"sm": "Samoan",
"sa": "Sanskrit",
"gd": "Scottish Gaelic",
"sr": "Serbian",
"st": "Sesotho",
"sn": "Shona",
"scn": "Sicilian",
"sd": "Sindhi",
"si": "Sinhala",
"sk": "Slovak",
"sl": "Slovenian",
"so": "Somali",
"es": "Spanish",
"es-419": "Spanish (Latin American)",
"su": "Sundanese",
"sw": "Swahili",
"sv": "Swedish",
"tl": "Tagalog",
"tg": "Tajik",
"ta": "Tamil",
"tt": "Tatar",
"te": "Telugu",
"th": "Thai",
"ti": "Tigrinya",
"ts": "Tsonga",
"tn": "Tswana",
"tr": "Turkish",
"uk": "Ukrainian"
"tk": "Turkmen",
"uk": "Ukrainian",
"ur": "Urdu",
"ug": "Uyghur",
"uz": "Uzbek",
"vi": "Vietnamese",
"cy": "Welsh",
"wo": "Wolof",
"xh": "Xhosa",
"yi": "Yiddish",
"yo": "Yoruba",
"zu": "Zulu"
} as const;
export function deeplLanguageToGoogleLanguage(language: string) {

View file

@ -24,7 +24,7 @@ import { Logger } from "@utils/Logger";
import { Margins } from "@utils/margins";
import { wordsToTitle } from "@utils/text";
import definePlugin, { ReporterTestable } from "@utils/types";
import { Button, ChannelStore, GuildMemberStore, SelectedChannelStore, SelectedGuildStore, useMemo, UserStore, VoiceStateStore } from "@webpack/common";
import { AuthenticationStore, Button, ChannelStore, GuildMemberStore, SelectedChannelStore, SelectedGuildStore, useMemo, UserStore, VoiceStateStore } from "@webpack/common";
import { ReactElement } from "react";
import { getCurrentVoice, settings } from "./settings";
@ -37,6 +37,7 @@ interface VoiceStateChangeEvent {
mute: boolean;
selfDeaf: boolean;
selfMute: boolean;
sessionId: string;
}
// Mute/Deaf for other people than you is commented out, because otherwise someone can spam it and it will be annoying
@ -157,6 +158,7 @@ export default definePlugin({
for (const state of voiceStates) {
const { userId, channelId, oldChannelId } = state;
const isMe = userId === myId;
if (isMe && state.sessionId !== AuthenticationStore.getSessionId()) continue;
if (!isMe) {
if (!myChanId) continue;
if (channelId !== myChanId && oldChannelId !== myChanId) continue;

View file

@ -35,7 +35,7 @@ import definePlugin, { OptionType } from "@utils/types";
import { chooseFile } from "@utils/web";
import { CloudUpload } from "@vencord/discord-types";
import { CloudUploadPlatform } from "@vencord/discord-types/enums";
import { findCssClassesLazy, findLazy, findStoreLazy } from "@webpack";
import { findLazy, findStoreLazy } from "@webpack";
import { Button, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common";
import { VoiceRecorderDesktop } from "./components/DesktopRecorder";
@ -58,7 +58,6 @@ const EMPTY_META: AudioMetadata = {
const CloudUploadConstructor = findLazy(m => m.prototype?.trackUploadFinished) as typeof CloudUpload;
const PendingReplyStore = findStoreLazy("PendingReplyStore");
const OptionClasses = findCssClassesLazy("optionName", "optionIcon", "optionLabel");
export const cl = classNameFactory("vc-vmsg-");

View file

@ -21,7 +21,7 @@
}
.vc-vmsg-preview-indicator {
background: var(--channeltextarea-background);
background: var(--control-secondary-background-default);
width: 16px;
height: 16px;
border-radius: 50%;

View file

@ -309,6 +309,8 @@ interface IsValid<T, D = unknown> {
export interface PluginSettingStringDef {
type: OptionType.STRING;
default?: string;
/** Whether to use a multiline text area */
multiline?: boolean;
}
export interface PluginSettingNumberDef {
type: OptionType.NUMBER;

View file

@ -599,6 +599,8 @@ export function findCssClasses<S extends string>(...classes: S[]): Record<S, str
if (!res) {
handleModuleNotFound("findCssClasses", ...classes);
if (IS_REPORTER) return null as any;
return {} as Record<S, string>;
}