diff --git a/README.md b/README.md
index d9913ee2f..3c81c3108 100644
--- a/README.md
+++ b/README.md
@@ -66,7 +66,6 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch
- GodMode by Tolgchu
- GoodPerson by nin0dev & mantikafasi
- GoogleThat by Samwich
-- Grammar by Samwich
- GrammarFix by unstream
- HideChatButtons by iamme
- HideMessage by Hanzy
@@ -108,6 +107,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch
- NotificationTitle by Kyuuhachi
- OnePingPerDM by ProffDea
- PinIcon by iamme
+- PolishWording (Grammar) by Samwich
- PlatformSpoofer by Drag
- PurgeMessages by bhop & nyx
- QuestionMarkReplacement by nyx
@@ -143,7 +143,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch
- VCSupport by thororen
- VencordRPC by AutumnVN
- VideoSpeed by Samwich
-- ViewRaw2 by Kyuuhachi
+- ViewRawVariant (ViewRaw2) by Kyuuhachi
- VoiceChannelLog by Sqaaakoi & maintained by thororen
- VoiceChatUtilities by D3SOX
- WebpackTarball by Kyuuhachi
diff --git a/src/debug/loadLazyChunks.ts b/src/debug/loadLazyChunks.ts
index 6923d3a23..c7f8047db 100644
--- a/src/debug/loadLazyChunks.ts
+++ b/src/debug/loadLazyChunks.ts
@@ -27,11 +27,11 @@ export async function loadLazyChunks() {
const LazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?(\i\.e\("?[^)]+?"?\)[^\]]*?)(?:\]\))?)\.then\(\i\.bind\(\i,"?([^)]+?)"?\)\)/g);
- const foundCssDebuggingLoad = false;
+ let foundCssDebuggingLoad = false;
async function searchAndLoadLazyChunks(factoryCode: string) {
// Workaround to avoid loading the CSS debugging chunk which turns the app pink
- const hasCssDebuggingLoad = foundCssDebuggingLoad ? false : factoryCode.includes(".cssDebuggingEnabled&&");
+ const hasCssDebuggingLoad = foundCssDebuggingLoad ? false : (foundCssDebuggingLoad = factoryCode.includes(".cssDebuggingEnabled&&"));
const lazyChunks = factoryCode.matchAll(LazyChunkRegex);
const validChunkGroups = new Set<[chunkIds: number[], entryPoint: number]>();
diff --git a/src/equicordplugins/ViewRawVariant/index.tsx b/src/equicordplugins/ViewRawVariant/index.tsx
new file mode 100644
index 000000000..fc29d2d40
--- /dev/null
+++ b/src/equicordplugins/ViewRawVariant/index.tsx
@@ -0,0 +1,150 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import { NavContextMenuPatchCallback } from "@api/ContextMenu";
+import { migratePluginSettings } from "@api/Settings";
+import { CodeBlock } from "@components/CodeBlock";
+import ErrorBoundary from "@components/ErrorBoundary";
+import { Devs } from "@utils/constants";
+import { getIntlMessage } from "@utils/discord";
+import { Margins } from "@utils/margins";
+import {
+ closeModal,
+ ModalCloseButton,
+ ModalContent,
+ ModalHeader,
+ ModalRoot,
+ ModalSize,
+ openModal,
+} from "@utils/modal";
+import definePlugin from "@utils/types";
+import { Forms, Menu, Text } from "@webpack/common";
+import { Message } from "discord-types/general";
+
+migratePluginSettings("ViewRawVariant", "ViewRaw2");
+
+type CustomMessage = Message & {
+ editHistory?: any;
+ deleted?: any;
+ firstEditTimestamp?: any;
+};
+
+const CopyIcon = () => {
+ return (
+
+ );
+};
+
+function cleanMessage(msg: CustomMessage) {
+ const author = { ...msg.author } as any;
+ delete author.email;
+ delete author.phone;
+ delete author.mfaEnabled;
+ delete author.personalConnectionId;
+ delete msg.editHistory;
+ delete msg.deleted;
+ delete msg.firstEditTimestamp;
+ return { ...msg, author };
+}
+
+function openViewRawModal(obj: any, type: string, isMessage?: boolean) {
+ const key = openModal((props) => (
+
+
+
+
+ View Raw {type}
+
+ closeModal(key)} />
+
+
+
+ {isMessage && (
+ <>
+
+ Content
+
+
+
+ >
+ )}
+
+ {type} Data
+
+
+
+
+
+ ));
+}
+
+function makeContextCallback(
+ name: string,
+ action: (any) => void,
+): NavContextMenuPatchCallback {
+ return (children, props) => {
+ if (props.label === getIntlMessage("CHANNEL_ACTIONS_MENU_LABEL"))
+ return; // random shit like notification settings
+
+ const value = props[name];
+ if (!value) return;
+
+ const lastChild = children.at(-1);
+ if (lastChild?.key === "developer-actions") {
+ const p = lastChild.props;
+ if (!Array.isArray(p.children)) p.children = [p.children];
+
+ children = p.children;
+ }
+
+ children.push(
+
action(value)}
+ icon={CopyIcon}
+ />,
+ );
+ };
+}
+
+export default definePlugin({
+ name: "ViewRawVariant",
+ description:
+ "Copy/View raw content of any message, channel, or guild, but show in the right click menu.",
+ authors: [Devs.KingFish, Devs.Ven, Devs.rad, Devs.ImLvna, Devs.Kyuuhachi],
+ contextMenus: {
+ "guild-context": makeContextCallback("guild", (val) =>
+ openViewRawModal(val, "Guild"),
+ ),
+ "channel-context": makeContextCallback("channel", (val) =>
+ openViewRawModal(val, "Channel"),
+ ),
+ "user-context": makeContextCallback("user", (val) =>
+ openViewRawModal(val, "User"),
+ ),
+ message: makeContextCallback("message", (val) =>
+ openViewRawModal(cleanMessage(val), "Message", true),
+ ),
+ },
+});
diff --git a/src/equicordplugins/fixFileExtensions/components.tsx b/src/equicordplugins/fixFileExtensions/components.tsx
index 91112ba75..65b76df10 100644
--- a/src/equicordplugins/fixFileExtensions/components.tsx
+++ b/src/equicordplugins/fixFileExtensions/components.tsx
@@ -8,7 +8,7 @@ const extensionMap = {
"ogg": [".ogv", ".oga", ".ogx", ".ogm", ".spx", ".opus"],
"jpg": [".jpg", ".jpeg", ".jfif", ".jpe", ".jif", ".jfi", ".pjpeg", ".pjp"],
"svg": [".svgz"],
- "mp4": [".m4v", ".m4a", ".m4r", ".m4b", ".m4p"],
+ "mp4": [".m4v", ".m4r", ".m4b", ".m4p"],
"mov": [".movie", ".qt"],
};
diff --git a/src/equicordplugins/grammarFix/index.ts b/src/equicordplugins/grammarFix/index.ts
index b5c38829a..0ec7d6f7d 100644
--- a/src/equicordplugins/grammarFix/index.ts
+++ b/src/equicordplugins/grammarFix/index.ts
@@ -13,57 +13,64 @@ import { definePluginSettings } from "@api/Settings";
import { EquicordDevs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
-const settings = definePluginSettings(
- {
- autoCapitalization: {
- type: OptionType.BOOLEAN,
- description: "Auto Capitalization to the first letter"
- },
- autoPunctuation: {
- type: OptionType.BOOLEAN,
- description: "Auto Punctuation at the end of a sentence"
- },
- autoWordReplacement: {
- type: OptionType.BOOLEAN,
- description: "Auto Capitalizes the first letter"
- }
- }
-);
+const settings = definePluginSettings({
+ autoCapitalization: {
+ type: OptionType.BOOLEAN,
+ description: "Auto Capitalization to the first letter",
+ },
+ autoPunctuation: {
+ type: OptionType.BOOLEAN,
+ description: "Auto Punctuation at the end of a sentence",
+ },
+ autoWordReplacement: {
+ type: OptionType.BOOLEAN,
+ description: "Auto Capitalizes the first letter",
+ },
+});
-const getPresend = dictionary => {
+const getPresend = (dictionary) => {
const presendObject: SendListener = (_, msg) => {
msg.content = msg.content.trim();
if (!msg.content.includes("```") && /\w/.test(msg.content.charAt(0))) {
if (settings.store.autoWordReplacement) {
const re = new RegExp(
`(^|(?<=[^A-Z0-9]+))(${Object.keys(dictionary)
- .map(k => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
+ .map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
.join("|")})((?=[^A-Z0-9]+)|$)`,
- "gi"
+ "gi",
);
if (re !== null) {
- msg.content = msg.content.replace(re, match => {
+ msg.content = msg.content.replace(re, (match) => {
return dictionary[match.toLowerCase()] || match;
});
}
}
if (settings.store.autoPunctuation) {
- if (/[A-Z0-9]/i.test(msg.content.charAt(msg.content.length - 1))) {
- if (!msg.content.startsWith("http", msg.content.lastIndexOf(" ") + 1))
+ if (
+ /[A-Z0-9]/i.test(msg.content.charAt(msg.content.length - 1))
+ ) {
+ if (
+ !msg.content.startsWith(
+ "http",
+ msg.content.lastIndexOf(" ") + 1,
+ )
+ )
msg.content += ".";
}
}
// Ensure sentences are capitalized after punctuation
if (settings.store.autoCapitalization) {
- msg.content = msg.content.replace(/([.!?])\s*(\w)/g, match =>
- match.toUpperCase()
+ msg.content = msg.content.replace(/([.!?])\s*(\w)/g, (match) =>
+ match.toUpperCase(),
);
// Ensure the first character of the entire message is capitalized
if (!msg.content.startsWith("http")) {
- msg.content = msg.content.charAt(0).toUpperCase() + msg.content.slice(1);
+ msg.content =
+ msg.content.charAt(0).toUpperCase() +
+ msg.content.slice(1);
}
}
}
@@ -79,7 +86,7 @@ export default definePlugin({
settings,
async start() {
let dictionary = await fetch(
- "https://raw.githubusercontent.com/wont-stream/dictionary/3d52fecd9aca5dfee0fcde0df2c2af357f977df7/index.min.json"
+ "https://raw.githubusercontent.com/wont-stream/dictionary/3d52fecd9aca5dfee0fcde0df2c2af357f977df7/index.min.json",
);
dictionary = await dictionary.json();
diff --git a/src/equicordplugins/moreStickers/components/misc.tsx b/src/equicordplugins/moreStickers/components/misc.tsx
index e6c3bcd33..b9194675d 100644
--- a/src/equicordplugins/moreStickers/components/misc.tsx
+++ b/src/equicordplugins/moreStickers/components/misc.tsx
@@ -11,7 +11,7 @@ import { Button, Forms, React, TabBar, Text, TextArea, Toasts } from "@webpack/c
import { convert as convertLineEP, getIdFromUrl as getLineEmojiPackIdFromUrl, getStickerPackById as getLineEmojiPackById, isLineEmojiPackHtml, parseHtml as getLineEPFromHtml } from "../lineEmojis";
import { convert as convertLineSP, getIdFromUrl as getLineStickerPackIdFromUrl, getStickerPackById as getLineStickerPackById, isLineStickerPackHtml, parseHtml as getLineSPFromHtml } from "../lineStickers";
-import { migrate } from "../migrate-v1";
+import { isV1, migrate } from "../migrate-v1";
import { deleteStickerPack, getStickerPack, getStickerPackMetas, saveStickerPack } from "../stickers";
import { SettingsTabsKey, Sticker, StickerPack, StickerPackMeta } from "../types";
import { cl, clPicker, Mutex } from "../utils";
@@ -92,6 +92,7 @@ export const Settings = () => {
const [addStickerHtml, setAddStickerHtml] = React.useState("");
const [tab, setTab] = React.useState(SettingsTabsKey.ADD_STICKER_PACK_URL);
const [hoveredStickerPackId, setHoveredStickerPackId] = React.useState(null);
+ const [_isV1, setV1] = React.useState(false);
async function refreshStickerPackMetas() {
setstickerPackMetas(await getStickerPackMetas());
@@ -99,6 +100,9 @@ export const Settings = () => {
React.useEffect(() => {
refreshStickerPackMetas();
}, []);
+ React.useEffect(() => {
+ isV1().then(setV1);
+ }, []);
return (
@@ -365,7 +369,7 @@ export const Settings = () => {
diff --git a/src/equicordplugins/moreStickers/index.tsx b/src/equicordplugins/moreStickers/index.tsx
index f02e6dc3d..5716f8e19 100644
--- a/src/equicordplugins/moreStickers/index.tsx
+++ b/src/equicordplugins/moreStickers/index.tsx
@@ -64,11 +64,11 @@ export default definePlugin({
}
},
{
- find: "#{intl::EXPRESSION_PICKER_GIF}",
+ find: `role:"tablist","aria-label":`,
replacement: {
- match: /role:"tablist",.+?#{intl::EXPRESSION_PICKER_CATEGORIES_A11Y_LABEL}\),children:(\[.*?\)\]}\)}\):null,)(.*?closePopout:\w.*?:null)/s,
+ match: /role:"tablist",.*?,?"aria-label":.+?\),children:(\[.*?\)\]}\)}\):null,)(.*?closePopout:\w.*?:null)/s,
replace: m => {
- const stickerTabRegex = /(\w+?)\?(\([^()]+?\))\((.{1,2}),{.{0,128},isActive:(.{1,2})===.{1,150},children:(.{1,10}#{intl::EXPRESSION_PICKER_STICKER}).*?:null/s;
+ const stickerTabRegex = /(\w+?)\?(\([^()]+?\))\((.{1,2}),{.{0,128},isActive:(.{1,2})===.{1,6}\.STICKER.{1,140},children:(.{1,2}\.intl\.string\(.+?\)).*?:null/s;
const res = m.replace(stickerTabRegex, (_m, canUseStickers, jsx, tabHeaderComp, currentTab, stickerText) => {
const isActive = `${currentTab}==="stickers+"`;
return (
diff --git a/src/equicordplugins/moreStickers/migrate-v1.ts b/src/equicordplugins/moreStickers/migrate-v1.ts
index 539ea004d..cdf01aa97 100644
--- a/src/equicordplugins/moreStickers/migrate-v1.ts
+++ b/src/equicordplugins/moreStickers/migrate-v1.ts
@@ -57,6 +57,20 @@ function migrateStickerPack(oldStickerPack: StickerPack): StickerPack {
};
}
+export async function isV1() {
+ const newPackMetas = await getStickerPackMetas(PACKS_KEY);
+ if (newPackMetas.length > 0) {
+ return false;
+ }
+
+ const oldPackMetas = await getStickerPackMetas(PACKS_KEY_OLD);
+ if (oldPackMetas.length === 0) {
+ return false;
+ }
+
+ return true;
+}
+
export async function migrate() {
const newPackMetas = await getStickerPackMetas(PACKS_KEY);
if (newPackMetas.length > 0) {
diff --git a/src/equicordplugins/moreStickers/stickers.ts b/src/equicordplugins/moreStickers/stickers.ts
index 4a12bda34..2e7e1f7cd 100644
--- a/src/equicordplugins/moreStickers/stickers.ts
+++ b/src/equicordplugins/moreStickers/stickers.ts
@@ -7,11 +7,12 @@
import * as DataStore from "@api/DataStore";
import { removeRecentStickerByPackId } from "./components";
-import { StickerPack, StickerPackMeta } from "./types";
+import { DynamicPackSetMeta, DynamicStickerPackMeta, StickerPack, StickerPackMeta } from "./types";
import { Mutex } from "./utils";
const mutex = new Mutex();
const PACKS_KEY = "MoreStickers:Packs";
+const DYNAMIC_PACK_SET_METAS_KEY = "MoreStickers:DynamicPackSetMetas";
/**
* Convert StickerPack to StickerPackMeta
@@ -24,7 +25,8 @@ function stickerPackToMeta(sp: StickerPack): StickerPackMeta {
id: sp.id,
title: sp.title,
author: sp.author,
- logo: sp.logo
+ logo: sp.logo,
+ dynamic: sp.dynamic,
};
}
@@ -43,8 +45,11 @@ export async function saveStickerPack(sp: StickerPack, packsKey: string = PACKS_
const unlock = await mutex.lock();
try {
- const packs = (await DataStore.get(packsKey) ?? null) as (StickerPackMeta[] | null);
- await DataStore.set(packsKey, packs === null ? [meta] : [...packs, meta]);
+ let packs = (await DataStore.get(packsKey) ?? null) as (StickerPackMeta[] | null);
+ if (packs?.some(p => p.id === sp.id)) {
+ packs = packs.map(p => p.id === sp.id ? meta : p);
+ }
+ await DataStore.set(packsKey, packs === null ? [meta] : packs);
} finally {
unlock();
}
@@ -106,3 +111,66 @@ export async function deleteStickerPack(id: string, packsKey: string = PACKS_KEY
})()
]);
}
+
+// ---------------------------- Dynamic Packs ----------------------------
+
+export async function getDynamicStickerPack(dspm: DynamicStickerPackMeta): Promise {
+ const dsp = await fetch(dspm.dynamic.refreshUrl, {
+ headers: dspm.dynamic.authHeaders,
+ });
+ if (!dsp.ok) return null;
+ return await dsp.json();
+}
+
+export async function getDynamicPackSetMetas(dpsmKey: string = DYNAMIC_PACK_SET_METAS_KEY): Promise {
+ return (await DataStore.get(dpsmKey)) ?? null as DynamicPackSetMeta[] | null;
+}
+
+function hasDynamicPackSetMeta(dpsm: DynamicPackSetMeta, metas?: DynamicPackSetMeta[] | null): boolean {
+ return !!metas?.some(m => m.id === dpsm.id);
+}
+
+export async function fetchDynamicPackSetMeta(dpsm: DynamicPackSetMeta): Promise {
+ const dpsm_ = await fetch(dpsm.refreshUrl, {
+ headers: dpsm.authHeaders,
+ });
+ if (!dpsm_.ok) return null;
+
+ const dpsmData = await dpsm_.json();
+ return dpsmData as DynamicPackSetMeta;
+}
+
+export async function refreshDynamicPackSet(old: DynamicPackSetMeta, _new: DynamicPackSetMeta): Promise {
+ const oldPacks = old.packs.map(p => p.id);
+ const newPacks = _new.packs.map(p => p.id);
+
+ const toRemove = oldPacks.filter(p => !newPacks.includes(p));
+ const toAdd = newPacks.filter(p => !oldPacks.includes(p));
+
+ await Promise.all([
+ ...toRemove.map(id => deleteStickerPack(id)),
+ ...toAdd.map(id => getDynamicStickerPack(_new.packs.find(p => p.id === id)!).then(sp => sp && saveStickerPack(sp)))
+ ]);
+}
+
+export async function saveDynamicPackSetMeta(dpsm: DynamicPackSetMeta, dpsmKey: string = DYNAMIC_PACK_SET_METAS_KEY): Promise {
+ let metas = (await DataStore.get(dpsmKey) ?? null) as (DynamicPackSetMeta[] | null);
+ if (hasDynamicPackSetMeta(dpsm, metas)) {
+ await refreshDynamicPackSet(metas!.find(m => m.id === dpsm.id)!, dpsm);
+ metas = metas!.map(m => m.id === dpsm.id ? dpsm : m);
+ }
+
+ const unlock = await mutex.lock();
+ try {
+ await DataStore.set(dpsmKey, metas === null ? [dpsm] : metas);
+ } finally {
+ unlock();
+ }
+}
+
+export async function fetchAndRefreshDynamicPackSet(dpsm: DynamicPackSetMeta, dpsmKey: string = DYNAMIC_PACK_SET_METAS_KEY): Promise {
+ const _new = await fetchDynamicPackSetMeta(dpsm);
+ if (!_new) return;
+
+ await saveDynamicPackSetMeta(_new, dpsmKey);
+}
diff --git a/src/equicordplugins/moreStickers/types.ts b/src/equicordplugins/moreStickers/types.ts
index 1f20d052f..5d545bdf0 100644
--- a/src/equicordplugins/moreStickers/types.ts
+++ b/src/equicordplugins/moreStickers/types.ts
@@ -138,6 +138,16 @@ export interface StickerPackMeta {
url?: string;
};
logo: Sticker;
+
+ dynamic?: DynamicStickerPackMeta["dynamic"];
+}
+
+export interface DynamicStickerPackMeta extends StickerPackMeta {
+ dynamic: {
+ version?: string;
+ refreshUrl: string;
+ authHeaders?: Record;
+ };
}
export interface StickerPack extends StickerPackMeta {
@@ -148,3 +158,18 @@ export interface FFmpegState {
ffmpeg?: FFmpeg;
isLoaded: boolean;
}
+
+export interface DynamicPackSetMeta {
+ id: string;
+ version?: string;
+
+ title?: string;
+ author?: {
+ name: string;
+ url?: string;
+ };
+
+ packs: DynamicStickerPackMeta[];
+ refreshUrl: string;
+ authHeaders?: Record;
+}
diff --git a/src/equicordplugins/grammar/index.ts b/src/equicordplugins/polishWording/index.ts
similarity index 53%
rename from src/equicordplugins/grammar/index.ts
rename to src/equicordplugins/polishWording/index.ts
index c84a1fb27..98107ad4d 100644
--- a/src/equicordplugins/grammar/index.ts
+++ b/src/equicordplugins/polishWording/index.ts
@@ -4,8 +4,16 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
-import { addPreSendListener, removePreSendListener, SendListener, } from "@api/MessageEvents";
-import { definePluginSettings, Settings } from "@api/Settings";
+import {
+ addPreSendListener,
+ removePreSendListener,
+ SendListener,
+} from "@api/MessageEvents";
+import {
+ definePluginSettings,
+ migratePluginSettings,
+ Settings,
+} from "@api/Settings";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
@@ -13,18 +21,20 @@ const presendObject: SendListener = (channelId, msg) => {
msg.content = textProcessing(msg.content);
};
-const settings = definePluginSettings(
- {
- blockedWords: {
- type: OptionType.STRING,
- description: "Words that will not be capitalised",
- default: ""
- }
- });
+migratePluginSettings("PolishWording", "Grammar");
+
+const settings = definePluginSettings({
+ blockedWords: {
+ type: OptionType.STRING,
+ description: "Words that will not be capitalised",
+ default: "",
+ },
+});
export default definePlugin({
- name: "Grammar",
- description: "Tweaks your messages to make them look nicer and have better grammar",
+ name: "PolishWording",
+ description:
+ "Tweaks your messages to make them look nicer and have better grammar",
authors: [Devs.Samwich],
dependencies: ["MessageEventsAPI"],
start() {
@@ -33,7 +43,7 @@ export default definePlugin({
stop() {
removePreSendListener(presendObject);
},
- settings
+ settings,
});
function textProcessing(input: string) {
@@ -44,14 +54,18 @@ function textProcessing(input: string) {
}
function apostrophe(textInput: string): string {
- const corrected = "wasn't, can't, don't, won't, isn't, aren't, haven't, hasn't, hadn't, doesn't, didn't, shouldn't, wouldn't, couldn't, i'm, you're, he's, she's, it's, they're, that's, who's, what's, there's, here's, how's, where's, when's, why's, let's, you'll, I'll, they'll, it'll, I've, you've, we've, they've, you'd, he'd, she'd, it'd, we'd, they'd, y'all".toLowerCase();
+ const corrected =
+ "wasn't, can't, don't, won't, isn't, aren't, haven't, hasn't, hadn't, doesn't, didn't, shouldn't, wouldn't, couldn't, i'm, you're, he's, she's, it's, they're, that's, who's, what's, there's, here's, how's, where's, when's, why's, let's, you'll, I'll, they'll, it'll, I've, you've, we've, they've, you'd, he'd, she'd, it'd, we'd, they'd, y'all".toLowerCase();
const words: string[] = corrected.split(", ");
const wordsInputted = textInput.split(" ");
- wordsInputted.forEach(element => {
- words.forEach(wordelement => {
+ wordsInputted.forEach((element) => {
+ words.forEach((wordelement) => {
if (removeApostrophes(wordelement) === element.toLowerCase()) {
- wordsInputted[wordsInputted.indexOf(element)] = restoreCap(wordelement, getCapData(element));
+ wordsInputted[wordsInputted.indexOf(element)] = restoreCap(
+ wordelement,
+ getCapData(element),
+ );
}
});
});
@@ -64,7 +78,6 @@ function getCapData(str: string) {
booleanArray.push(char === char.toUpperCase());
}
return booleanArray;
-
}
function removeApostrophes(str: string): string {
@@ -90,20 +103,22 @@ function restoreCap(str: string, data: boolean[]): string {
}
function cap(textInput: string): string {
-
const sentences = textInput.split(/(?<=\w\.)\s/);
- const blockedWordsArray: string[] = Settings.plugins.Grammar.blockedWords.split(", ");
+ const blockedWordsArray: string[] =
+ Settings.plugins.PolishWording.blockedWords.split(", ");
- return sentences.map(element => {
-
- if (!blockedWordsArray.some(word => element.toLowerCase().startsWith(word.toLowerCase()))) {
- return element.charAt(0).toUpperCase() + element.slice(1);
- }
- else {
- return element;
- }
-
- }).join(" ");
+ return sentences
+ .map((element) => {
+ if (
+ !blockedWordsArray.some((word) =>
+ element.toLowerCase().startsWith(word.toLowerCase()),
+ )
+ ) {
+ return element.charAt(0).toUpperCase() + element.slice(1);
+ } else {
+ return element;
+ }
+ })
+ .join(" ");
}
-
diff --git a/src/equicordplugins/statusPresets/index.tsx b/src/equicordplugins/statusPresets/index.tsx
index 5889448d4..9936f3ba5 100644
--- a/src/equicordplugins/statusPresets/index.tsx
+++ b/src/equicordplugins/statusPresets/index.tsx
@@ -138,11 +138,12 @@ export default definePlugin({
}
},
{
- find: /"aria-label":.{0,1}\.\i\.string\(\i\.\i#{intl::STATUS_MENU_LABEL}/,
+ find: "#{intl::STATUS_MENU_LABEL}",
replacement: {
- match: /!\i&&(.{0,15}\i\.Fragment.{0,55}null==(\i).{0,200}customEmojiPlaceholder\}\),onClick:([^}]+}))/,
+ match: /!\i\i&&(.{0,20}\i\.Fragment.{0,100}null==(\i).{0,200}customEmojiPlaceholder\}\),onClick:(.*?}))/,
replace: "$self.render($2, $3),false&&$1"
- }
+ },
+ all: true
}
],
render(status: null | { emoji: Emoji | null; }, openCustomStatusModal: () => void) {
diff --git a/src/equicordplugins/viewRaw2/index.tsx b/src/equicordplugins/viewRaw2/index.tsx
deleted file mode 100644
index 4518d3b23..000000000
--- a/src/equicordplugins/viewRaw2/index.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Vencord, a Discord client mod
- * Copyright (c) 2024 Vendicated and contributors
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-
-import { NavContextMenuPatchCallback } from "@api/ContextMenu";
-import { CodeBlock } from "@components/CodeBlock";
-import ErrorBoundary from "@components/ErrorBoundary";
-import { Devs } from "@utils/constants";
-import { getIntlMessage } from "@utils/discord";
-import { Margins } from "@utils/margins";
-import { closeModal, ModalCloseButton, ModalContent, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal";
-import definePlugin from "@utils/types";
-import { Forms, Menu, Text } from "@webpack/common";
-import { Message } from "discord-types/general";
-
-type CustomMessage = Message & { editHistory?: any; deleted?: any; firstEditTimestamp?: any; };
-
-const CopyIcon = () => {
- return ;
-};
-
-function cleanMessage(msg: CustomMessage) {
- const author = { ...msg.author } as any;
- delete author.email;
- delete author.phone;
- delete author.mfaEnabled;
- delete author.personalConnectionId;
- delete msg.editHistory;
- delete msg.deleted;
- delete msg.firstEditTimestamp;
- return { ...msg, author };
-}
-
-function openViewRawModal(obj: any, type: string, isMessage?: boolean) {
- const key = openModal(props => (
-
-
-
- View Raw {type}
- closeModal(key)} />
-
-
-
- {isMessage && (
- <>
- Content
-
-
- >
- )}
-
- {type} Data
-
-
-
-
-
- ));
-}
-
-function makeContextCallback(name: string, action: (any) => void): NavContextMenuPatchCallback {
- return (children, props) => {
- if (props.label === getIntlMessage("CHANNEL_ACTIONS_MENU_LABEL")) return; // random shit like notification settings
-
- const value = props[name];
- if (!value) return;
-
- const lastChild = children.at(-1);
- if (lastChild?.key === "developer-actions") {
- const p = lastChild.props;
- if (!Array.isArray(p.children))
- p.children = [p.children];
-
- children = p.children;
- }
-
- children.push(
- action(value)}
- icon={CopyIcon}
- />
- );
- };
-}
-
-export default definePlugin({
- name: "ViewRaw2",
- description: "Copy and view the raw content/data of any message, channel or guild",
- authors: [Devs.KingFish, Devs.Ven, Devs.rad, Devs.ImLvna, Devs.Kyuuhachi],
- contextMenus: {
- "guild-context": makeContextCallback("guild", val => openViewRawModal(val, "Guild")),
- "channel-context": makeContextCallback("channel", val => openViewRawModal(val, "Channel")),
- "user-context": makeContextCallback("user", val => openViewRawModal(val, "User")),
- "message": makeContextCallback("message", val => openViewRawModal(cleanMessage(val), "Message", true)),
- }
-});
diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts
index f6bc2c8b0..bb1654c8d 100644
--- a/src/plugins/crashHandler/index.ts
+++ b/src/plugins/crashHandler/index.ts
@@ -107,7 +107,7 @@ export default definePlugin({
try {
if (!hasCrashedOnce) {
hasCrashedOnce = true;
- maybePromptToUpdate("Uh oh, Discord has just crashed... but good news, there is a Vencord update available that might fix this issue! Would you like to update now?", true);
+ maybePromptToUpdate("Uh oh, Discord has just crashed... but good news, there is a Equicord update available that might fix this issue! Would you like to update now?", true);
}
} catch { }
diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx
index f5596f391..57a39540d 100644
--- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx
+++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx
@@ -20,7 +20,7 @@ import { AvatarDecorationModalPreview } from "../components";
const FileUpload = findComponentByCodeLazy("fileUploadInput,");
const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE=3]="POSITIVE', {
- HelpMessageTypes: filters.byProps("POSITIVE", "WARNING"),
+ HelpMessageTypes: filters.byProps("POSITIVE", "WARNING", "INFO"),
HelpMessage: filters.byCode(".iconDiv")
});
@@ -119,8 +119,8 @@ function CreateDecorationModal(props: ModalProps) {
/>
-
-
You can receive updates on your decoration's review by joining
+ To receive updates on your decoration's review, join {
e.preventDefault();
@@ -138,8 +138,8 @@ function CreateDecorationModal(props: ModalProps) {
}}
>
Decor's Discord server
- .
-
+ and allow direct messages.
+
diff --git a/src/plugins/pictureInPicture/index.tsx b/src/plugins/pictureInPicture/index.tsx
index 20cedf45b..ef3d35ff1 100644
--- a/src/plugins/pictureInPicture/index.tsx
+++ b/src/plugins/pictureInPicture/index.tsx
@@ -30,10 +30,10 @@ export default definePlugin({
{
find: ".removeMosaicItemHoverButton),",
replacement: {
- match: /\.nonMediaMosaicItem\]:!(\i).{0,50}?children:\[\S,(\S)/,
- replace: "$&,$1&&$2&&$self.renderPiPButton(),"
- },
- },
+ match: /\.nonMediaMosaicItem\]:.{0,40}children:\[(?<=showDownload:(\i).+?isVisualMediaType:(\i).+?)/,
+ replace: "$&$1&&$2&&$self.renderPiPButton(),"
+ }
+ }
],
renderPiPButton: ErrorBoundary.wrap(() => {
diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx
index 204bc0be3..055c39874 100644
--- a/src/plugins/roleColorEverywhere/index.tsx
+++ b/src/plugins/roleColorEverywhere/index.tsx
@@ -20,6 +20,7 @@ import { definePluginSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { makeRange } from "@components/PluginSettings/components";
import { Devs } from "@utils/constants";
+import { Logger } from "@utils/Logger";
import definePlugin, { OptionType } from "@utils/types";
import { findByCodeLazy } from "@webpack";
import { ChannelStore, GuildMemberStore, GuildStore } from "@webpack/common";
@@ -51,6 +52,12 @@ const settings = definePluginSettings({
description: "Show role colors in the reactors list",
restartNeeded: true
},
+ pollResults: {
+ type: OptionType.BOOLEAN,
+ default: true,
+ description: "Show role colors in the poll results",
+ restartNeeded: true
+ },
colorChatMessages: {
type: OptionType.BOOLEAN,
default: false,
@@ -62,14 +69,15 @@ const settings = definePluginSettings({
description: "Intensity of message coloring.",
markers: makeRange(0, 100, 10),
default: 30
- },
+ }
});
-
export default definePlugin({
name: "RoleColorEverywhere",
- authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN, Devs.Kyuuhachi],
+ authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN, Devs.Kyuuhachi, Devs.jamesbt365],
description: "Adds the top role color anywhere possible",
+ settings,
+
patches: [
// Chat Mentions
{
@@ -77,100 +85,106 @@ export default definePlugin({
replacement: [
{
match: /onContextMenu:\i,color:\i,\.\.\.\i(?=,children:)(?<=user:(\i),channel:(\i).{0,500}?)/,
- replace: "$&,color:$self.getUserColor($1?.id,{channelId:$2?.id})"
+ replace: "$&,color:$self.getColorInt($1?.id,$2?.id)"
}
],
- predicate: () => settings.store.chatMentions,
+ predicate: () => settings.store.chatMentions
},
// Slate
{
find: ".userTooltip,children",
replacement: [
{
- match: /let\{id:(\i),guildId:(\i)[^}]*\}.*?\.\i,{(?=children)/,
- replace: "$&color:$self.getUserColor($1,{guildId:$2}),"
+ match: /let\{id:(\i),guildId:\i,channelId:(\i)[^}]*\}.*?\.\i,{(?=children)/,
+ replace: "$&color:$self.getColorInt($1,$2),"
}
],
- predicate: () => settings.store.chatMentions,
+ predicate: () => settings.store.chatMentions
},
+ // Member List Role Headers
{
find: 'tutorialId:"whos-online',
replacement: [
{
match: /null,\i," — ",\i\]/,
- replace: "null,$self.roleGroupColor(arguments[0])]"
+ replace: "null,$self.RoleGroupColor(arguments[0])]"
},
],
- predicate: () => settings.store.memberList,
+ predicate: () => settings.store.memberList
},
{
find: "#{intl::THREAD_BROWSER_PRIVATE}",
replacement: [
{
match: /children:\[\i," — ",\i\]/,
- replace: "children:[$self.roleGroupColor(arguments[0])]"
+ replace: "children:[$self.RoleGroupColor(arguments[0])]"
},
],
- predicate: () => settings.store.memberList,
+ predicate: () => settings.store.memberList
},
+ // Voice Users
{
- find: "renderPrioritySpeaker",
+ find: "renderPrioritySpeaker(){",
replacement: [
{
match: /renderName\(\){.+?usernameSpeaking\]:.+?(?=children)/,
- replace: "$&...$self.getVoiceProps(this.props),"
+ replace: "$&style:$self.getColorStyle(this?.props?.user?.id,this?.props?.guildId),"
}
],
- predicate: () => settings.store.voiceUsers,
+ predicate: () => settings.store.voiceUsers
},
+ // Reaction List
{
find: ".reactorDefault",
replacement: {
- match: /,onContextMenu:e=>.{0,15}\((\i),(\i),(\i)\).{0,250}tag:"strong"/,
- replace: "$&,style:{color:$self.getColor($2?.id,$1)}"
+ match: /,onContextMenu:\i=>.{0,15}\((\i),(\i),(\i)\).{0,250}tag:"strong"/,
+ replace: "$&,style:$self.getColorStyle($2?.id,$1?.channel?.id)"
},
predicate: () => settings.store.reactorsList,
},
+ // Poll Results
+ {
+ find: ",reactionVoteCounts",
+ replacement: {
+ match: /\.nickname,(?=children:)/,
+ replace: "$&style:$self.getColorStyle(arguments[0]?.user?.id,arguments[0]?.channel?.id),"
+ },
+ predicate: () => settings.store.pollResults
+ },
+ // Messages
{
find: "#{intl::MESSAGE_EDITED}",
replacement: {
match: /(?<=isUnsupported\]:(\i)\.isUnsupported\}\),)(?=children:\[)/,
- replace: "style:{color:$self.useMessageColor($1)},"
+ replace: "style:$self.useMessageColorStyle($1),"
},
- predicate: () => settings.store.colorChatMessages,
- },
+ predicate: () => settings.store.colorChatMessages
+ }
],
- settings,
- getColor(userId: string, { channelId, guildId }: { channelId?: string; guildId?: string; }) {
- if (!(guildId ??= ChannelStore.getChannel(channelId!)?.guild_id)) return null;
- return GuildMemberStore.getMember(guildId, userId)?.colorString ?? null;
+ getColorString(userId: string, channelOrGuildId: string) {
+ try {
+ const guildId = ChannelStore.getChannel(channelOrGuildId)?.guild_id ?? GuildStore.getGuild(channelOrGuildId)?.id;
+ if (guildId == null) return null;
+
+ return GuildMemberStore.getMember(guildId, userId)?.colorString ?? null;
+ } catch (e) {
+ new Logger("RoleColorEverywhere").error("Failed to get color string", e);
+ }
+
+ return null;
},
- getUserColor(userId: string, ids: { channelId?: string; guildId?: string; }) {
- const colorString = this.getColor(userId, ids);
+ getColorInt(userId: string, channelOrGuildId: string) {
+ const colorString = this.getColorString(userId, channelOrGuildId);
return colorString && parseInt(colorString.slice(1), 16);
},
- roleGroupColor: ErrorBoundary.wrap(({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) => {
- const role = GuildStore.getRole(guildId, id);
+ getColorStyle(userId: string, channelOrGuildId: string) {
+ const colorString = this.getColorString(userId, channelOrGuildId);
- return (
-
- {title ?? label} — {count}
-
- );
- }, { noop: true }),
-
- getVoiceProps({ user: { id: userId }, guildId }: { user: { id: string; }; guildId: string; }) {
- return {
- style: {
- color: this.getColor(userId, { guildId })
- }
+ return colorString && {
+ color: colorString
};
},
@@ -178,11 +192,36 @@ export default definePlugin({
try {
const { messageSaturation } = settings.use(["messageSaturation"]);
const author = useMessageAuthor(message);
- if (author.colorString !== undefined && messageSaturation !== 0)
+
+ if (author.colorString != null && messageSaturation !== 0) {
return `color-mix(in oklab, ${author.colorString} ${messageSaturation}%, var(--text-normal))`;
+ }
} catch (e) {
- console.error("[RCE] failed to get message color", e);
+ new Logger("RoleColorEverywhere").error("Failed to get message color", e);
}
- return undefined;
+
+ return null;
},
+
+ useMessageColorStyle(message: any) {
+ const color = this.useMessageColor(message);
+
+ return color && {
+ color
+ };
+ },
+
+ RoleGroupColor: ErrorBoundary.wrap(({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) => {
+ const role = GuildStore.getRole(guildId, id);
+
+ return role != null && (
+
+ {title ?? label} — {count}
+
+ );
+ }, { noop: true })
});
diff --git a/src/plugins/shikiCodeblocks.desktop/api/themes.ts b/src/plugins/shikiCodeblocks.desktop/api/themes.ts
index f31ce60b3..bc1dd184d 100644
--- a/src/plugins/shikiCodeblocks.desktop/api/themes.ts
+++ b/src/plugins/shikiCodeblocks.desktop/api/themes.ts
@@ -1,6 +1,6 @@
/*
* Vencord, a modification for Discord's desktop app
- * Copyright (c) 2022 Vendicated and contributors
+ * Copyright (c) 2024 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,9 +18,9 @@
import { IShikiTheme } from "@vap/shiki";
-export const SHIKI_REPO = "shikijs/shiki";
-export const SHIKI_REPO_COMMIT = "0b28ad8ccfbf2615f2d9d38ea8255416b8ac3043";
-export const shikiRepoTheme = (name: string) => `https://raw.githubusercontent.com/${SHIKI_REPO}/${SHIKI_REPO_COMMIT}/packages/shiki/themes/${name}.json`;
+export const SHIKI_REPO = "shikijs/textmate-grammars-themes";
+export const SHIKI_REPO_COMMIT = "2d87559c7601a928b9f7e0f0dda243d2fb6d4499";
+export const shikiRepoTheme = (name: string) => `https://raw.githubusercontent.com/${SHIKI_REPO}/${SHIKI_REPO_COMMIT}/packages/tm-themes/themes/${name}.json`;
export const themes = {
// Default
@@ -30,33 +30,59 @@ export const themes = {
MaterialCandy: "https://raw.githubusercontent.com/millsp/material-candy/master/material-candy.json",
// More from Shiki repo
+ Andromeeda: shikiRepoTheme("andromeeda"),
+ AuroraX: shikiRepoTheme("aurora-x"),
+ AyuDark: shikiRepoTheme("ayu-dark"),
+ CatppuccinLatte: shikiRepoTheme("catppuccin-latte"),
+ CatppuccinFrappe: shikiRepoTheme("catppuccin-frappe"),
+ CatppuccinMacchiato: shikiRepoTheme("catppuccin-macchiato"),
+ CatppuccinMocha: shikiRepoTheme("catppuccin-mocha"),
DraculaSoft: shikiRepoTheme("dracula-soft"),
Dracula: shikiRepoTheme("dracula"),
+ EverforestDark: shikiRepoTheme("everforest-dark"),
+ EverforestLight: shikiRepoTheme("everforest-light"),
+ GithubDarkDefault: shikiRepoTheme("github-dark-default"),
GithubDarkDimmed: shikiRepoTheme("github-dark-dimmed"),
+ GithubDarkHighContrast: shikiRepoTheme("github-dark-high-contrast"),
GithubDark: shikiRepoTheme("github-dark"),
+ GithubLightDefault: shikiRepoTheme("github-light-default"),
+ GithubLightHighContrast: shikiRepoTheme("github-light-high-contrast"),
GithubLight: shikiRepoTheme("github-light"),
+ Houston: shikiRepoTheme("houston"),
+ KanagawaDragon: shikiRepoTheme("kanagawa-dragon"),
+ KanagawaLotus: shikiRepoTheme("kanagawa-lotus"),
+ KanagawaWave: shikiRepoTheme("kanagawa-wave"),
+ LaserWave: shikiRepoTheme("laserwave"),
LightPlus: shikiRepoTheme("light-plus"),
- MaterialDarker: shikiRepoTheme("material-darker"),
- MaterialDefault: shikiRepoTheme("material-default"),
- MaterialLighter: shikiRepoTheme("material-lighter"),
- MaterialOcean: shikiRepoTheme("material-ocean"),
- MaterialPalenight: shikiRepoTheme("material-palenight"),
+ MaterialDarker: shikiRepoTheme("material-theme-darker"),
+ MaterialDefault: shikiRepoTheme("material-theme"),
+ MaterialLighter: shikiRepoTheme("material-theme-lighter"),
+ MaterialOcean: shikiRepoTheme("material-theme-ocean"),
+ MaterialPalenight: shikiRepoTheme("material-theme-palenight"),
MinDark: shikiRepoTheme("min-dark"),
MinLight: shikiRepoTheme("min-light"),
Monokai: shikiRepoTheme("monokai"),
+ NightOwl: shikiRepoTheme("night-owl"),
Nord: shikiRepoTheme("nord"),
OneDarkPro: shikiRepoTheme("one-dark-pro"),
+ OneLight: shikiRepoTheme("one-light"),
+ Plastic: shikiRepoTheme("plastic"),
Poimandres: shikiRepoTheme("poimandres"),
+ Red: shikiRepoTheme("red"),
RosePineDawn: shikiRepoTheme("rose-pine-dawn"),
RosePineMoon: shikiRepoTheme("rose-pine-moon"),
RosePine: shikiRepoTheme("rose-pine"),
SlackDark: shikiRepoTheme("slack-dark"),
SlackOchin: shikiRepoTheme("slack-ochin"),
+ SnazzyLight: shikiRepoTheme("snazzy-light"),
SolarizedDark: shikiRepoTheme("solarized-dark"),
SolarizedLight: shikiRepoTheme("solarized-light"),
+ Synthwave84: shikiRepoTheme("synthwave-84"),
+ TokyoNight: shikiRepoTheme("tokyo-night"),
+ Vesper: shikiRepoTheme("vesper"),
+ VitesseBlack: shikiRepoTheme("vitesse-black"),
VitesseDark: shikiRepoTheme("vitesse-dark"),
VitesseLight: shikiRepoTheme("vitesse-light"),
- CssVariables: shikiRepoTheme("css-variables"),
};
export const themeCache = new Map();
diff --git a/src/plugins/viewRaw/index.tsx b/src/plugins/viewRaw/index.tsx
index 0134ea3e3..8ee1ca8d7 100644
--- a/src/plugins/viewRaw/index.tsx
+++ b/src/plugins/viewRaw/index.tsx
@@ -155,6 +155,7 @@ export default definePlugin({
"guild-context": MakeContextCallback("Guild"),
"channel-context": MakeContextCallback("Channel"),
"thread-context": MakeContextCallback("Channel"),
+ "gdm-context": MakeContextCallback("Channel"),
"user-context": MakeContextCallback("User")
},
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 7f2792310..851b58100 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -525,7 +525,7 @@ export const Devs = /* #__PURE__*/ Object.freeze({
id: 721717126523781240n
},
nyx: {
- name: "verticalsync",
+ name: "verticalsync.",
id: 1207087393929171095n
},
nekohaxx: {
@@ -584,6 +584,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "SomeAspy",
id: 516750892372852754n
},
+ jamesbt365: {
+ name: "jamesbt365",
+ id: 158567567487795200n,
+ },
} satisfies Record);
export const EquicordDevs = Object.freeze({