2023-04-14 20:26:46 -04:00
|
|
|
/*
|
|
|
|
* Vencord, a modification for Discord's desktop app
|
|
|
|
* Copyright (c) 2023 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";
|
|
|
|
import { Channel } from "discord-types/general";
|
|
|
|
|
2024-03-07 05:06:24 -05:00
|
|
|
import { contextMenus } from "./contextMenus";
|
2023-04-21 21:17:00 -04:00
|
|
|
import { getPinAt, isPinned, settings, snapshotArray, sortedSnapshot, usePinnedDms } from "./settings";
|
2023-04-14 20:26:46 -04:00
|
|
|
|
|
|
|
export default definePlugin({
|
|
|
|
name: "PinDMs",
|
|
|
|
description: "Allows you to pin private channels to the top of your DM list. To pin/unpin or reorder pins, right click DMs",
|
2024-03-13 16:59:09 -04:00
|
|
|
authors: [Devs.Ven],
|
2023-04-14 20:26:46 -04:00
|
|
|
|
2023-04-16 19:06:54 -04:00
|
|
|
settings,
|
2024-03-07 05:06:24 -05:00
|
|
|
contextMenus,
|
2023-04-14 20:26:46 -04:00
|
|
|
|
|
|
|
usePinCount(channelIds: string[]) {
|
|
|
|
const pinnedDms = usePinnedDms();
|
|
|
|
// See comment on 2nd patch for reasoning
|
|
|
|
return channelIds.length ? [pinnedDms.size] : [];
|
|
|
|
},
|
|
|
|
|
|
|
|
getChannel(channels: Record<string, Channel>, idx: number) {
|
|
|
|
return channels[getPinAt(idx)];
|
|
|
|
},
|
|
|
|
|
|
|
|
isPinned,
|
2023-04-21 21:17:00 -04:00
|
|
|
getSnapshot: sortedSnapshot,
|
2023-04-14 20:26:46 -04:00
|
|
|
|
|
|
|
getScrollOffset(channelId: string, rowHeight: number, padding: number, preRenderedChildren: number, originalOffset: number) {
|
|
|
|
if (!isPinned(channelId))
|
|
|
|
return (
|
|
|
|
(rowHeight + padding) * 2 // header
|
|
|
|
+ rowHeight * snapshotArray.length // pins
|
|
|
|
+ originalOffset // original pin offset minus pins
|
|
|
|
);
|
|
|
|
|
|
|
|
return rowHeight * (snapshotArray.indexOf(channelId) + preRenderedChildren) + padding;
|
|
|
|
},
|
|
|
|
|
|
|
|
patches: [
|
|
|
|
// Patch DM list
|
|
|
|
{
|
|
|
|
find: ".privateChannelsHeaderContainer,",
|
|
|
|
replacement: [
|
|
|
|
{
|
|
|
|
// filter Discord's privateChannelIds list to remove pins, and pass
|
|
|
|
// pinCount as prop. This needs to be here so that the entire DM list receives
|
|
|
|
// updates on pin/unpin
|
2023-10-25 11:34:23 -04:00
|
|
|
match: /(?<=\i,{channels:\i,)privateChannelIds:(\i),/,
|
2023-04-14 20:26:46 -04:00
|
|
|
replace: "privateChannelIds:$1.filter(c=>!$self.isPinned(c)),pinCount:$self.usePinCount($1),"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// sections is an array of numbers, where each element is a section and
|
|
|
|
// the number is the amount of rows. Add our pinCount in second place
|
|
|
|
// - Section 1: buttons for pages like Friends & Library
|
|
|
|
// - Section 2: our pinned dms
|
|
|
|
// - Section 3: the normal dm list
|
2023-10-25 11:34:23 -04:00
|
|
|
match: /(?<=renderRow:this\.renderRow,)sections:\[\i,/,
|
2023-04-14 20:26:46 -04:00
|
|
|
// For some reason, adding our sections when no private channels are ready yet
|
|
|
|
// makes DMs infinitely load. Thus usePinCount returns either a single element
|
|
|
|
// array with the count, or an empty array. Due to spreading, only in the former
|
|
|
|
// case will an element be added to the outer array
|
|
|
|
// Thanks for the fix, Strencher!
|
2023-10-25 11:34:23 -04:00
|
|
|
replace: "$&...this.props.pinCount??[],"
|
2023-04-14 20:26:46 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
// Patch renderSection (renders the header) to set the text to "Pinned DMs" instead of "Direct Messages"
|
|
|
|
// lookbehind is used to lookup parameter name. We could use arguments[0], but
|
|
|
|
// if children ever is wrapped in an iife, it will break
|
2023-10-25 11:34:23 -04:00
|
|
|
match: /children:(\i\.\i\.Messages.DIRECT_MESSAGES)(?<=renderSection=(\i)=>{.+?)/,
|
2023-04-14 20:26:46 -04:00
|
|
|
replace: "children:$2.section===1?'Pinned DMs':$1"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Patch channel lookup inside renderDM
|
|
|
|
// channel=channels[channelIds[row]];
|
2023-10-25 11:34:23 -04:00
|
|
|
match: /(?<=renderDM=\((\i),(\i)\)=>{.*?this.state,\i=\i\[\i\],\i=)((\i)\[\i\]);/,
|
2023-04-14 20:26:46 -04:00
|
|
|
// section 1 is us, manually get our own channel
|
|
|
|
// section === 1 ? getChannel(channels, row) : channels[channelIds[row]];
|
2023-10-25 11:34:23 -04:00
|
|
|
replace: "$1===1?$self.getChannel($4,$2):$3;"
|
2023-04-14 20:26:46 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
// Fix getRowHeight's check for whether this is the DMs section
|
2023-11-15 13:01:50 -05:00
|
|
|
// DMS (inlined) === section
|
|
|
|
match: /(?<=getRowHeight=\(.{2,50}?)1===\i/,
|
|
|
|
// DMS (inlined) === section - 1
|
|
|
|
replace: "$&-1"
|
2023-04-14 20:26:46 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
// Override scrollToChannel to properly account for pinned channels
|
2023-10-25 11:34:23 -04:00
|
|
|
match: /(?<=scrollTo\(\{to:\i\}\):\(\i\+=)(\d+)\*\(.+?(?=,)/,
|
2023-04-14 20:26:46 -04:00
|
|
|
replace: "$self.getScrollOffset(arguments[0],$1,this.props.padding,this.state.preRenderedChildren,$&)"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
|
|
|
|
// Fix Alt Up/Down navigation
|
|
|
|
{
|
2023-10-25 11:34:23 -04:00
|
|
|
find: ".Routes.APPLICATION_STORE&&",
|
2023-04-14 20:26:46 -04:00
|
|
|
replacement: {
|
2023-10-25 11:34:23 -04:00
|
|
|
// channelIds = __OVERLAY__ ? stuff : [...getStaticPaths(),...channelIds)]
|
|
|
|
match: /(?<=\i=__OVERLAY__\?\i:\[\.\.\.\i\(\),\.\.\.)\i/,
|
2023-04-14 20:26:46 -04:00
|
|
|
// ....concat(pins).concat(toArray(channelIds).filter(c => !isPinned(c)))
|
2023-10-25 11:34:23 -04:00
|
|
|
replace: "$self.getSnapshot().concat($&.filter(c=>!$self.isPinned(c)))"
|
2023-04-14 20:26:46 -04:00
|
|
|
}
|
2023-09-05 14:51:22 -04:00
|
|
|
},
|
|
|
|
// fix alt+shift+up/down
|
|
|
|
{
|
2023-10-25 11:34:23 -04:00
|
|
|
find: ".getFlattenedGuildIds()],",
|
2023-09-05 14:51:22 -04:00
|
|
|
replacement: {
|
2023-10-25 11:34:23 -04:00
|
|
|
match: /(?<=\i===\i\.ME\?)\i\.\i\.getPrivateChannelIds\(\)/,
|
2023-09-05 14:51:22 -04:00
|
|
|
replace: "$self.getSnapshot().concat($&.filter(c=>!$self.isPinned(c)))"
|
|
|
|
}
|
|
|
|
},
|
2023-04-14 20:26:46 -04:00
|
|
|
]
|
|
|
|
});
|