This commit is contained in:
Manti 2022-11-25 11:01:33 +03:00
commit 7f65345d3e
16 changed files with 742 additions and 17 deletions

View file

@ -1,3 +1,6 @@
> **Warning**
> These instructions are only for advanced users. If you're not a Developer, you should use our [graphical installer](https://github.com/Vendicated/VencordInstaller#usage) instead.
# Installation Guide
Welcome to Megu's Installation Guide! In this file, you will learn about how to download, install, and uninstall Vencord!

View file

@ -214,7 +214,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
size={Button.Sizes.SMALL}
color={Button.Colors.RED}
>
Exit Without Saving
Cancel
</Button>
<Tooltip text="You must fix all errors before saving" shouldShow={!canSubmit()}>
{({ onMouseEnter, onMouseLeave }) => (
@ -226,7 +226,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
onMouseLeave={onMouseLeave}
disabled={!canSubmit()}
>
Save & Exit
Save & Close
</Button>
)}
</Tooltip>

View file

@ -0,0 +1,61 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Settings } from "../api/settings";
import { Devs } from "../utils/constants";
import { makeLazy } from "../utils/misc";
import definePlugin, { OptionType } from "../utils/types";
export default definePlugin({
name: "BetterNotesBox",
description: "Hide notes or disable spellcheck (Configure in settings!!)",
authors: [Devs.Ven],
patches: [
{
find: "hideNote:",
all: true,
predicate: makeLazy(() => Vencord.Settings.plugins.BetterNotesBox.hide),
replacement: {
match: /hideNote:.+?(?=[,}])/g,
replace: "hideNote:true",
}
}, {
find: "Messages.NOTE_PLACEHOLDER",
replacement: {
match: /\.NOTE_PLACEHOLDER,/,
replace: "$&spellCheck:!Vencord.Settings.plugins.BetterNotesBox.noSpellCheck,"
}
}
],
options: {
hide: {
type: OptionType.BOOLEAN,
description: "Hide notes",
default: false,
restartNeeded: true
},
noSpellCheck: {
type: OptionType.BOOLEAN,
description: "Disable spellcheck in notes",
disabled: () => Settings.plugins.BetterNotesBox.hide,
default: false
}
}
});

View file

