Merge branch 'dev' into modules-proxy-patches

This commit is contained in:
Nuckyz 2024-05-29 05:10:24 -03:00
commit 4db6c4b88a
No known key found for this signature in database
GPG key ID: 440BF8296E1C4AD9
12 changed files with 118 additions and 24 deletions

29
src/api/MessageUpdater.ts Normal file
View file

@ -0,0 +1,29 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { MessageCache, MessageStore } from "@webpack/common";
import { FluxStore } from "@webpack/types";
import { Message } from "discord-types/general";
/**
* Update and re-render a message
* @param channelId The channel id of the message
* @param messageId The message id
* @param fields The fields of the message to change. Leave empty if you just want to re-render
*/
export function updateMessage(channelId: string, messageId: string, fields?: Partial<Message>) {
const channelMessageCache = MessageCache.getOrCreate(channelId);
if (!channelMessageCache.has(messageId)) return;
// To cause a message to re-render, we basically need to create a new instance of the message and obtain a new reference
// If we have fields to modify we can use the merge method of the class, otherwise we just create a new instance with the old fields
const newChannelMessageCache = channelMessageCache.update(messageId, (oldMessage: any) => {
return fields ? oldMessage.merge(fields) : new oldMessage.constructor(oldMessage);
});
MessageCache.commit(newChannelMessageCache);
(MessageStore as unknown as FluxStore).emitChange();
}

View file

@ -26,6 +26,7 @@ import * as $MessageAccessories from "./MessageAccessories";
import * as $MessageDecorations from "./MessageDecorations"; import * as $MessageDecorations from "./MessageDecorations";
import * as $MessageEventsAPI from "./MessageEvents"; import * as $MessageEventsAPI from "./MessageEvents";
import * as $MessagePopover from "./MessagePopover"; import * as $MessagePopover from "./MessagePopover";
import * as $MessageUpdater from "./MessageUpdater";
import * as $Notices from "./Notices"; import * as $Notices from "./Notices";
import * as $Notifications from "./Notifications"; import * as $Notifications from "./Notifications";
import * as $ServerList from "./ServerList"; import * as $ServerList from "./ServerList";
@ -110,3 +111,8 @@ export const ContextMenu = $ContextMenu;
* An API allowing you to add buttons to the chat input * An API allowing you to add buttons to the chat input
*/ */
export const ChatButtons = $ChatButtons; export const ChatButtons = $ChatButtons;
/**
* An API allowing you to update and re-render messages
*/
export const MessageUpdater = $MessageUpdater;

View file

@ -140,8 +140,14 @@ if (!IS_VANILLA) {
return originalAppend.apply(this, args); return originalAppend.apply(this, args);
}; };
// disable renderer backgrounding to prevent the app from unloading when in the background
// https://github.com/electron/electron/issues/2822
// https://github.com/GoogleChrome/chrome-launcher/blob/5a27dd574d47a75fec0fb50f7b774ebf8a9791ba/docs/chrome-flags-for-tools.md#task-throttling
// Work around discord unloading when in background // Work around discord unloading when in background
// Discord also recently started adding these flags but only on windows for some reason dunno why, it happens on Linux too
app.commandLine.appendSwitch("disable-renderer-backgrounding"); app.commandLine.appendSwitch("disable-renderer-backgrounding");
app.commandLine.appendSwitch("disable-background-timer-throttling");
app.commandLine.appendSwitch("disable-backgrounding-occluded-windows");
} else { } else {
console.log("[Vencord] Running in vanilla mode. Not loading Vencord"); console.log("[Vencord] Running in vanilla mode. Not loading Vencord");
} }

View file

