Merge branch 'Vendicated:main' into main

This commit is contained in:
camila 2024-04-03 11:24:26 -05:00 committed by GitHub
commit 37c1172311
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 164 additions and 132 deletions

View file

@ -1,6 +1,6 @@
> [!WARNING] > [!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. > 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.
> No support will be provided for installing in this fashion. If you cannot figure it out, you should just stick to a regular install. > No support will be provided for installing in this fashion. If you cannot figure it out, you should just stick to a regular install.
# Installation Guide # Installation Guide
@ -95,5 +95,3 @@ Simply run:
```shell ```shell
pnpm uninject pnpm uninject
``` ```
If you need more help, ask in the support channel in our [Discord Server](https://discord.gg/D9uwnFnqmd).

View file

@ -1,7 +1,7 @@
{ {
"name": "vencord", "name": "vencord",
"private": "true", "private": "true",
"version": "1.7.3", "version": "1.7.4",
"description": "The cutest Discord client mod", "description": "The cutest Discord client mod",
"homepage": "https://github.com/Vendicated/Vencord#readme", "homepage": "https://github.com/Vendicated/Vencord#readme",
"bugs": { "bugs": {

View file

@ -67,7 +67,8 @@ const IGNORED_DISCORD_ERRORS = [
"Unable to process domain list delta: Client revision number is null", "Unable to process domain list delta: Client revision number is null",
"Downloading the full bad domains file", "Downloading the full bad domains file",
/\[GatewaySocket\].{0,110}Cannot access '/, /\[GatewaySocket\].{0,110}Cannot access '/,
"search for 'name' in undefined" "search for 'name' in undefined",
"Attempting to set fast connect zstd when unsupported"
] as Array<string | RegExp>; ] as Array<string | RegExp>;
function toCodeBlock(s: string) { function toCodeBlock(s: string) {

View file

@ -13,10 +13,10 @@ export default definePlugin({
authors: [Devs.Ven], authors: [Devs.Ven],
patches: [{ patches: [{
find: 'location:"ChannelTextAreaButtons"', find: '"sticker")',
replacement: { replacement: {
match: /if\(!\i\.isMobile\)\{(?=.+?&&(\i)\.push\(.{0,50}"gift")/, match: /!\i\.isMobile(?=.+?(\i)\.push\(.{0,50}"gift")/,
replace: "$&Vencord.Api.ChatButtons._injectButtons($1,arguments[0]);" replace: "$& &&(Vencord.Api.ChatButtons._injectButtons($1,arguments[0]),true)"
} }
}] }]
}); });

View file

@ -31,7 +31,7 @@ export default definePlugin({
match: /let\{[^}]*lostPermissionTooltipText:\i[^}]*\}=(\i),/, match: /let\{[^}]*lostPermissionTooltipText:\i[^}]*\}=(\i),/,
replace: "$&vencordProps=$1," replace: "$&vencordProps=$1,"
}, { }, {
match: /decorators:.{0,100}?children:\[/, match: /\.Messages\.GUILD_OWNER(?=.+?decorators:(\i)\(\)).+?\1=?\(\)=>.+?children:\[/,
replace: "$&...(typeof vencordProps=='undefined'?[]:Vencord.Api.MemberListDecorators.__getDecorators(vencordProps))," replace: "$&...(typeof vencordProps=='undefined'?[]:Vencord.Api.MemberListDecorators.__getDecorators(vencordProps)),"
} }
] ]

View file

@ -35,7 +35,7 @@ export default definePlugin({
} }
}, },
{ {
find: ".handleSendMessage=", find: ".handleSendMessage",
replacement: { replacement: {
// props.chatInputType...then((function(isMessageValid)... var parsedMessage = b.c.parse(channel,... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply); // props.chatInputType...then((function(isMessageValid)... var parsedMessage = b.c.parse(channel,... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply);
// Lookbehind: validateMessage)({openWarningPopout:..., type: i.props.chatInputType, content: t, stickers: r, ...}).then((function(isMessageValid) // Lookbehind: validateMessage)({openWarningPopout:..., type: i.props.chatInputType, content: t, stickers: r, ...}).then((function(isMessageValid)

View file

@ -26,7 +26,7 @@ export default definePlugin({
required: true, required: true,
patches: [ patches: [
{ {
find: 'displayName="NoticeStore"', find: '"NoticeStore"',
replacement: [ replacement: [
{ {
match: /\i=null;(?=.{0,80}getPremiumSubscription\(\))/g, match: /\i=null;(?=.{0,80}getPremiumSubscription\(\))/g,

View file

@ -41,7 +41,7 @@ export default definePlugin({
authors: [Devs.zt, Devs.Trwy], authors: [Devs.zt, Devs.Trwy],
patches: [ patches: [
{ {
find: ".displayName=\"MaskedLinkStore\"", find: '="MaskedLinkStore",',
replacement: { replacement: {
match: /(?<=isTrustedDomain\(\i\){)return \i\(\i\)/, match: /(?<=isTrustedDomain\(\i\){)return \i\(\i\)/,
replace: "return true" replace: "return true"

View file

@ -26,7 +26,7 @@ export default definePlugin({
"Change GIF alt text from simply being 'GIF' to containing the gif tags / filename", "Change GIF alt text from simply being 'GIF' to containing the gif tags / filename",
patches: [ patches: [
{ {
find: "onCloseImage=", find: '"onCloseImage",',
replacement: { replacement: {
match: /(return.{0,10}\.jsx.{0,50}isWindowFocused)/, match: /(return.{0,10}\.jsx.{0,50}isWindowFocused)/,
replace: replace:

View file

@ -15,8 +15,8 @@ export default definePlugin({
{ {
find: ".GIFPickerResultTypes.SEARCH", find: ".GIFPickerResultTypes.SEARCH",
replacement: [{ replacement: [{
match: "this.state={resultType:null}", match: /(?<="state",{resultType:)null/,
replace: 'this.state={resultType:"Favorites"}' replace: '"Favorites"'
}] }]
} }
] ]

View file

@ -18,6 +18,7 @@
import { Settings } from "@api/Settings"; import { Settings } from "@api/Settings";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { canonicalizeMatch } from "@utils/patches";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { findByPropsLazy } from "@webpack"; import { findByPropsLazy } from "@webpack";
@ -39,8 +40,12 @@ export default definePlugin({
match: /hideNote:.+?(?=([,}].*?\)))/g, match: /hideNote:.+?(?=([,}].*?\)))/g,
replace: (m, rest) => { replace: (m, rest) => {
const destructuringMatch = rest.match(/}=.+/); const destructuringMatch = rest.match(/}=.+/);
if (destructuringMatch == null) return "hideNote:!0"; if (destructuringMatch) {
return m; const defaultValueMatch = m.match(canonicalizeMatch(/hideNote:(\i)=!?\d/));
return defaultValueMatch ? `hideNote:${defaultValueMatch[1]}=!0` : m;
}
return "hideNote:!0";
} }
} }
}, },
@ -52,10 +57,10 @@ export default definePlugin({
} }
}, },
{ {
find: ".Messages.NOTE}", find: ".popularApplicationCommandIds,",
replacement: { replacement: {
match: /(?<=return \i\?)null(?=:\(0,\i\.jsxs)/, match: /lastSection:(!?\i)}\),/,
replace: "$self.patchPadding(arguments[0])" replace: "$&$self.patchPadding($1),"
} }
} }
], ],
@ -75,8 +80,8 @@ export default definePlugin({
} }
}, },
patchPadding(e: any) { patchPadding(lastSection: any) {
if (!e.lastSection) return; if (!lastSection) return;
return ( return (
<div className={UserPopoutSectionCssClasses.lastSection}></div> <div className={UserPopoutSectionCssClasses.lastSection}></div>
); );

View file

@ -82,7 +82,7 @@ export default definePlugin({
find: "this.renderArtisanalHack()", find: "this.renderArtisanalHack()",
replacement: [ replacement: [
{ // Fade in on layer { // Fade in on layer
match: /(?<=(\i)\.contextType=\i\.AccessibilityPreferencesContext;)/, match: /(?<=\((\i),"contextType",\i\.AccessibilityPreferencesContext\);)/,
replace: "$1=$self.Layer;", replace: "$1=$self.Layer;",
predicate: () => settings.store.disableFade predicate: () => settings.store.disableFade
}, },
@ -107,11 +107,11 @@ export default definePlugin({
], ],
predicate: () => settings.store.disableFade predicate: () => settings.store.disableFade
}, },
{ // Load menu stuff on hover, not on click { // Load menu TOC eagerly
find: "Messages.USER_SETTINGS_WITH_BUILD_OVERRIDE.format", find: "Messages.USER_SETTINGS_WITH_BUILD_OVERRIDE.format",
replacement: { replacement: {
match: /(?<=handleOpenSettingsContextMenu.{0,250}?\i\.el\(("[^"]+")\)\.then\([^;]*?("\d+").*?Messages\.USER_SETTINGS,)(?=onClick:)/, match: /(?<=(\i)\(this,"handleOpenSettingsContextMenu",.{0,100}?openContextMenuLazy.{0,100}?(await Promise\.all[^};]*?\)\)).*?,)(?=\1\(this)/,
replace: "onMouseEnter(){Vencord.Webpack.wreq.el($1).then(()=>Vencord.Webpack.wreq($2));}," replace: "(async ()=>$2)(),"
}, },
predicate: () => settings.store.eagerLoad predicate: () => settings.store.eagerLoad
}, },

View file

@ -49,7 +49,7 @@ export default definePlugin({
}, },
// Decoration modal module // Decoration modal module
{ {
find: ".decorationGridItem", find: ".decorationGridItem,",
replacement: [ replacement: [
{ {
match: /(?<==)\i=>{let{children.{20,100}decorationGridItem/, match: /(?<==)\i=>{let{children.{20,100}decorationGridItem/,
@ -61,8 +61,8 @@ export default definePlugin({
}, },
// Remove NEW label from decor avatar decorations // Remove NEW label from decor avatar decorations
{ {
match: /(?<=\.Section\.PREMIUM_PURCHASE&&\i;if\()(?<=avatarDecoration:(\i).+?)/, match: /(?<=\.Section\.PREMIUM_PURCHASE&&\i)(?<=avatarDecoration:(\i).+?)/,
replace: "$1.skuId===$self.SKU_ID||" replace: "||$1.skuId===$self.SKU_ID"
} }
] ]
}, },

View file

@ -29,7 +29,7 @@ export default definePlugin({
{ {
find: ".Messages.BOT_CALL_IDLE_DISCONNECT", find: ".Messages.BOT_CALL_IDLE_DISCONNECT",
replacement: { replacement: {
match: /,?(?=this\.idleTimeout=new \i\.Timeout)/, match: /,?(?=\i\(this,"idleTimeout",new \i\.Timeout\))/,
replace: ";return;" replace: ";return;"
} }
}, },

View file

@ -64,7 +64,7 @@ export default definePlugin({
} }
}, },
{ {
find: ".isStaff=()", find: '"isStaff",',
predicate: () => settings.store.enableIsStaff, predicate: () => settings.store.enableIsStaff,
replacement: [ replacement: [
{ {

View file

@ -277,7 +277,7 @@ export default definePlugin({
} }
}, },
{ {
find: '.displayName="UserSettingsProtoStore"', find: '"UserSettingsProtoStore"',
replacement: [ replacement: [
{ {
// Overwrite incoming connection settings proto with our local settings // Overwrite incoming connection settings proto with our local settings
@ -388,6 +388,14 @@ export default definePlugin({
match: /\i\.\i\.isPremium\(\i\.\i\.getCurrentUser\(\)\)/, match: /\i\.\i\.isPremium\(\i\.\i\.getCurrentUser\(\)\)/,
replace: "true" replace: "true"
} }
},
// Make all Soundboard sounds available
{
find: 'type:"GUILD_SOUNDBOARD_SOUND_CREATE"',
replacement: {
match: /(?<=type:"(?:SOUNDBOARD_SOUNDS_RECEIVED|GUILD_SOUNDBOARD_SOUND_CREATE|GUILD_SOUNDBOARD_SOUND_UPDATE|GUILD_SOUNDBOARD_SOUNDS_UPDATE)".+?available:)\i\.available/g,
replace: "true"
}
} }
], ],

View file

@ -29,10 +29,10 @@ export default definePlugin({
authors: [Devs.Ven], authors: [Devs.Ven],
patches: [{ patches: [{
find: ".handleSelectGIF=", find: '"handleSelectGIF",',
replacement: { replacement: {
match: /\.handleSelectGIF=(\i)=>\{/, match: /"handleSelectGIF",(\i)=>\{/,
replace: ".handleSelectGIF=$1=>{if (!this.props.className) return $self.handleSelect($1);" replace: '"handleSelectGIF",$1=>{if (!this.props.className) return $self.handleSelect($1);'
} }
}], }],

View file

@ -210,10 +210,10 @@ export default definePlugin({
patches: [ patches: [
{ {
find: '.displayName="LocalActivityStore"', find: '="LocalActivityStore",',
replacement: [ replacement: [
{ {
match: /HANG_STATUS.+?(?=!\i\(\i,\i\)&&)(?<=(\i)\.push.+?)/, match: /HANG_STATUS.+?(?=!\i\(\)\(\i,\i\)&&)(?<=(\i)\.push.+?)/,
replace: (m, activities) => `${m}${activities}=${activities}.filter($self.isActivityNotIgnored);` replace: (m, activities) => `${m}${activities}=${activities}.filter($self.isActivityNotIgnored);`
} }
] ]

View file

@ -23,7 +23,7 @@ import { makeRange } from "@components/PluginSettings/components";
import { debounce } from "@shared/debounce"; import { debounce } from "@shared/debounce";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { Menu, React, ReactDOM } from "@webpack/common"; import { Menu, ReactDOM } from "@webpack/common";
import type { Root } from "react-dom/client"; import type { Root } from "react-dom/client";
import { Magnifier, MagnifierProps } from "./components/Magnifier"; import { Magnifier, MagnifierProps } from "./components/Magnifier";
@ -168,7 +168,7 @@ export default definePlugin({
}, },
{ {
find: "handleImageLoad=", find: ".handleImageLoad)",
replacement: [ replacement: [
{ {
match: /placeholderVersion:\i,/, match: /placeholderVersion:\i,/,

View file

@ -81,11 +81,11 @@ export default definePlugin({
find: ".LOADING_DID_YOU_KNOW}", find: ".LOADING_DID_YOU_KNOW}",
replacement: [ replacement: [
{ {
match: /\._loadingText=function\(\)\{/, match: /"_loadingText",function\(\)\{/,
replace: "$&return $self.quote;", replace: "$&return $self.quote;",
}, },
{ {
match: /\._eventLoadingText=function\(\)\{/, match: /"_eventLoadingText",function\(\)\{/,
replace: "$&return $self.quote;", replace: "$&return $self.quote;",
predicate: () => settings.store.replaceEvents predicate: () => settings.store.replaceEvents
} }

View file

@ -225,7 +225,7 @@ export default definePlugin({
{ {
// MessageStore // MessageStore
// Module 171447 // Module 171447
find: "displayName=\"MessageStore\"", find: '"MessageStore"',
replacement: [ replacement: [
{ {
// Add deleted=true to all target messages in the MESSAGE_DELETE event // Add deleted=true to all target messages in the MESSAGE_DELETE event
@ -380,7 +380,7 @@ export default definePlugin({
{ {
// ReferencedMessageStore // ReferencedMessageStore
// Module 778667 // Module 778667
find: "displayName=\"ReferencedMessageStore\"", find: '"ReferencedMessageStore"',
replacement: [ replacement: [
{ {
match: /MESSAGE_DELETE:function\((\i)\).+?},/, match: /MESSAGE_DELETE:function\((\i)\).+?},/,

View file

@ -38,8 +38,8 @@ export default definePlugin({
] ]
}, },
...[ ...[
'displayName="MessageStore"', '="MessageStore",',
'displayName="ReadStateStore"' '"displayName","ReadStateStore")'
].map(find => ({ ].map(find => ({
find, find,
predicate: () => Settings.plugins.NoBlockedMessages.ignoreBlockedMessages === true, predicate: () => Settings.plugins.NoBlockedMessages.ignoreBlockedMessages === true,

View file

@ -27,7 +27,7 @@ export default definePlugin({
{ {
find: '.ensureModule("discord_rpc")', find: '.ensureModule("discord_rpc")',
replacement: { replacement: {
match: /\.ensureModule\("discord_rpc"\)\.then\(\(.+?\)\)}/, match: /\.ensureModule\("discord_rpc"\)\.then\(\(.+?\)}\)}/,
replace: '.ensureModule("discord_rpc")}', replace: '.ensureModule("discord_rpc")}',
}, },
}, },

View file

@ -31,9 +31,9 @@ interface ColorPickerWithSwatchesProps {
} }
const ColorPicker = findComponentByCodeLazy<ColorPickerProps>(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); const ColorPicker = findComponentByCodeLazy<ColorPickerProps>(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)");
const ColorPickerWithSwatches = findComponentByCodeLazy<ColorPickerWithSwatchesProps>(".presets,", "customColor:"); const ColorPickerWithSwatches = findComponentByCodeLazy<ColorPickerWithSwatchesProps>("presets,", "customColor:");
export const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}el\("(.+?)"\).{0,50}"UserSettings"/); export const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}Promise\.all\((\[\i\.\i\(".+?"\).+?\])\).then\(\i\.bind\(\i,"(.+?)"\)\).{0,50}"UserSettings"/);
const cl = classNameFactory("vc-pindms-modal-"); const cl = classNameFactory("vc-pindms-modal-");
@ -53,7 +53,7 @@ function useCategory(categoryId: string | null, initalChannelId: string | null)
setCategory({ setCategory({
id: Toasts.genId(), id: Toasts.genId(),
name: `Pin Category ${categories.length + 1}`, name: `Pin Category ${categories.length + 1}`,
color: 10070709, color: DEFAULT_COLOR,
collapsed: false, collapsed: false,
channels: [initalChannelId] channels: [initalChannelId]
}); });

View file

@ -8,7 +8,7 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/Co
import { Menu } from "@webpack/common"; import { Menu } from "@webpack/common";
import { addChannelToCategory, canMoveChannelInDirection, categories, isPinned, moveChannel, removeChannelFromCategory } from "../data"; import { addChannelToCategory, canMoveChannelInDirection, categories, isPinned, moveChannel, removeChannelFromCategory } from "../data";
import { forceUpdate, settings } from "../index"; import { forceUpdate, PinOrder, settings } from "../index";
import { openCategoryModal } from "./CreateCategoryModal"; import { openCategoryModal } from "./CreateCategoryModal";
function createPinMenuItem(channelId: string) { function createPinMenuItem(channelId: string) {
@ -52,7 +52,7 @@ function createPinMenuItem(channelId: string) {
/> />
{ {
!settings.store.sortDmsByNewestMessage && canMoveChannelInDirection(channelId, -1) && ( settings.store.pinOrder === PinOrder.Custom && canMoveChannelInDirection(channelId, -1) && (
<Menu.MenuItem <Menu.MenuItem
id="move-up" id="move-up"
label="Move Up" label="Move Up"
@ -62,7 +62,7 @@ function createPinMenuItem(channelId: string) {
} }
{ {
!settings.store.sortDmsByNewestMessage && canMoveChannelInDirection(channelId, 1) && ( settings.store.pinOrder === PinOrder.Custom && canMoveChannelInDirection(channelId, 1) && (
<Menu.MenuItem <Menu.MenuItem
id="move-down" id="move-down"
label="Move Down" label="Move Down"

View file

@ -34,11 +34,19 @@ const PrivateChannelSortStore = findStoreLazy("PrivateChannelSortStore") as { ge
export let instance: any; export let instance: any;
export const forceUpdate = () => instance?.props?._forceUpdate?.(); export const forceUpdate = () => instance?.props?._forceUpdate?.();
export const enum PinOrder {
LastMessage,
Custom
}
export const settings = definePluginSettings({ export const settings = definePluginSettings({
sortDmsByNewestMessage: { pinOrder: {
type: OptionType.BOOLEAN, type: OptionType.SELECT,
description: "Sort DMs by newest message", description: "Which order should pinned DMs be displayed in?",
default: false, options: [
{ label: "Most recent message", value: PinOrder.LastMessage, default: true },
{ label: "Custom (right click channels to reorder)", value: PinOrder.Custom }
],
onChange: () => forceUpdate() onChange: () => forceUpdate()
}, },
@ -61,11 +69,6 @@ export default definePlugin({
{ {
find: ".privateChannelsHeaderContainer,", find: ".privateChannelsHeaderContainer,",
replacement: [ replacement: [
// Init
{
match: /(?<=componentDidMount\(\){).{1,100}scrollToChannel/,
replace: "$self._instance = this;$&"
},
{ {
// Filter out pinned channels from the private channel list // Filter out pinned channels from the private channel list
match: /(?<=\i,{channels:\i,)privateChannelIds:(\i)/, match: /(?<=\i,{channels:\i,)privateChannelIds:(\i)/,
@ -79,11 +82,11 @@ export default definePlugin({
// Rendering // Rendering
{ {
match: /this\.renderDM=\(.+?(\i\.default),{channel.+?this.renderRow=(\i)=>{/, match: /"renderRow",(\i)=>{(?<="renderDM",.+?(\i\.default),\{channel:.+?)/,
replace: "$&if($self.isChannelIndex($2.section, $2.row))return $self.renderChannel($2.section,$2.row,$1);" replace: "$&if($self.isChannelIndex($1.section, $1.row))return $self.renderChannel($1.section,$1.row,$2);"
}, },
{ {
match: /this\.renderSection=(\i)=>{/, match: /"renderSection",(\i)=>{/,
replace: "$&if($self.isCategoryIndex($1.section))return $self.renderCategory($1);" replace: "$&if($self.isCategoryIndex($1.section))return $self.renderCategory($1);"
}, },
{ {
@ -93,11 +96,11 @@ export default definePlugin({
// Fix Row Height // Fix Row Height
{ {
match: /(?<=this\.getRowHeight=.{1,100}return 1===)\i/, match: /(?<="getRowHeight",.{1,100}return 1===)\i/,
replace: "($&-$self.categoryLen())" replace: "($&-$self.categoryLen())"
}, },
{ {
match: /this.getRowHeight=\((\i),(\i)\)=>{/, match: /"getRowHeight",\((\i),(\i)\)=>{/,
replace: "$&if($self.isChannelHidden($1,$2))return 0;" replace: "$&if($self.isChannelHidden($1,$2))return 0;"
}, },
@ -164,12 +167,15 @@ export default definePlugin({
getSections, getSections,
getAllUncollapsedChannels, getAllUncollapsedChannels,
requireSettingsMenu, requireSettingsMenu,
makeProps(instance, { sections }: { sections: number[]; }) { makeProps(instance, { sections }: { sections: number[]; }) {
this._instance = instance;
this.sections = sections; this.sections = sections;
this.sections.splice(1, 0, ...this.getPinCount(instance.props.privateChannelIds || [])); this.sections.splice(1, 0, ...this.getSections());
if (this.instance?.props?.privateChannelIds?.length === 0) { if (this.instance?.props?.privateChannelIds?.length === 0) {
// dont render direct messages header
this.sections[this.sections.length - 1] = 0; this.sections[this.sections.length - 1] = 0;
} }
@ -199,10 +205,6 @@ export default definePlugin({
return (sectionHeaderSizePx + sections.reduce((acc, v) => acc += v + 44, 0) + DEFAULT_CHUNK_SIZE) * 1.5; return (sectionHeaderSizePx + sections.reduce((acc, v) => acc += v + 44, 0) + DEFAULT_CHUNK_SIZE) * 1.5;
}, },
getPinCount(channelIds: string[]) {
return channelIds.length ? this.getSections() : [];
},
isCategoryIndex(sectionIndex: number) { isCategoryIndex(sectionIndex: number) {
return this.sections && sectionIndex > 0 && sectionIndex < this.sections.length - 1; return this.sections && sectionIndex > 0 && sectionIndex < this.sections.length - 1;
}, },
@ -211,7 +213,7 @@ export default definePlugin({
if (settings.store.dmSectioncollapsed && sectionIndex !== 0) if (settings.store.dmSectioncollapsed && sectionIndex !== 0)
return true; return true;
const cat = categories[sectionIndex - 1]; const cat = categories[sectionIndex - 1];
return this.isCategoryIndex(sectionIndex) && (cat.channels.length === 0 || cat?.channels[channelIndex]); return this.isCategoryIndex(sectionIndex) && (cat?.channels?.length === 0 || cat?.channels[channelIndex]);
}, },
isDMSectioncollapsed() { isDMSectioncollapsed() {
@ -219,7 +221,6 @@ export default definePlugin({
}, },
collapseDMList() { collapseDMList() {
// console.log("HI");
settings.store.dmSectioncollapsed = !settings.store.dmSectioncollapsed; settings.store.dmSectioncollapsed = !settings.store.dmSectioncollapsed;
forceUpdate(); forceUpdate();
}, },
@ -350,7 +351,7 @@ export default definePlugin({
getCategoryChannels(category: Category) { getCategoryChannels(category: Category) {
if (category.channels.length === 0) return []; if (category.channels.length === 0) return [];
if (settings.store.sortDmsByNewestMessage) { if (settings.store.pinOrder === PinOrder.LastMessage) {
return PrivateChannelSortStore.getPrivateChannelIds().filter(c => category.channels.includes(c)); return PrivateChannelSortStore.getPrivateChannelIds().filter(c => category.channels.includes(c));
} }

View file

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import "./style.css";
import { addServerListElement, removeServerListElement, ServerListRenderPosition } from "@api/ServerList"; import { addServerListElement, removeServerListElement, ServerListRenderPosition } from "@api/ServerList";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
@ -49,9 +51,11 @@ const ReadAllButton = () => (
<Button <Button
onClick={onClick} onClick={onClick}
size={Button.Sizes.MIN} size={Button.Sizes.MIN}
color={Button.Colors.BRAND} color={Button.Colors.CUSTOM}
style={{ marginTop: "2px", marginBottom: "8px", marginLeft: "9px" }} className="vc-ranb-button"
>Read all</Button> >
Read All
</Button>
); );
export default definePlugin({ export default definePlugin({

View file

@ -0,0 +1,11 @@
.vc-ranb-button {
color: var(--interactive-normal);
padding: 0 0.5em;
margin-bottom: 0.5em;
width: 100%;
box-sizing: border-box;
}
.vc-ranb-button:hover {
color: var(--interactive-active);
}

View file

@ -59,7 +59,7 @@ export default definePlugin({
find: "GuildHomeFeedbackExperiment.definition.id", find: "GuildHomeFeedbackExperiment.definition.id",
replacement: [ replacement: [
{ {
match: /return{showFeedback:\i,setOnDismissedFeedback:(\i)}/, match: /return{showFeedback:.+?,setOnDismissedFeedback:(\i)}/,
replace: "return{showFeedback:false,setOnDismissedFeedback:$1}" replace: "return{showFeedback:false,setOnDismissedFeedback:$1}"
} }
] ]

View file

@ -30,9 +30,9 @@ export default definePlugin({
patches: [ patches: [
{ {
find: ".removeObscurity=", find: ".removeObscurity,",
replacement: { replacement: {
match: /(?<=\.removeObscurity=(\i)=>{)/, match: /(?<="removeObscurity",(\i)=>{)/,
replace: (_, event) => `$self.reveal(${event});` replace: (_, event) => `$self.reveal(${event});`
} }
} }

View file

@ -16,7 +16,7 @@ export default definePlugin({
{ {
find: "call_ringing_beat\"", find: "call_ringing_beat\"",
replacement: { replacement: {
match: /500===\i\.random\(1,1e3\)/, match: /500===\i\(\)\.random\(1,1e3\)/,
replace: "true" replace: "true"
} }
}, },

View file

@ -138,7 +138,7 @@ export default definePlugin({
all: true, all: true,
// Render null instead of the buttons if the channel is hidden // Render null instead of the buttons if the channel is hidden
replacement: { replacement: {
match: /(?<=renderOpenChatButton=\(\)=>{)/, match: /(?<="renderOpenChatButton",\(\)=>{)/,
replace: "if($self.isHiddenChannel(this.props.channel))return null;" replace: "if($self.isHiddenChannel(this.props.channel))return null;"
} }
}, },
@ -191,10 +191,10 @@ export default definePlugin({
}, },
{ {
// Hide the new version of unreads box for hidden channels // Hide the new version of unreads box for hidden channels
find: '.displayName="ChannelListUnreadsStore"', find: '="ChannelListUnreadsStore",',
replacement: { replacement: {
match: /(?<=if\(null==(\i))(?=.{0,160}?getHasImportantUnread\)\(\i\))/g, // Global because Discord has multiple methods like that in the same module match: /(?=&&\(0,\i\.getHasImportantUnread\)\((\i)\))/g, // Global because Discord has multiple methods like that in the same module
replace: (_, channel) => `||$self.isHiddenChannel(${channel})` replace: (_, channel) => `&&!$self.isHiddenChannel(${channel})`
} }
}, },
{ {
@ -218,19 +218,19 @@ export default definePlugin({
find: "Missing channel in Channel.renderHeaderToolbar", find: "Missing channel in Channel.renderHeaderToolbar",
replacement: [ replacement: [
{ {
match: /(?<=renderHeaderToolbar=\(\)=>{.+?case \i\.\i\.GUILD_TEXT:)(?=.+?(\i\.push.{0,50}channel:(\i)},"notifications"\)\)))(?<=isLurking:(\i).+?)/, match: /(?<="renderHeaderToolbar",\(\)=>{.+?case \i\.\i\.GUILD_TEXT:)(?=.+?(\i\.push.{0,50}channel:(\i)},"notifications"\)\)))(?<=isLurking:(\i).+?)/,
replace: (_, pushNotificationButtonExpression, channel, isLurking) => `if(!${isLurking}&&$self.isHiddenChannel(${channel})){${pushNotificationButtonExpression};break;}` replace: (_, pushNotificationButtonExpression, channel, isLurking) => `if(!${isLurking}&&$self.isHiddenChannel(${channel})){${pushNotificationButtonExpression};break;}`
}, },
{ {
match: /(?<=renderHeaderToolbar=\(\)=>{.+?case \i\.\i\.GUILD_MEDIA:)(?=.+?(\i\.push.{0,40}channel:(\i)},"notifications"\)\)))(?<=isLurking:(\i).+?)/, match: /(?<="renderHeaderToolbar",\(\)=>{.+?case \i\.\i\.GUILD_MEDIA:)(?=.+?(\i\.push.{0,40}channel:(\i)},"notifications"\)\)))(?<=isLurking:(\i).+?)/,
replace: (_, pushNotificationButtonExpression, channel, isLurking) => `if(!${isLurking}&&$self.isHiddenChannel(${channel})){${pushNotificationButtonExpression};break;}` replace: (_, pushNotificationButtonExpression, channel, isLurking) => `if(!${isLurking}&&$self.isHiddenChannel(${channel})){${pushNotificationButtonExpression};break;}`
}, },
{ {
match: /renderMobileToolbar=\(\)=>{.+?case \i\.\i\.GUILD_DIRECTORY:(?<=let{channel:(\i).+?)/, match: /"renderMobileToolbar",\(\)=>{.+?case \i\.\i\.GUILD_DIRECTORY:(?<=let{channel:(\i).+?)/,
replace: (m, channel) => `${m}if($self.isHiddenChannel(${channel}))break;` replace: (m, channel) => `${m}if($self.isHiddenChannel(${channel}))break;`
}, },
{ {
match: /(?<=renderHeaderBar=\(\)=>{.+?hideSearch:(\i)\.isDirectory\(\))/, match: /(?<="renderHeaderBar",\(\)=>{.+?hideSearch:(\i)\.isDirectory\(\))/,
replace: (_, channel) => `||$self.isHiddenChannel(${channel})` replace: (_, channel) => `||$self.isHiddenChannel(${channel})`
}, },
{ {
@ -442,7 +442,7 @@ export default definePlugin({
} }
}, },
{ {
find: '.displayName="GuildChannelStore"', find: '="GuildChannelStore",',
replacement: [ replacement: [
{ {
// Make GuildChannelStore contain hidden channels // Make GuildChannelStore contain hidden channels
@ -465,7 +465,7 @@ export default definePlugin({
} }
}, },
{ {
find: '.displayName="NowPlayingViewStore"', find: '="NowPlayingViewStore",',
replacement: { replacement: {
// Make active now voice states on hidden channels // Make active now voice states on hidden channels
match: /(getVoiceStateForUser.{0,150}?)&&\i\.\i\.canWithPartialContext.{0,20}VIEW_CHANNEL.+?}\)(?=\?)/, match: /(getVoiceStateForUser.{0,150}?)&&\i\.\i\.canWithPartialContext.{0,20}VIEW_CHANNEL.+?}\)(?=\?)/,

View file

@ -51,7 +51,7 @@ export default definePlugin({
}, },
}, },
{ {
find: '.displayName="SpotifyStore"', find: '"displayName","SpotifyStore")',
replacement: [ replacement: [
{ {
predicate: () => settings.store.noSpotifyAutoPause, predicate: () => settings.store.noSpotifyAutoPause,

View file

@ -98,8 +98,8 @@ export default definePlugin({
{ {
find: ".popularApplicationCommandIds,", find: ".popularApplicationCommandIds,",
replacement: { replacement: {
match: /\(0,\i\.jsx\)\(\i\.\i,{user:\i,setNote/, match: /applicationId:\i\.id}\),(?=.{0,50}setNote:\i)/,
replace: "$self.patchPopout(arguments[0]),$&", replace: "$&$self.patchPopout(arguments[0]),",
} }
}, },
// below username // below username

View file

@ -71,7 +71,7 @@ export default definePlugin({
}, },
// Prevent the MediaEngineStore from overwriting our LocalVolumes above 200 with the ones the Discord Audio Context Settings sync sends // Prevent the MediaEngineStore from overwriting our LocalVolumes above 200 with the ones the Discord Audio Context Settings sync sends
{ {
find: '.displayName="MediaEngineStore"', find: '="MediaEngineStore",',
replacement: [ replacement: [
{ {
match: /(\.settings\.audioContextSettings.+?)(\i\[\i\])=(\i\.volume)(.+?setLocalVolume\(\i,).+?\)/, match: /(\.settings\.audioContextSettings.+?)(\i\[\i\])=(\i\.volume)(.+?setLocalVolume\(\i,).+?\)/,

View file

@ -195,7 +195,7 @@ export default definePlugin({
// Add back "Show My Camera" context menu // Add back "Show My Camera" context menu
{ {
find: '.default("MediaEngineWebRTC");', find: '"MediaEngineWebRTC");',
replacement: { replacement: {
match: /supports\(\i\)\{switch\(\i\)\{case (\i).Features/, match: /supports\(\i\)\{switch\(\i\)\{case (\i).Features/,
replace: "$&.DISABLE_VIDEO:return true;case $1.Features" replace: "$&.DISABLE_VIDEO:return true;case $1.Features"

View file

@ -93,28 +93,30 @@ export default definePlugin({
description: "Renders the avatars of users who reacted to a message", description: "Renders the avatars of users who reacted to a message",
authors: [Devs.Ven, Devs.KannaDev, Devs.newwares], authors: [Devs.Ven, Devs.KannaDev, Devs.newwares],
patches: [{ patches: [
find: ",reactionRef:", {
replacement: { find: ",reactionRef:",
match: /(\i)\?null:\(0,\i\.jsx\)\(\i\.\i,{className:\i\.reactionCount,.*?}\),/, replacement: {
replace: "$&$1?null:$self.renderUsers(this.props)," match: /(\i)\?null:\(0,\i\.jsx\)\(\i\.\i,{className:\i\.reactionCount,.*?}\),/,
} replace: "$&$1?null:$self.renderUsers(this.props),"
}, { }
find: '.displayName="MessageReactionsStore";', }, {
replacement: { find: '"MessageReactionsStore"',
match: /(?<=CONNECTION_OPEN:function\(\){)(\i)={}/, replacement: {
replace: "$&;$self.reactions=$1" match: /(?<=CONNECTION_OPEN:function\(\){)(\i)={}/,
} replace: "$&;$self.reactions=$1"
}, }
{ },
{
find: "cleanAutomaticAnchor(){", find: "cleanAutomaticAnchor(){",
replacement: { replacement: {
match: /this\.automaticAnchor=null,this\.messageFetchAnchor=null,/, match: /constructor\(\i\)\{(?=.{0,100}automaticAnchor)/,
replace: "$&$self.setScrollObj(this)," replace: "$&$self.setScrollObj(this);"
}
} }
}
], ],
setScrollObj(scroll: any) { setScrollObj(scroll: any) {
Scroll = scroll; Scroll = scroll;
}, },

View file

@ -44,7 +44,6 @@ export let PermissionStore: GenericStore;
export let GuildChannelStore: GenericStore; export let GuildChannelStore: GenericStore;
export let ReadStateStore: GenericStore; export let ReadStateStore: GenericStore;
export let PresenceStore: GenericStore; export let PresenceStore: GenericStore;
export let PoggerModeSettingsStore: GenericStore;
export let GuildStore: t.GuildStore; export let GuildStore: t.GuildStore;
export let UserStore: Stores.UserStore & t.FluxStore; export let UserStore: Stores.UserStore & t.FluxStore;

View file

@ -110,13 +110,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) continue; if (!mod?.exports || mod.exports === window) 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 && filter(mod.exports.default)) { if (mod.exports.default && mod.exports.default !== window && filter(mod.exports.default)) {
const found = mod.exports.default; const found = mod.exports.default;
return isWaitFor ? [found, key] : found; return isWaitFor ? [found, key] : found;
} }
@ -408,10 +408,11 @@ export function findExportedComponentLazy<T extends object = any>(...props: stri
/** /**
* Extract and load chunks using their entry point * Extract and load chunks using their entry point
* @param code An array of all the code the module factory containing the entry point (as of using it to load chunks) must include * @param code An array of all the code the module factory containing the lazy chunk loading must include
* @param matcher A RegExp that returns the entry point id as the first capture group. Defaults to a matcher that captures the first entry point found in the module factory * @param matcher A RegExp that returns the chunk ids array as the first capture group and the entry point id as the second. Defaults to a matcher that captures the lazy chunk loading found in the module factory
* @returns A promise that resolves when the chunks were loaded
*/ */
export async function extractAndLoadChunks(code: string[], matcher: RegExp = /\.el\("(.+?)"\)(?<=(\i)\.el.+?)\.then\(\2\.bind\(\2,"\1"\)\)/) { export async function extractAndLoadChunks(code: string[], matcher: RegExp = /Promise\.all\((\[\i\.\i\(".+?"\).+?\])\).then\(\i\.bind\(\i,"(.+?)"\)\)/) {
const module = findModuleFactory(...code); const module = findModuleFactory(...code);
if (!module) { if (!module) {
const err = new Error("extractAndLoadChunks: Couldn't find module factory"); const err = new Error("extractAndLoadChunks: Couldn't find module factory");
@ -432,9 +433,9 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = /\.
return; return;
} }
const [, id] = match; const [, rawChunkIds, entryPointId] = match;
if (!id || !Number(id)) { if (!rawChunkIds || Number.isNaN(entryPointId)) {
const err = new Error("extractAndLoadChunks: Matcher didn't return a capturing group with the entry point, or the entry point returned wasn't a number"); const err = new Error("extractAndLoadChunks: Matcher didn't return a capturing group with the chunk ids array, or the entry point id returned as the second group wasn't a number");
logger.warn(err, "Code:", code, "Matcher:", matcher); logger.warn(err, "Code:", code, "Matcher:", matcher);
// Strict behaviour in DevBuilds to fail early and make sure the issue is found // Strict behaviour in DevBuilds to fail early and make sure the issue is found
@ -444,19 +445,21 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = /\.
return; return;
} }
await (wreq as any).el(id); const chunkIds = Array.from(rawChunkIds.matchAll(/\("(.+?)"\)/g)).map((m: any) => m[1]);
return wreq(id as any);
await Promise.all(chunkIds.map(id => wreq.e(id)));
wreq(entryPointId);
} }
/** /**
* This is just a wrapper around {@link extractAndLoadChunks} to make our reporter test for your webpack finds. * This is just a wrapper around {@link extractAndLoadChunks} to make our reporter test for your webpack finds.
* *
* Extract and load chunks using their entry point * Extract and load chunks using their entry point
* @param code An array of all the code the module factory containing the entry point (as of using it to load chunks) must include * @param code An array of all the code the module factory containing the lazy chunk loading must include
* @param matcher A RegExp that returns the entry point id as the first capture group. Defaults to a matcher that captures the first entry point found in the module factory * @param matcher A RegExp that returns the chunk ids array as the first capture group and the entry point id as the second. Defaults to a matcher that captures the lazy chunk loading found in the module factory
* @returns A function that loads the chunks on first call * @returns A function that returns a promise that resolves when the chunks were loaded, on first call
*/ */
export function extractAndLoadChunksLazy(code: string[], matcher: RegExp = /\.el\("(.+?)"\)(?<=(\i)\.el.+?)\.then\(\2\.bind\(\2,"\1"\)\)/) { export function extractAndLoadChunksLazy(code: string[], matcher: RegExp = /Promise\.all\((\[\i\.\i\(".+?"\).+?\])\).then\(\i\.bind\(\i,"(.+?)"\)\)/) {
if (IS_DEV) lazyWebpackSearchHistory.push(["extractAndLoadChunks", [code, matcher]]); if (IS_DEV) lazyWebpackSearchHistory.push(["extractAndLoadChunks", [code, matcher]]);
return () => extractAndLoadChunks(code, matcher); return () => extractAndLoadChunks(code, matcher);