This commit is contained in:
thororen1234 2024-10-14 19:33:17 -04:00
parent 75fac79ad1
commit deceb2ba97
13 changed files with 186 additions and 58 deletions

View file

@ -71,7 +71,8 @@ async function syncSettings() {
if (localStorage.Vencord_settingsDirty) { if (localStorage.Vencord_settingsDirty) {
await putCloudSettings(); await putCloudSettings();
delete localStorage.Vencord_settingsDirty; delete localStorage.Vencord_settingsDirty;
} else if (await getCloudSettings(false)) { // if we synchronized something (false means no sync) } else if (await getCloudSettings(false)) {
// if we synchronized something (false means no sync)
// we show a notification here instead of allowing getCloudSettings() to show one to declutter the amount of // we show a notification here instead of allowing getCloudSettings() to show one to declutter the amount of
// potential notifications that might occur. getCloudSettings() will always send a notification regardless if // potential notifications that might occur. getCloudSettings() will always send a notification regardless if
// there was an error to notify the user, but besides that we only want to show one notification instead of all // there was an error to notify the user, but besides that we only want to show one notification instead of all

View file

@ -37,12 +37,13 @@ export const settings = definePluginSettings({
export default definePlugin({ export default definePlugin({
name: "Anammox", name: "Anammox",
description: "Remove Some Discord Settings", description: "A microbial process that plays an important part in the nitrogen cycle",
authors: [Devs.Kyuuhachi], authors: [Devs.Kyuuhachi],
settings, settings,
patches: [ patches: [
{ // Above DMs, mouse nav {
// Above DMs, mouse nav
find: 'tutorialId:"direct-messages"', find: 'tutorialId:"direct-messages"',
replacement: [ replacement: [
{ {
@ -56,7 +57,8 @@ export default definePlugin({
], ],
predicate: () => settings.store.dms, predicate: () => settings.store.dms,
}, },
{ // Above DMs, keyboard nav {
// Above DMs, keyboard nav
find: ".hasLibraryApplication()&&!", find: ".hasLibraryApplication()&&!",
replacement: [ replacement: [
{ {
@ -70,7 +72,8 @@ export default definePlugin({
], ],
predicate: () => settings.store.dms, predicate: () => settings.store.dms,
}, },
{ // Settings, sidebar {
// Settings, sidebar
find: "Messages.BILLING_SETTINGS", find: "Messages.BILLING_SETTINGS",
replacement: [ replacement: [
{ {
@ -84,23 +87,26 @@ export default definePlugin({
], ],
predicate: () => settings.store.billing, predicate: () => settings.store.billing,
}, },
{ // Gift button {
find: 'Messages.PREMIUM_GIFT_BUTTON_LABEL,"aria-haspopup":"dialog",onClick:', // Gift button
find: ".gifts)||void 0===",
replacement: { replacement: {
match: /if\(\i\)return null;/, match: /let\{disabled:\i,channel:\i\}=\i/,
replace: "return null;", replace: "return null;$&",
}, },
predicate: () => settings.store.gift, predicate: () => settings.store.gift,
}, },
{ // Emoji list {
// Emoji list
find: "Messages.EMOJI_PICKER_CREATE_EMOJI_TITLE,size:", find: "Messages.EMOJI_PICKER_CREATE_EMOJI_TITLE,size:",
replacement: { replacement: {
match: /(\i)=\i\|\|!\i&&\i.\i\i.isEmojiCategoryNitroLocked\(\{[^}]*\}\);/, match: /(\i)=\i\|\|!\i&&\i.\i.isEmojiCategoryNitroLocked\(\{[^}]*\}\);/,
replace: "$&$1||" replace: "$&$1||"
}, },
predicate: () => settings.store.emojiList, predicate: () => settings.store.emojiList,
}, },
{ // Emoji category list {
// Emoji category list
find: "Messages.EMOJI_CATEGORY_TOP_GUILD_EMOJI.format({", find: "Messages.EMOJI_CATEGORY_TOP_GUILD_EMOJI.format({",
replacement: { replacement: {
match: /(?<=(\i)\.unshift\((\i)\):)(?=\1\.push\(\2\))/, match: /(?<=(\i)\.unshift\((\i)\):)(?=\1\.push\(\2\))/,

View file

@ -163,7 +163,8 @@ function ChannelTabContent(props: ChannelTabsProps & {
{!showStatusIndicators && <TypingIndicator isTyping={isTyping} />} {!showStatusIndicators && <TypingIndicator isTyping={isTyping} />}
</> </>
); );
} else { // Group DM } else {
// Group DM
return ( return (
<> <>
<ChannelIcon channel={channel} /> <ChannelIcon channel={channel} />

View file

@ -25,7 +25,7 @@ const mimeTypes = {
mov: "video/quicktime", mov: "video/quicktime",
}; };
const formatDimension = (value) => value % 1 === 0 ? value : value.toFixed(2); const formatDimension = value => value % 1 === 0 ? value : value.toFixed(2);
function getMimeType(extension: string | undefined): [boolean, string] { function getMimeType(extension: string | undefined): [boolean, string] {
if (!extension) return [false, ""]; if (!extension) return [false, ""];
@ -389,7 +389,7 @@ export default definePlugin({
start() { start() {
let timeout: number | undefined; let timeout: number | undefined;
let previewDiv: HTMLDivElement | null = null; const previewDiv: HTMLDivElement | null = null;
function initialScan() { function initialScan() {
const appContainer = document.querySelector('[class*="app-"]'); const appContainer = document.querySelector('[class*="app-"]');

View file

@ -55,4 +55,4 @@ video {
.dimensions-displaying, .dimensions-displaying,
.dimensions-original { .dimensions-original {
display: block; display: block;
} }

View file

@ -6,12 +6,14 @@
import "./style.css"; import "./style.css";
import { definePluginSettings } from "@api/Settings";
import { getUserSettingLazy } from "@api/UserSettings";
import ErrorBoundary from "@components/ErrorBoundary"; import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { proxyLazy } from "@utils/lazy"; import { proxyLazy } from "@utils/lazy";
import definePlugin from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { findComponentByCodeLazy } from "@webpack"; import { findComponentByCodeLazy } from "@webpack";
import { ChannelStore, Forms, MessageStore, RestAPI, Tooltip, useEffect, useState, useStateFromStores } from "@webpack/common"; import { ChannelStore, Constants, Forms, MessageStore, RestAPI, Tooltip, useEffect, useState, useStateFromStores } from "@webpack/common";
import type { ComponentType, HTMLAttributes } from "react"; import type { ComponentType, HTMLAttributes } from "react";
declare enum SpinnerTypes { declare enum SpinnerTypes {
@ -38,52 +40,124 @@ const { Spinner } = proxyLazy(() => Forms as any as {
SpinnerTypes: typeof SpinnerTypes; SpinnerTypes: typeof SpinnerTypes;
}); });
const MessageDisplayCompact = getUserSettingLazy("textAndImages", "messageDisplayCompact")!;
const ChannelMessage = findComponentByCodeLazy("isFirstMessageInForumPost", "trackAnnouncementViews") as ComponentType<any>; const ChannelMessage = findComponentByCodeLazy("isFirstMessageInForumPost", "trackAnnouncementViews") as ComponentType<any>;
const settings = definePluginSettings({
onLink: {
description: "Show tooltip when hovering over message links",
type: OptionType.BOOLEAN,
default: true,
restartNeeded: true,
},
onReply: {
description: "Show tooltip when hovering over message replies",
type: OptionType.BOOLEAN,
default: true,
restartNeeded: true,
},
onForward: {
description: "Show tooltip when hovering over forwarded messages",
type: OptionType.BOOLEAN,
default: true,
restartNeeded: true,
},
display: {
description: "Display style",
type: OptionType.SELECT,
options: [
{
label: "Same as message",
value: "auto",
default: true
},
{
label: "Compact",
value: "compact"
},
{
label: "Cozy",
value: "cozy"
},
]
},
});
export default definePlugin({ export default definePlugin({
name: "MessageLinkTooltip", name: "MessageLinkTooltip",
description: "Like MessageLinkEmbed but without taking space", description: "Like MessageLinkEmbed but without taking space",
authors: [Devs.Kyuuhachi], authors: [Devs.Kyuuhachi],
settings,
patches: [ patches: [
{ {
find: ',className:"channelMention",children:[', find: ',className:"channelMention",children:[',
replacement: { replacement: {
match: /(?<=\.jsxs\)\()(\i\.\i)(?=,\{role:"link")/, match: /(?<=\.jsxs\)\()(\i\.\i),\{(?=role:"link")/,
replace: "$self.wrapComponent(arguments[0], $1)" replace: "$self.MentionTooltip,{Component:$1,vcProps:arguments[0],"
} },
} predicate: () => settings.store.onLink,
},
{
find: "Messages.REPLY_QUOTE_MESSAGE_NOT_LOADED",
replacement: {
// Should match two places
match: /(\i\.Clickable),\{/g,
replace: "$self.ReplyTooltip,{Component:$1,vcProps:arguments[0],"
},
predicate: () => settings.store.onReply,
},
{
find: "Messages.MESSAGE_FORWARDED}",
replacement: {
match: /(\i\.Clickable),\{/,
replace: "$self.ForwardTooltip,{Component:$1,vcProps:arguments[0],"
},
predicate: () => settings.store.onForward,
},
], ],
wrapComponent({ messageId, channelId }, Component: ComponentType) { MentionTooltip({ Component, vcProps, ...props }) {
return props => { return withTooltip(Component, props, vcProps.messageId, vcProps.channelId);
if (messageId === undefined) return <Component {...props} />; },
return <Tooltip
tooltipClassName="c98-message-link-tooltip" ReplyTooltip({ Component, vcProps, ...props }) {
text={ const mess = vcProps.baseMessage.messageReference;
<ErrorBoundary> return withTooltip(Component, props, mess?.message_id, mess?.channel_id);
<MessagePreview },
channelId={channelId}
messageId={messageId} ForwardTooltip({ Component, vcProps, ...props }) {
/> const mess = vcProps.message.messageReference;
</ErrorBoundary> return withTooltip(Component, props, mess?.message_id, mess?.channel_id);
} },
>
{({ onMouseEnter, onMouseLeave }) =>
<Component
{...props}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
/>
}
</Tooltip>;
};
}
}); });
function withTooltip(Component, props, messageId, channelId) {
if (!messageId) return <Component {...props} />;
return <Tooltip
tooltipClassName="c98-message-link-tooltip"
text={
<ErrorBoundary>
<MessagePreview
channelId={channelId}
messageId={messageId}
/>
</ErrorBoundary>
}
children={({ onMouseEnter, onMouseLeave }) =>
<Component {...props} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />}
/>;
}
function MessagePreview({ channelId, messageId }) { function MessagePreview({ channelId, messageId }) {
const channel = ChannelStore.getChannel(channelId); const channel = ChannelStore.getChannel(channelId);
const message = useMessage(channelId, messageId); const message = useMessage(channelId, messageId);
const rawCompact = MessageDisplayCompact.useSetting();
const compact = settings.store.display === "compact" ? true : settings.store.display === "cozy" ? false : rawCompact;
// TODO handle load failure // TODO handle load failure
if (!message) { if (!message) {
return <Spinner type={Spinner.Type.PULSING_ELLIPSIS} />; return <Spinner type={Spinner.Type.PULSING_ELLIPSIS} />;
@ -94,6 +168,7 @@ function MessagePreview({ channelId, messageId }) {
message={message} message={message}
channel={channel} channel={channel}
subscribeToComponentDispatch={false} subscribeToComponentDispatch={false}
compact={compact}
/>; />;
} }
@ -107,7 +182,7 @@ function useMessage(channelId, messageId) {
if (message == null) if (message == null)
(async () => { (async () => {
const res = await RestAPI.get({ const res = await RestAPI.get({
url: `/channels/${channelId}/messages`, url: Constants.Endpoints.MESSAGES(channelId),
query: { query: {
limit: 1, limit: 1,
around: messageId, around: messageId,

View file

@ -0,0 +1,34 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
export default definePlugin({
name: "MoreThemes",
description: "Enables Darker and Midnight themes",
authors: [Devs.Kyuuhachi],
patches: [
{
// matches twice: the settings menu and the settings context menu
find: '("appearance_settings")',
replacement: {
match: /\("appearance_settings"\)/,
replace: "$&||true"
},
all: true,
},
{
// make it actually save the setting instead of falling back to dark
find: 'getCurrentConfig({location:"ThemeStore"}).enabled',
replacement: {
match: /getCurrentConfig\(\{location:"ThemeStore"\}\)\.enabled/,
replace: "$&&&false"
},
}
],
});

View file

@ -218,7 +218,8 @@ export default definePlugin({
// @ts-ignore Typescript will add userAgentData IMMEDIATELY // @ts-ignore Typescript will add userAgentData IMMEDIATELY
|| navigator.userAgentData?.brands?.find(b => b.brand === "Chromium" || b.brand === "Google Chrome")?.version || navigator.userAgentData?.brands?.find(b => b.brand === "Chromium" || b.brand === "Google Chrome")?.version
|| null; || null;
} catch { // inb4 some stupid browser throws unsupported error for navigator.userAgentData, it's only in chromium } catch {
// inb4 some stupid browser throws unsupported error for navigator.userAgentData, it's only in chromium
return null; return null;
} }
}, },

View file

@ -83,14 +83,16 @@ export default definePlugin({
const connectionSuccessful = await new Promise(res => setTimeout(() => res(ws.readyState === WebSocket.OPEN), 1000)); // check if open after 1s const connectionSuccessful = await new Promise(res => setTimeout(() => res(ws.readyState === WebSocket.OPEN), 1000)); // check if open after 1s
if (!connectionSuccessful) { if (!connectionSuccessful) {
showNotice("Failed to connect to arRPC, is it running?", "Retry", () => { // show notice about failure to connect, with retry/ignore showNotice("Failed to connect to arRPC, is it running?", "Retry", () => {
// show notice about failure to connect, with retry/ignore
popNotice(); popNotice();
this.start(); this.start();
}); });
return; return;
} }
Toasts.show({ // show toast on success Toasts.show({
// show toast on success
message: "Connected to arRPC", message: "Connected to arRPC",
type: Toasts.Type.SUCCESS, type: Toasts.Type.SUCCESS,
id: Toasts.genId(), id: Toasts.genId(),

View file

@ -84,19 +84,22 @@ export default definePlugin({
{ {
find: "this.renderArtisanalHack()", find: "this.renderArtisanalHack()",
replacement: [ replacement: [
{ // Fade in on layer {
// Fade in on layer
match: /(?<=\((\i),"contextType",\i\.\i\);)/, match: /(?<=\((\i),"contextType",\i\.\i\);)/,
replace: "$1=$self.Layer;", replace: "$1=$self.Layer;",
predicate: () => settings.store.disableFade predicate: () => settings.store.disableFade
}, },
{ // Lazy-load contents {
// Lazy-load contents
match: /createPromise:\(\)=>([^:}]*?),webpackId:"?\d+"?,name:(?!="CollectiblesShop")"[^"]+"/g, match: /createPromise:\(\)=>([^:}]*?),webpackId:"?\d+"?,name:(?!="CollectiblesShop")"[^"]+"/g,
replace: "$&,_:$1", replace: "$&,_:$1",
predicate: () => settings.store.eagerLoad predicate: () => settings.store.eagerLoad
} }
] ]
}, },
{ // For some reason standardSidebarView also has a small fade-in {
// For some reason standardSidebarView also has a small fade-in
find: 'minimal:"contentColumnMinimal"', find: 'minimal:"contentColumnMinimal"',
replacement: [ replacement: [
{ {
@ -110,7 +113,8 @@ export default definePlugin({
], ],
predicate: () => settings.store.disableFade predicate: () => settings.store.disableFade
}, },
{ // Load menu TOC eagerly {
// Load menu TOC eagerly
find: "Messages.USER_SETTINGS_WITH_BUILD_OVERRIDE.format", find: "Messages.USER_SETTINGS_WITH_BUILD_OVERRIDE.format",
replacement: { replacement: {
match: /(\i)\(this,"handleOpenSettingsContextMenu",.{0,100}?null!=\i&&.{0,100}?(await Promise\.all[^};]*?\)\)).*?,(?=\1\(this)/, match: /(\i)\(this,"handleOpenSettingsContextMenu",.{0,100}?null!=\i&&.{0,100}?(await Promise\.all[^};]*?\)\)).*?,(?=\1\(this)/,
@ -118,7 +122,8 @@ export default definePlugin({
}, },
predicate: () => settings.store.eagerLoad predicate: () => settings.store.eagerLoad
}, },
{ // Settings cog context menu {
// Settings cog context menu
find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL",
replacement: [ replacement: [
{ {

View file

@ -84,7 +84,8 @@ export default definePlugin({
}); });
}, },
getIdleTimeout() { // milliseconds, default is 6e5 getIdleTimeout() {
// milliseconds, default is 6e5
const { idleTimeout } = settings.store; const { idleTimeout } = settings.store;
return idleTimeout === 0 ? Infinity : idleTimeout * 60000; return idleTimeout === 0 ? Infinity : idleTimeout * 60000;
} }

View file

@ -108,7 +108,8 @@ export default definePlugin({
// Old Discord Android clients have a delay of around 17 days // Old Discord Android clients have a delay of around 17 days
// This is a workaround for that // This is a workaround for that
if (-delta >= DISCORD_KT_DELAY - 86400000) { // One day of padding for good measure if (-delta >= DISCORD_KT_DELAY - 86400000) {
// One day of padding for good measure
isDiscordKotlin = detectDiscordKotlin; isDiscordKotlin = detectDiscordKotlin;
delta += DISCORD_KT_DELAY; delta += DISCORD_KT_DELAY;
} }

View file

@ -135,7 +135,8 @@ function jumpIfOffScreen(channelId: string, messageId: string) {
function getNextMessage(isUp: boolean, isReply: boolean) { function getNextMessage(isUp: boolean, isReply: boolean) {
let messages: Array<Message & { deleted?: boolean; }> = MessageStore.getMessages(SelectedChannelStore.getChannelId())._array; let messages: Array<Message & { deleted?: boolean; }> = MessageStore.getMessages(SelectedChannelStore.getChannelId())._array;
if (!isReply) { // we are editing so only include own if (!isReply) {
// we are editing so only include own
const meId = UserStore.getCurrentUser().id; const meId = UserStore.getCurrentUser().id;
messages = messages.filter(m => m.author.id === meId); messages = messages.filter(m => m.author.id === meId);
} }