@ -0,0 +1,124 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Message } from "discord-types/general";
import { get, set } from "../api/DataStore";
import { Devs } from "../utils/constants";
import Logger from "../utils/Logger";
import definePlugin from "../utils/types";
import { ChannelStore, FluxDispatcher } from "../webpack/common";
let style: HTMLStyleElement;
const KEY = "HideAttachments_HiddenIds";
const ImageVisible = () => (
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M5 21q-.825 0-1.413-.587Q3 19.825 3 19V5q0-.825.587-1.413Q4.175 3 5 3h14q.825 0 1.413.587Q21 4.175 21 5v14q0 .825-.587 1.413Q19.825 21 19 21Zm0-2h14V5H5v14Zm1-2h12l-3.75-5-3 4L9 13Zm-1 2V5v14Z" />
</svg>
);
const ImageInvisible = () => (
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="m21 18.15-2-2V5H7.85l-2-2H19q.825 0 1.413.587Q21 4.175 21 5Zm-1.2 4.45L18.2 21H5q-.825 0-1.413-.587Q3 19.825 3 19V5.8L1.4 4.2l1.4-1.4 18.4 18.4ZM6 17l3-4 2.25 3 .825-1.1L5 7.825V19h11.175l-2-2Zm7.425-6.425ZM10.6 13.4Z" />
</svg>
);
let hiddenMessages: Set<string> = new Set();
const getHiddenMessages = () => get(KEY).then(set => {
hiddenMessages = set ?? new Set<string>();
return hiddenMessages;
});
const saveHiddenMessages = (ids: Set<string>) => set(KEY, ids);
export default definePlugin({
name: "HideAttachments",
description: "Hide attachments and Embeds for individual messages via hover button",
authors: [Devs.Ven],
patches: [{
find: "Messages.MESSAGE_UTILITIES_A11Y_LABEL",
replacement: {
match: /(message:(.).{0,100}Fragment,\{children:\[)(.{0,40}renderPopout:.{0,200}message_reaction_emoji_picker.+?return (.{1,3})\(.{0,30}"add-reaction")/,
replace: "$1Vencord.Plugins.plugins.HideAttachments.renderButton($2, $4),$3"
}
}],
async start() {
style = document.createElement("style");
style.id = "VencordHideAttachments";
document.head.appendChild(style);
await getHiddenMessages();
await this.buildCss();
},
stop() {
style.remove();
hiddenMessages.clear();
},
async buildCss() {
const elements = [...hiddenMessages].map(id => `#message-accessories-${id}`).join(",");
style.textContent = `
:is(${elements}) [class*="embedWrapper"] {
/* important is not necessary, but add it to make sure bad themes won't break it */
display: none !important;
}
:is(${elements})::after {
content: "Attachments hidden";
color: var(--text-muted);
font-size: 80%;
}
`;
},
renderButton(msg: Message, makeItem: (data: any) => React.ComponentType) {
try {
if (!msg.attachments.length && !msg.embeds.length) return null;
const isHidden = hiddenMessages.has(msg.id);
return makeItem({
key: "HideAttachments",
label: isHidden ? "Show Attachments" : "Hide Attachments",
icon: isHidden ? ImageVisible : ImageInvisible,
message: msg,
channel: ChannelStore.getChannel(msg.channel_id),
onClick: () => this.toggleHide(msg)
});
} catch (err) {
new Logger("HideAttachments").error(err);
return null;
}
},
async toggleHide(message: Message) {
const ids = await getHiddenMessages();
if (!ids.delete(message.id))
ids.add(message.id);
await saveHiddenMessages(ids);
await this.buildCss();
// update is necessary to rerender the PopOver
FluxDispatcher.dispatch({
type: "MESSAGE_UPDATE",
message
});
}
});

View file

@ -47,6 +47,15 @@ export default definePlugin({
match: /,(.{1,2})\.execute\((.{1,2}),(.{1,2})\)]/,
replace: (_, cmd, args, ctx) => `,Vencord.Api.Commands._handleCommand(${cmd}, ${args}, ${ctx})]`
}
},
// Show plugin name instead of "Built-In"
{
find: "().source,children",
replacement: {
// ...children: p?.name
match: /(?<=:(.{1,3})\.displayDescription\}.{0,200}\(\)\.source,children:)[^}]+/,
replace: "$1.plugin||($&)"
}
}
],
});

80
src/plugins/dictionary.ts Normal file
View file

@ -0,0 +1,80 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { ApplicationCommandOptionType, sendBotMessage } from "../api/Commands";
import { ApplicationCommandInputType } from "../api/Commands/types";
import { Devs } from "../utils/constants";
import definePlugin from "../utils/types";
export default definePlugin({
name: "UrbanDictionary",
description: "Searches for a word on Urban Dictionary",
authors: [Devs.jewdev],
dependencies: ["CommandsAPI"],
commands: [
{
name: "urban",
description: "Returns the definition of a word from Urban Dictionary",
inputType: ApplicationCommandInputType.BUILT_IN,
options: [
{
type: ApplicationCommandOptionType.STRING,
name: "word",
description: "The word to search for on Urban Dictionary",
required: true
}
],
execute: async (args, ctx) => {
try {
const { list: [definition] } = await (await fetch(`https://api.urbandictionary.com/v0/define?term=${args[0].value}`)).json();
if (!definition)
return void sendBotMessage(ctx.channel.id, { content: "No results found." });
const linkify = text => text.replace(/\[(.+?)\]/g, (_, word) => `[${word}](https://www.urbandictionary.com/define.php?term=${encodeURIComponent(word)})`);
return void sendBotMessage(ctx.channel.id, {
embeds: [
{
type: "rich",
author: {
name: `Definition of ${definition.word}`,
url: definition.permalink
},
description: linkify(definition.definition),
fields: [
{
name: "Example",
value: linkify(definition.example)
}
],
color: 0xFF9900,
footer: { text: `👍 ${definition.thumbs_up.toString()} | 👎 ${definition.thumbs_down.toString()} | Uploaded by ${definition.author}`, icon_url: "https://www.urbandictionary.com/favicon.ico" },
timestamp: new Date(definition.written_on).toISOString()
}
] as any
});
} catch (error) {
return void sendBotMessage(ctx.channel.id, {
content: `Something went wrong: \`${error}\``
});
}
}
}
]
});