@ -0,0 +1,37 @@
/*
* 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 { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
export default definePlugin({
name: "MessageUpdaterAPI",
description: "API for updating and re-rendering messages.",
authors: [Devs.Nuckyz],
patches: [
{
// Message accessories have a custom logic to decide if they should render again, so we need to make it not ignore changed message reference
find: "}renderEmbeds(",
replacement: {
match: /(?<=this.props,\i,\[)"message",/,
replace: ""
}
}
]
});

View file

@ -333,7 +333,7 @@ export default definePlugin({
] ]
}, },
{ {
find: "renderEmbeds(", find: "}renderEmbeds(",
replacement: [ replacement: [
{ {
// Call our function to decide whether the embed should be ignored or not // Call our function to decide whether the embed should be ignored or not

View file

@ -18,12 +18,13 @@
import { addChatBarButton, ChatBarButton } from "@api/ChatButtons"; import { addChatBarButton, ChatBarButton } from "@api/ChatButtons";
import { addButton, removeButton } from "@api/MessagePopover"; import { addButton, removeButton } from "@api/MessagePopover";
import { updateMessage } from "@api/MessageUpdater";
import { definePluginSettings } from "@api/Settings"; import { definePluginSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary"; import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { getStegCloak } from "@utils/dependencies"; import { getStegCloak } from "@utils/dependencies";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { ChannelStore, Constants, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common"; import { ChannelStore, Constants, RestAPI, Tooltip } from "@webpack/common";
import { Message } from "discord-types/general"; import { Message } from "discord-types/general";
import { buildDecModal } from "./components/DecryptionModal"; import { buildDecModal } from "./components/DecryptionModal";
@ -103,7 +104,7 @@ export default definePlugin({
name: "InvisibleChat", name: "InvisibleChat",
description: "Encrypt your Messages in a non-suspicious way!", description: "Encrypt your Messages in a non-suspicious way!",
authors: [Devs.SammCheese], authors: [Devs.SammCheese],
dependencies: ["MessagePopoverAPI", "ChatInputButtonAPI"], dependencies: ["MessagePopoverAPI", "ChatInputButtonAPI", "MessageUpdaterAPI"],
patches: [ patches: [
{ {
// Indicator // Indicator
@ -180,14 +181,7 @@ export default definePlugin({
message.embeds.push(embed); message.embeds.push(embed);
} }
this.updateMessage(message); updateMessage(message.channel_id, message.id, { embeds: message.embeds });
},
updateMessage: (message: any) => {
FluxDispatcher.dispatch({
type: "MESSAGE_UPDATE",
message,
});
}, },
popOverIcon: () => <PopOverIcon />, popOverIcon: () => <PopOverIcon />,

View file

@ -17,6 +17,7 @@
*/ */
import { addAccessory, removeAccessory } from "@api/MessageAccessories"; import { addAccessory, removeAccessory } from "@api/MessageAccessories";
import { updateMessage } from "@api/MessageUpdater";
import { definePluginSettings } from "@api/Settings"; import { definePluginSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary"; import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants.js"; import { Devs } from "@utils/constants.js";
@ -28,7 +29,6 @@ import {
Button, Button,
ChannelStore, ChannelStore,
Constants, Constants,
FluxDispatcher,
GuildStore, GuildStore,
IconUtils, IconUtils,
MessageStore, MessageStore,
@ -250,15 +250,9 @@ function MessageEmbedAccessory({ message }: { message: Message; }) {
if (linkedMessage) { if (linkedMessage) {
messageCache.set(messageID, { message: linkedMessage, fetched: true }); messageCache.set(messageID, { message: linkedMessage, fetched: true });
} else { } else {
const msg = { ...message } as any;
delete msg.embeds;
delete msg.interaction;
messageFetchQueue.unshift(() => fetchMessage(channelID, messageID) messageFetchQueue.unshift(() => fetchMessage(channelID, messageID)
.then(m => m && FluxDispatcher.dispatch({ .then(m => m && updateMessage(message.channel_id, message.id))
type: "MESSAGE_UPDATE",
message: msg
}))
); );
continue; continue;
} }
@ -367,7 +361,7 @@ export default definePlugin({
name: "MessageLinkEmbeds", name: "MessageLinkEmbeds",
description: "Adds a preview to messages that link another message", description: "Adds a preview to messages that link another message",
authors: [Devs.TheSun, Devs.Ven, Devs.RyanCaoDev], authors: [Devs.TheSun, Devs.Ven, Devs.RyanCaoDev],
dependencies: ["MessageAccessoriesAPI"], dependencies: ["MessageAccessoriesAPI", "MessageUpdaterAPI"],
settings, settings,

View file

@ -2,6 +2,8 @@
Enables Discord's experimental Summaries feature on every server, displaying AI generated summaries of conversations. Enables Discord's experimental Summaries feature on every server, displaying AI generated summaries of conversations.
Read more about summaries in the [official Discord help article](https://support.discord.com/hc/en-us/articles/12926016807575-In-Channel-Conversation-Summaries)!
Note that this plugin can't fetch old summaries, it can only display ones created while your Discord is running with the plugin enabled. Note that this plugin can't fetch old summaries, it can only display ones created while your Discord is running with the plugin enabled.
![](https://github.com/Vendicated/Vencord/assets/45497981/bd931b0c-2e85-4c10-9f7c-8ba01eb55745) ![](https://github.com/Vendicated/Vencord/assets/45497981/bd931b0c-2e85-4c10-9f7c-8ba01eb55745)

View file

@ -41,8 +41,33 @@ export class FluxStore {
__getLocalVars(): Record<string, any>; __getLocalVars(): Record<string, any>;
} }
export class FluxEmitter {
constructor();
changeSentinel: number;
changedStores: Set<FluxStore>;
isBatchEmitting: boolean;
isDispatching: boolean;
isPaused: boolean;
pauseTimer: NodeJS.Timeout | null;
reactChangedStores: Set<FluxStore>;
batched(batch: (...args: any[]) => void): void;
destroy(): void;
emit(): void;
emitNonReactOnce(): void;
emitReactOnce(): void;
getChangeSentinel(): number;
getIsPaused(): boolean;
injectBatchEmitChanges(batch: (...args: any[]) => void): void;
markChanged(store: FluxStore): void;
pause(): void;
resume(): void;
}
export interface Flux { export interface Flux {
Store: typeof FluxStore; Store: typeof FluxStore;
Emitter: FluxEmitter;
} }
export class WindowStore extends FluxStore { export class WindowStore extends FluxStore {

View file

@ -144,6 +144,7 @@ const persistFilter = filters.byCode("[zustand persist middleware]");
export const { persist: zustandPersist } = findLazy(m => m.persist && persistFilter(m.persist)); export const { persist: zustandPersist } = findLazy(m => m.persist && persistFilter(m.persist));
export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); export const MessageActions = findByPropsLazy("editMessage", "sendMessage");
export const MessageCache = findByPropsLazy("clearCache", "_channelMessages");
export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal"); export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal");
export const InviteActions = findByPropsLazy("resolveInvite"); export const InviteActions = findByPropsLazy("resolveInvite");

View file

@ -377,7 +377,7 @@ function patchFactory(id: PropertyKey, factory: ModuleFactory) {
// There are (at the time of writing) 11 modules exporting the window // There are (at the time of writing) 11 modules exporting the window
// Make these non enumerable to improve webpack search performance // Make these non enumerable to improve webpack search performance
if (exports === window && typeof require === "function" && require.c != null) { if ((exports === window || exports?.default === window) && typeof require === "function" && require.c != null) {
define(require.c, id, { define(require.c, id, {
value: require.c[id], value: require.c[id],
enumerable: false enumerable: false
@ -395,7 +395,7 @@ function patchFactory(id: PropertyKey, factory: ModuleFactory) {
for (const [filter, callback] of subscriptions) { for (const [filter, callback] of subscriptions) {
try { try {
if (filter(exports)) { if (exports && filter(exports)) {
subscriptions.delete(filter); subscriptions.delete(filter);
callback(exports, id); callback(exports, id);
} else if (exports.default && filter(exports.default)) { } else if (exports.default && filter(exports.default)) {

View file

@ -114,13 +114,13 @@ export const find = traceFunction("find", function find(filter: FilterFn, { isIn
for (const key in cache) { for (const key in cache) {
const mod = cache[key]; const mod = cache[key];
if (!mod?.exports || mod.exports === window) continue; if (!mod?.exports) continue;
if (filter(mod.exports)) { if (filter(mod.exports)) {
return isWaitFor ? [mod.exports, key] : mod.exports; return isWaitFor ? [mod.exports, key] : mod.exports;
} }
if (mod.exports.default && mod.exports.default !== window && filter(mod.exports.default)) { if (mod.exports.default && filter(mod.exports.default)) {
const found = mod.exports.default; const found = mod.exports.default;
return isWaitFor ? [found, key] : found; return isWaitFor ? [found, key] : found;
} }