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) {
await putCloudSettings();
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
// 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

View file

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

View file

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

View file

@ -25,7 +25,7 @@ const mimeTypes = {
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] {
if (!extension) return [false, ""];
@ -389,7 +389,7 @@ export default definePlugin({
start() {
let timeout: number | undefined;
let previewDiv: HTMLDivElement | null = null;
const previewDiv: HTMLDivElement | null = null;
function initialScan() {
const appContainer = document.querySelector('[class*="app-"]');

View file

@ -6,12 +6,14 @@
import "./style.css";
import { definePluginSettings } from "@api/Settings";
import { getUserSettingLazy } from "@api/UserSettings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
import { proxyLazy } from "@utils/lazy";
import definePlugin from "@utils/types";
import definePlugin, { OptionType } from "@utils/types";
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";
declare enum SpinnerTypes {
@ -38,26 +40,102 @@ const { Spinner } = proxyLazy(() => Forms as any as {
SpinnerTypes: typeof SpinnerTypes;
});
const MessageDisplayCompact = getUserSettingLazy("textAndImages", "messageDisplayCompact")!;
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({
name: "MessageLinkTooltip",
description: "Like MessageLinkEmbed but without taking space",
authors: [Devs.Kyuuhachi],
settings,
patches: [
{
find: ',className:"channelMention",children:[',
replacement: {
match: /(?<=\.jsxs\)\()(\i\.\i)(?=,\{role:"link")/,
replace: "$self.wrapComponent(arguments[0], $1)"
}
}
match: /(?<=\.jsxs\)\()(\i\.\i),\{(?=role:"link")/,
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) {
return props => {
if (messageId === undefined) return <Component {...props} />;
MentionTooltip({ Component, vcProps, ...props }) {
return withTooltip(Component, props, vcProps.messageId, vcProps.channelId);
},
ReplyTooltip({ Component, vcProps, ...props }) {
const mess = vcProps.baseMessage.messageReference;
return withTooltip(Component, props, mess?.message_id, mess?.channel_id);
},
ForwardTooltip({ Component, vcProps, ...props }) {
const mess = vcProps.message.messageReference;
return withTooltip(Component, props, mess?.message_id, mess?.channel_id);
},
});
function withTooltip(Component, props, messageId, channelId) {
if (!messageId) return <Component {...props} />;
return <Tooltip
tooltipClassName="c98-message-link-tooltip"
text={
@ -68,22 +146,18 @@ export default definePlugin({
/>
</ErrorBoundary>
}
>
{({ onMouseEnter, onMouseLeave }) =>
<Component
{...props}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
/>
children={({ onMouseEnter, onMouseLeave }) =>
<Component {...props} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />}
/>;
}
</Tooltip>;
};
}
});
function MessagePreview({ channelId, messageId }) {
const channel = ChannelStore.getChannel(channelId);
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
if (!message) {
return <Spinner type={Spinner.Type.PULSING_ELLIPSIS} />;
@ -94,6 +168,7 @@ function MessagePreview({ channelId, messageId }) {
message={message}
channel={channel}
subscribeToComponentDispatch={false}
compact={compact}
/>;
}
@ -107,7 +182,7 @@ function useMessage(channelId, messageId) {
if (message == null)
(async () => {
const res = await RestAPI.get({
url: `/channels/${channelId}/messages`,
url: Constants.Endpoints.MESSAGES(channelId),
query: {
limit: 1,
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
|| navigator.userAgentData?.brands?.find(b => b.brand === "Chromium" || b.brand === "Google Chrome")?.version
|| 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;
}
},

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
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();
this.start();
});
return;
}
Toasts.show({ // show toast on success
Toasts.show({
// show toast on success
message: "Connected to arRPC",
type: Toasts.Type.SUCCESS,
id: Toasts.genId(),

View file

@ -84,19 +84,22 @@ export default definePlugin({
{
find: "this.renderArtisanalHack()",
replacement: [
{ // Fade in on layer
{
// Fade in on layer
match: /(?<=\((\i),"contextType",\i\.\i\);)/,
replace: "$1=$self.Layer;",
predicate: () => settings.store.disableFade
},
{ // Lazy-load contents
{
// Lazy-load contents
match: /createPromise:\(\)=>([^:}]*?),webpackId:"?\d+"?,name:(?!="CollectiblesShop")"[^"]+"/g,
replace: "$&,_:$1",
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"',
replacement: [
{
@ -110,7 +113,8 @@ export default definePlugin({
],
predicate: () => settings.store.disableFade
},
{ // Load menu TOC eagerly
{
// Load menu TOC eagerly
find: "Messages.USER_SETTINGS_WITH_BUILD_OVERRIDE.format",
replacement: {
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
},
{ // Settings cog context menu
{
// Settings cog context menu
find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL",
replacement: [
{

View file

@ -84,7 +84,8 @@ export default definePlugin({
});
},
getIdleTimeout() { // milliseconds, default is 6e5
getIdleTimeout() {
// milliseconds, default is 6e5
const { idleTimeout } = settings.store;
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
// 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;
delta += DISCORD_KT_DELAY;
}

View file

@ -135,7 +135,8 @@ function jumpIfOffScreen(channelId: string, messageId: string) {
function getNextMessage(isUp: boolean, isReply: boolean) {
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;
messages = messages.filter(m => m.author.id === meId);
}