mirror of
https://github.com/Equicord/Equicord.git
synced 2025-02-20 15:18:50 -05:00
Merge branch 'dev'
This commit is contained in:
commit
ad5b8c85b8
20 changed files with 499 additions and 245 deletions
|
@ -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
|
||||
|
|
|
@ -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]>();
|
||||
|
|
150
src/equicordplugins/ViewRawVariant/index.tsx
Normal file
150
src/equicordplugins/ViewRawVariant/index.tsx
Normal file
|
@ -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 (
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
aria-hidden="true"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<path d="M12.9297 3.25007C12.7343 3.05261 12.4154 3.05226 12.2196 3.24928L11.5746 3.89824C11.3811 4.09297 11.3808 4.40733 11.5739 4.60245L16.5685 9.64824C16.7614 9.84309 16.7614 10.1569 16.5685 10.3517L11.5739 15.3975C11.3808 15.5927 11.3811 15.907 11.5746 16.1017L12.2196 16.7507C12.4154 16.9477 12.7343 16.9474 12.9297 16.7499L19.2604 10.3517C19.4532 10.1568 19.4532 9.84314 19.2604 9.64832L12.9297 3.25007Z" />
|
||||
<path d="M8.42616 4.60245C8.6193 4.40733 8.61898 4.09297 8.42545 3.89824L7.78047 3.24928C7.58466 3.05226 7.26578 3.05261 7.07041 3.25007L0.739669 9.64832C0.5469 9.84314 0.546901 10.1568 0.739669 10.3517L7.07041 16.7499C7.26578 16.9474 7.58465 16.9477 7.78047 16.7507L8.42545 16.1017C8.61898 15.907 8.6193 15.5927 8.42616 15.3975L3.43155 10.3517C3.23869 10.1569 3.23869 9.84309 3.43155 9.64824L8.42616 4.60245Z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
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) => (
|
||||
<ErrorBoundary>
|
||||
<ModalRoot {...props} size={ModalSize.LARGE}>
|
||||
<ModalHeader>
|
||||
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>
|
||||
View Raw {type}
|
||||
</Text>
|
||||
<ModalCloseButton onClick={() => closeModal(key)} />
|
||||
</ModalHeader>
|
||||
<ModalContent>
|
||||
<div style={{ padding: "16px 0" }}>
|
||||
{isMessage && (
|
||||
<>
|
||||
<Forms.FormTitle tag="h5">
|
||||
Content
|
||||
</Forms.FormTitle>
|
||||
<CodeBlock
|
||||
content={obj.content}
|
||||
lang="markdown"
|
||||
/>
|
||||
<Forms.FormDivider
|
||||
className={Margins.bottom20}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Forms.FormTitle tag="h5">{type} Data</Forms.FormTitle>
|
||||
<CodeBlock
|
||||
content={JSON.stringify(obj, null, 4)}
|
||||
lang="json"
|
||||
/>
|
||||
</div>
|
||||
</ModalContent>
|
||||
</ModalRoot>
|
||||
</ErrorBoundary>
|
||||
));
|
||||
}
|
||||
|
||||
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(
|
||||
<Menu.MenuItem
|
||||
id={`c98-view-${name}-raw`}
|
||||
label="View Raw"
|
||||
action={() => 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),
|
||||
),
|
||||
},
|
||||
});
|
|
@ -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"],
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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<string>("");
|
||||
const [tab, setTab] = React.useState<SettingsTabsKey>(SettingsTabsKey.ADD_STICKER_PACK_URL);
|
||||
const [hoveredStickerPackId, setHoveredStickerPackId] = React.useState<string | null>(null);
|
||||
const [_isV1, setV1] = React.useState<boolean>(false);
|
||||
|
||||
async function refreshStickerPackMetas() {
|
||||
setstickerPackMetas(await getStickerPackMetas());
|
||||
|
@ -99,6 +100,9 @@ export const Settings = () => {
|
|||
React.useEffect(() => {
|
||||
refreshStickerPackMetas();
|
||||
}, []);
|
||||
React.useEffect(() => {
|
||||
isV1().then(setV1);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={cl("settings")}>
|
||||
|
@ -365,7 +369,7 @@ export const Settings = () => {
|
|||
|
||||
<Flex flexDirection="row" style={{
|
||||
alignItems: "center",
|
||||
justifyContent: "center"
|
||||
justifyContent: "start"
|
||||
}} >
|
||||
<Button
|
||||
size={Button.Sizes.SMALL}
|
||||
|
@ -399,6 +403,9 @@ export const Settings = () => {
|
|||
onClick={async e => {
|
||||
await migrate();
|
||||
}}
|
||||
style={{
|
||||
display: _isV1 ? "unset" : "none"
|
||||
}}
|
||||
>Migrate from v1</Button>
|
||||
</Flex>
|
||||
</div>
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<StickerPack | null> {
|
||||
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<DynamicPackSetMeta[] | null> {
|
||||
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<DynamicPackSetMeta | null> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
const _new = await fetchDynamicPackSetMeta(dpsm);
|
||||
if (!_new) return;
|
||||
|
||||
await saveDynamicPackSetMeta(_new, dpsmKey);
|
||||
}
|
||||
|
|
|
@ -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<string, string>;
|
||||
};
|
||||
}
|
||||
|
||||
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<string, string>;
|
||||
}
|
||||
|
|
|
@ -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(" ");
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
@ -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 <svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" width="18" height="18">
|
||||
<path d="M12.9297 3.25007C12.7343 3.05261 12.4154 3.05226 12.2196 3.24928L11.5746 3.89824C11.3811 4.09297 11.3808 4.40733 11.5739 4.60245L16.5685 9.64824C16.7614 9.84309 16.7614 10.1569 16.5685 10.3517L11.5739 15.3975C11.3808 15.5927 11.3811 15.907 11.5746 16.1017L12.2196 16.7507C12.4154 16.9477 12.7343 16.9474 12.9297 16.7499L19.2604 10.3517C19.4532 10.1568 19.4532 9.84314 19.2604 9.64832L12.9297 3.25007Z" />
|
||||
<path d="M8.42616 4.60245C8.6193 4.40733 8.61898 4.09297 8.42545 3.89824L7.78047 3.24928C7.58466 3.05226 7.26578 3.05261 7.07041 3.25007L0.739669 9.64832C0.5469 9.84314 0.546901 10.1568 0.739669 10.3517L7.07041 16.7499C7.26578 16.9474 7.58465 16.9477 7.78047 16.7507L8.42545 16.1017C8.61898 15.907 8.6193 15.5927 8.42616 15.3975L3.43155 10.3517C3.23869 10.1569 3.23869 9.84309 3.43155 9.64824L8.42616 4.60245Z" />
|
||||
</svg>;
|
||||
};
|
||||
|
||||
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 => (
|
||||
<ErrorBoundary>
|
||||
<ModalRoot {...props} size={ModalSize.LARGE}>
|
||||
<ModalHeader>
|
||||
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>View Raw {type}</Text>
|
||||
<ModalCloseButton onClick={() => closeModal(key)} />
|
||||
</ModalHeader>
|
||||
<ModalContent>
|
||||
<div style={{ padding: "16px 0" }}>
|
||||
{isMessage && (
|
||||
<>
|
||||
<Forms.FormTitle tag="h5">Content</Forms.FormTitle>
|
||||
<CodeBlock content={obj.content} lang="markdown" />
|
||||
<Forms.FormDivider className={Margins.bottom20} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<Forms.FormTitle tag="h5">{type} Data</Forms.FormTitle>
|
||||
<CodeBlock content={JSON.stringify(obj, null, 4)} lang="json" />
|
||||
</div>
|
||||
</ModalContent >
|
||||
</ModalRoot >
|
||||
</ErrorBoundary >
|
||||
));
|
||||
}
|
||||
|
||||
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(
|
||||
<Menu.MenuItem
|
||||
id={`c98-view-${name}-raw`}
|
||||
label="View Raw"
|
||||
action={() => 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)),
|
||||
}
|
||||
});
|
|
@ -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 { }
|
||||
|
||||
|
|
|
@ -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) {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Forms.FormText type="description" className={Margins.bottom16}>
|
||||
<br />You can receive updates on your decoration's review by joining <Link
|
||||
<HelpMessage messageType={HelpMessageTypes.INFO}>
|
||||
To receive updates on your decoration's review, join <Link
|
||||
href={`https://discord.gg/${INVITE_KEY}`}
|
||||
onClick={async e => {
|
||||
e.preventDefault();
|
||||
|
@ -138,8 +138,8 @@ function CreateDecorationModal(props: ModalProps) {
|
|||
}}
|
||||
>
|
||||
Decor's Discord server
|
||||
</Link>.
|
||||
</Forms.FormText>
|
||||
</Link> and allow direct messages.
|
||||
</HelpMessage>
|
||||
</ErrorBoundary>
|
||||
</ModalContent>
|
||||
<ModalFooter className={cl("modal-footer")}>
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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 (
|
||||
<span style={{
|
||||
color: role?.colorString,
|
||||
fontWeight: "unset",
|
||||
letterSpacing: ".05em"
|
||||
}}>
|
||||
{title ?? label} — {count}
|
||||
</span>
|
||||
);
|
||||
}, { 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 && (
|
||||
<span style={{
|
||||
color: role.colorString,
|
||||
fontWeight: "unset",
|
||||
letterSpacing: ".05em"
|
||||
}}>
|
||||
{title ?? label} — {count}
|
||||
</span>
|
||||
);
|
||||
}, { noop: true })
|
||||
});
|
||||
|
|
|
@ -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<string, IShikiTheme>();
|
||||
|
|
|
@ -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")
|
||||
},
|
||||
|
||||
|
|
|
@ -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<string, Dev>);
|
||||
|
||||
export const EquicordDevs = Object.freeze({
|
||||
|
|
Loading…
Add table
Reference in a new issue