View file

@ -0,0 +1,99 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { DataStore } from "../api";
import { Devs } from "../utils/constants";
import definePlugin from "../utils/types";
import { ChannelStore, FluxDispatcher, NavigationRouter, SelectedChannelStore, SelectedGuildStore } from "../webpack/common";
export interface LogoutEvent {
type: "LOGOUT";
isSwitchingAccount: boolean;
}
interface ChannelSelectEvent {
type: "CHANNEL_SELECT";
channelId: string | null;
guildId: string | null;
}
interface PreviousChannel {
guildId: string | null;
channelId: string | null;
}
export default definePlugin({
name: "KeepCurrentChannel",
description: "Attempt to navigate the channel you were in before switching accounts or loading Discord.",
authors: [Devs.Nuckyz],
isSwitchingAccount: false,
previousCache: {} as PreviousChannel,
attemptToNavigateToChannel(guildId: string | null, channelId: string) {
if (!ChannelStore.hasChannel(channelId)) return;
NavigationRouter.transitionTo(`/channels/${guildId ?? "@me"}/${channelId}`);
},
onLogout(e: LogoutEvent) {
this.isSwitchingAccount = e.isSwitchingAccount;
},
onConnectionOpen() {
if (!this.isSwitchingAccount) return;
this.isSwitchingAccount = false;
if (this.previousCache.channelId) this.attemptToNavigateToChannel(this.previousCache.guildId, this.previousCache.channelId);
},
async onChannelSelect({ guildId, channelId }: ChannelSelectEvent) {
if (this.isSwitchingAccount) return;
this.previousCache = {
guildId,
channelId
};
await DataStore.set("KeepCurrentChannel_previousData", this.previousCache);
},
async start() {
const previousData = await DataStore.get<PreviousChannel>("KeepCurrentChannel_previousData");
if (previousData) {
this.previousCache = previousData;
if (this.previousCache.channelId) this.attemptToNavigateToChannel(this.previousCache.guildId, this.previousCache.channelId);
} else {
this.previousCache = {
guildId: SelectedGuildStore.getGuildId(),
channelId: SelectedChannelStore.getChannelId() ?? null
};
await DataStore.set("KeepCurrentChannel_previousData", this.previousCache);
}
FluxDispatcher.subscribe("LOGOUT", this.onLogout.bind(this));
FluxDispatcher.subscribe("CONNECTION_OPEN", this.onConnectionOpen.bind(this));
FluxDispatcher.subscribe("CHANNEL_SELECT", this.onChannelSelect.bind(this));
},
stop() {
FluxDispatcher.unsubscribe("LOGOUT", this.onLogout);
FluxDispatcher.unsubscribe("CONNECTION_OPEN", this.onConnectionOpen);
FluxDispatcher.unsubscribe("CHANNEL_SELECT", this.onChannelSelect);
}
});

View file

@ -41,13 +41,28 @@ const quotes = [
"mdmt",
"Wdn`khc+(oxbeof",
'Ig"zkp*\'g{*xolglj`&~g|*gowg/$mgt(Eclm`.#ticf{l*xed"wl`&Kangj igbhqn\'d`dn `v#lqrw{3%$bhv-h|)kangj_imwhlhb',
"Tscmw%Tnoa~x"
"Tscmw%Tnoa~x",
"If#npus(ec`e!vl$lhsm{`ncu\"ekw&f(defeov-$Rnf|)sdupf$wcam{ceg!vl$du'D`d~x-\"jw%oi(okht-\"DJP)Kags,!mq$du'A|n sg`akrkq)~jkdl#pj&diefbnf\"jp)&@F\\*{ltq#Hlhrp'",
"Ynw$v`&cg`dl fml`%rhlhs*",
"Dnl$p%qhz{s' hv$w%hh|aceg!;#gpvt(fl+cndea`&dg|fon&v#wjjqm(",
"\ud83d)pft`gs(ec`e!13$qojmz#",
"a!njcmr'ide~nu\"lb%rheoedldpz$lu'gbkr",
"dn\"zkp&kgo4",
"hnpqkw",
"sn\"fau",
"Sn\"tmqnh}}*musvkaw&flf&+ldv$w%lr{}*aulr#vlao|)cetn\"jp$",
"Dxkmc%ot(hhxomwwai'{hln",
"hd{#}js&(pe~'sg#gprb(3#\"",
"hd{b${",
"<;vqkijbq33271:56<3799?24944:",
"Thof$lu'ofdn,!qsefc'az*bnrcma+&Om{o+iu\"`khct$)bnrd\"bcdoi&",
"snofplkb{)c'r\"lod'|f*aurv#cpno`abchijklmno"
];
export default definePlugin({
name: "LoadingQuotes",
description: "Replace Discords loading quotes",
authors: [Devs.Ven],
authors: [Devs.Ven, Devs.KraXen72],
patches: [
{
find: ".LOADING_DID_YOU_KNOW",

246
src/plugins/messageTags.ts Normal file
View file

@ -0,0 +1,246 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { DataStore } from "../api";
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, registerCommand, sendBotMessage, unregisterCommand } from "../api/Commands";
import { Settings } from "../api/settings";
import { Devs } from "../utils/constants";
import definePlugin, { OptionType } from "../utils/types";
const EMOTE = "<:luna:1035316192220553236>";
const DATA_KEY = "MessageTags_TAGS";
const MessageTagsMarker = Symbol("MessageTags");
const author = {
id: "821472922140803112",
bot: false
};
interface Tag {
name: string;
message: string;
enabled: boolean;
}
const getTags = () => DataStore.get(DATA_KEY).then<Tag[]>(t => t ?? []);
const getTag = (name: string) => DataStore.get(DATA_KEY).then<Tag | null>((t: Tag[]) => (t ?? []).find((tt: Tag) => tt.name === name) ?? null);
const addTag = async (tag: Tag) => {
const tags = await getTags();
tags.push(tag);
DataStore.set(DATA_KEY, tags);
return tags;
};
const removeTag = async (name: string) => {
let tags = await getTags();
tags = await tags.filter((t: Tag) => t.name !== name);
DataStore.set(DATA_KEY, tags);
return tags;
};
function createTagCommand(tag: Tag) {
registerCommand({
name: tag.name,
description: tag.name,
inputType: ApplicationCommandInputType.BUILT_IN_TEXT,
execute: async (_, ctx) => {
if (!await getTag(tag.name)) {
sendBotMessage(ctx.channel.id, {
author,
content: `${EMOTE} The tag **${tag.name}** does not exist anymore! Please reload ur Discord to fix :)`
});
return { content: `/${tag.name}` };
}
if (Settings.plugins.MessageTags.clyde) sendBotMessage(ctx.channel.id, {
author,
content: `${EMOTE} The tag **${tag.name}** has been sent!`
});
return { content: tag.message.replaceAll("\\n", "\n") };
},
[MessageTagsMarker]: true,
}, "CustomTags");
}
export default definePlugin({
name: "MessageTags",
description: "Allows you to save messages and to use them with a simple command.",
authors: [Devs.Luna],
options: {
clyde: {
name: "Clyde message on send",
description: "If enabled, clyde will send you an ephemeral message when a tag was used.",
type: OptionType.BOOLEAN,
default: true
}
},
dependencies: ["CommandsAPI"],
async start() {
for (const tag of await getTags()) createTagCommand(tag);
},
commands: [
{
name: "tags",
description: "Manage all the tags for yourself",
inputType: ApplicationCommandInputType.BUILT_IN,
options: [
{
name: "create",
description: "Create a new tag",
type: ApplicationCommandOptionType.SUB_COMMAND,
options: [
{
name: "tag-name",
description: "The name of the tag to trigger the response",
type: ApplicationCommandOptionType.STRING,
required: true
},
{
name: "message",
description: "The message that you will send when using this tag",
type: ApplicationCommandOptionType.STRING,
required: true
}
]
},
{
name: "list",
description: "List all tags from yourself",
type: ApplicationCommandOptionType.SUB_COMMAND,
options: []
},
{
name: "delete",
description: "Remove a tag from your yourself",
type: ApplicationCommandOptionType.SUB_COMMAND,
options: [
{
name: "tag-name",
description: "The name of the tag to trigger the response",
type: ApplicationCommandOptionType.STRING,
required: true
}
]
},
{
name: "preview",
description: "Preview a tag without sending it publicly",
type: ApplicationCommandOptionType.SUB_COMMAND,
options: [
{
name: "tag-name",
description: "The name of the tag to trigger the response",
type: ApplicationCommandOptionType.STRING,
required: true
}
]
}
],
async execute(args, ctx) {
switch (args[0].name) {
case "create": {
const name: string = findOption(args[0].options, "tag-name", "");
const message: string = findOption(args[0].options, "message", "");
if (await getTag(name))
return sendBotMessage(ctx.channel.id, {
author,
content: `${EMOTE} A Tag with the name **${name}** already exists!`
});
const tag = {
name: name,
enabled: true,
message: message
};
createTagCommand(tag);
await addTag(tag);
sendBotMessage(ctx.channel.id, {
author,
content: `${EMOTE} Successfully created the tag **${name}**!`
});
break; // end 'create'
}
case "delete": {
const name: string = findOption(args[0].options, "tag-name", "");
if (!await getTag(name))
return sendBotMessage(ctx.channel.id, {
author,
content: `${EMOTE} A Tag with the name **${name}** does not exist!`
});
unregisterCommand(name);
await removeTag(name);
sendBotMessage(ctx.channel.id, {
author,
content: `${EMOTE} Successfully deleted the tag **${name}**!`
});
break; // end 'delete'
}
case "list": {
sendBotMessage(ctx.channel.id, {
author,
embeds: [
{
// @ts-ignore
title: "All Tags:",
// @ts-ignore
description: (await getTags())
.map(tag => `\`${tag.name}\`: ${tag.message.slice(0, 72).replaceAll("\\n", " ")}${tag.message.length > 72 ? "..." : ""}`)
.join("\n") || `${EMOTE} Woops! There are no tags yet, use \`/tags create\` to create one!`,
// @ts-ignore
color: 0xd77f7f,
type: "rich",
}
]
});
break; // end 'list'
}
case "preview": {
const name: string = findOption(args[0].options, "tag-name", "");
const tag = await getTag(name);
if (!tag)
return sendBotMessage(ctx.channel.id, {
author,
content: `${EMOTE} A Tag with the name **${name}** does not exist!`
});
sendBotMessage(ctx.channel.id, {
author,
content: tag.message.replaceAll("\\n", "\n")
});
break; // end 'preview'
}
}
return sendBotMessage(ctx.channel.id, {
author,
content: "Invalid sub-command"
});
}
}
]
});

View file

@ -58,7 +58,7 @@ const PlatformIcon = ({ platform, status }: { platform: Platform, status: string
const tooltip = platform[0].toUpperCase() + platform.slice(1);
const Icon = Icons[platform] ?? Icons.desktop;
return <Icon color={getStatusColor(status)} tooltip={tooltip} />;
return <Icon color={`var(--${getStatusColor(status)}`} tooltip={tooltip} />;
};
const PlatformIndicator = ({ user }: { user: User; }) => {

View file

@ -72,13 +72,13 @@ export default LazyComponent(() => {
body: "Do you really you want to report this review?",
confirmText: "Report",
cancelText: "Nevermind",
confirmColor: "red",
// confirmColor: "red", this just adds a class name and breaks the submit button guh
onConfirm: () => reportReview(review.id)
});
}
return (
<div className={classes(cozyMessage, wrapper)} style={
<div className={classes(cozyMessage, wrapper,message, groupStart, cozy, "user-review")} style={
{
marginLeft: "0px",
paddingLeft: "52px",
@ -89,6 +89,7 @@ export default LazyComponent(() => {
<div className={contents} style={{ paddingLeft: "0px" }}>
<img
className={classes(avatar, clickable)}
style={{ left: "8px" }}
onClick={openModal}
src={review.profile_photo || "/assets/1f0bfc0865d324c2587920a7d80c609b.png?size=128"}
style={{ left: "0px" }}
@ -103,11 +104,13 @@ export default LazyComponent(() => {
{review.badges.map(badge => <ReviewBadge {...badge} />)}
<p
className={classes(messageContent, defaultColor)}
style={{ fontSize: 15, marginTop: 4, marginRight: "0px" }}
style={{ fontSize: 15, marginTop: 4 }}
>
{review.comment}
</p>
<div className={classes(container, isHeader, buttons)}>
<div className={classes(container, isHeader, buttons)} style={{
padding: "0px",
}}>
<div className={buttonClasses.wrapper} >
<MessageButton type="report" callback={reportRev} />
{canDeleteReview(review, UserStore.getCurrentUser().id) && (

View file

@ -18,8 +18,8 @@
import type { KeyboardEvent } from "react";
import { lazyWebpack, useAwaiter } from "../../../utils/misc";
import { Forms, Text } from "../../../webpack/common";
import { classes, lazyWebpack, useAwaiter } from "../../../utils/misc";
import { Forms, Text, UserStore } from "../../../webpack/common";
import { addReview, getReviews } from "../Utils/ReviewDBAPI";
import ReviewComponent from "./ReviewComponent";
@ -46,7 +46,7 @@ export default function ReviewsView({ userId }: { userId: string; }) {
}
return (
<>
<div className="ReviewDB">
<Text
tag="h2"
variant="eyebrow"
@ -70,16 +70,24 @@ export default function ReviewsView({ userId }: { userId: string; }) {
</Forms.FormText>
)}
<textarea
className={Classes.textarea.replace("textarea", "")}
className={classes(Classes.textarea.replace("textarea", ""),"enter-comment")}
// this produces something like '-_59yqs ...' but since no class exists with that name its fine
placeholder="Enter a comment"
placeholder= {"Review @" + UserStore.getUser(userId)?.username ?? ""}
onKeyDown={onKeyPress}
style={{
marginTop: "6px",
resize: "none",
marginBottom: "12px",
padding: "12px",
marginBottom: "12px",
color: "var(--text-normal)",
border: "1px solid var(--profile-message-input-border-color)",
fontSize: "14px",
borderRadius: "3px",
}}
/>
</>
<div/>
);
}

View file

@ -0,0 +1,60 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { makeRange } from "../components/PluginSettings/components/SettingSliderComponent";
import { Devs } from "../utils/constants";
import definePlugin, { OptionType } from "../utils/types";
export default definePlugin({
name: "VolumeBooster",
authors: [Devs.Nuckyz],
description: "Allows you to set the user and stream volume above the default maximum.",
patches: [
{
find: ".Messages.USER_VOLUME",
replacement: {
match: /maxValue:(.{1,2}\..{1,2})\?(\d+?):(\d+?),/,
replace: (_, defaultMaxVolumePredicate, higherMaxVolume, minorMaxVolume) => ""
+ `maxValue:${defaultMaxVolumePredicate}`
+ `?${higherMaxVolume}*Vencord.Settings.plugins.VolumeBooster.multiplier`
+ `:${minorMaxVolume}*Vencord.Settings.plugins.VolumeBooster.multiplier,`
}
},
{
find: "currentVolume:",
replacement: {
match: /maxValue:(.{1,2}\..{1,2})\?(\d+?):(\d+?),/,
replace: (_, defaultMaxVolumePredicate, higherMaxVolume, minorMaxVolume) => ""
+ `maxValue:${defaultMaxVolumePredicate}`
+ `?${higherMaxVolume}*Vencord.Settings.plugins.VolumeBooster.multiplier`
+ `:${minorMaxVolume}*Vencord.Settings.plugins.VolumeBooster.multiplier,`
}
}
],
options: {
multiplier: {
description: "Volume Multiplier",
type: OptionType.SLIDER,
markers: makeRange(1, 5, 1),
default: 2,
stickToMarkers: true,
}
}
});

View file

@ -148,5 +148,13 @@ export const Devs = Object.freeze({
Ducko: {
name: "Ducko",
id: 506482395269169153n
},
jewdev: {
name: "jewdev",
id: 222369866529636353n
},
Luna: {
name: "Luny",
id: 821472922140803112n
}
});

View file

@ -28,7 +28,7 @@ export async function toggle(isEnabled: boolean) {
style.id = "vencord-custom-css";
document.head.appendChild(style);
VencordNative.ipc.on(IpcEvents.QUICK_CSS_UPDATE, (_, css: string) => style.innerText = css);
style.innerText = await VencordNative.ipc.invoke(IpcEvents.GET_QUICK_CSS);
style.textContent = await VencordNative.ipc.invoke(IpcEvents.GET_QUICK_CSS);
}
} else // @ts-ignore yes typescript, property 'disabled' does exist on type 'HTMLStyleElement' u should try reading the docs some time
style.disabled = !isEnabled;

View file

@ -41,6 +41,7 @@ export const PresenceStore = lazyWebpack(filters.byProps("setCurrentUserOnConnec
export let GuildStore: Stores.GuildStore;
export let UserStore: Stores.UserStore;
export let SelectedChannelStore: Stores.SelectedChannelStore;
export let SelectedGuildStore: any;
export let ChannelStore: Stores.ChannelStore;
export const Forms = {} as {
@ -125,6 +126,13 @@ export const Clipboard = mapMangledModuleLazy('document.queryCommandEnabled("cop
SUPPORTS_COPY: x => typeof x === "boolean",
});
export const NavigationRouter = mapMangledModuleLazy("Transitioning to external path", {
transitionTo: filters.byCode("Transitioning to external path"),
transitionToGuild: filters.byCode("transitionToGuild"),
goBack: filters.byCode("goBack()"),
goForward: filters.byCode("goForward()"),
});
waitFor("useState", m => React = m);
waitFor(["dispatch", "subscribe"], m => {
@ -139,6 +147,7 @@ waitFor(["dispatch", "subscribe"], m => {
waitFor(["getCurrentUser", "initialize"], m => UserStore = m);
waitFor("getSortedPrivateChannels", m => ChannelStore = m);
waitFor("getCurrentlySelectedChannelId", m => SelectedChannelStore = m);
waitFor("getLastSelectedGuildId", m => SelectedGuildStore = m);
waitFor("getGuildCount", m => GuildStore = m);
waitFor(["Hovers", "Looks", "Sizes"], m => Button = m);