diff --git a/src/api/ServerList.ts b/src/api/ServerList.ts
new file mode 100644
index 00000000..d3a9a110
--- /dev/null
+++ b/src/api/ServerList.ts
@@ -0,0 +1,55 @@
+/*
+ * 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 .
+*/
+
+import Logger from "../utils/Logger";
+
+const logger = new Logger("ServerListAPI");
+
+export enum ServerListRenderPosition {
+ Above,
+ In,
+}
+
+const renderFunctionsAbove = new Set();
+const renderFunctionsIn = new Set();
+
+function getRenderFunctions(position: ServerListRenderPosition) {
+ return position === ServerListRenderPosition.Above ? renderFunctionsAbove : renderFunctionsIn;
+}
+
+export function addServerListElement(position: ServerListRenderPosition, renderFunction: Function) {
+ getRenderFunctions(position).add(renderFunction);
+}
+
+export function removeServerListElement(position: ServerListRenderPosition, renderFunction: Function) {
+ getRenderFunctions(position).delete(renderFunction);
+}
+
+export const renderAll = (position: ServerListRenderPosition) => {
+ const ret: Array = [];
+
+ for (const renderFunction of getRenderFunctions(position)) {
+ try {
+ ret.unshift(renderFunction());
+ } catch (e) {
+ logger.error("Failed to render server list element:", e);
+ }
+ }
+
+ return ret;
+};
diff --git a/src/api/index.ts b/src/api/index.ts
index bde4b3e7..98fc6a4a 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -22,6 +22,7 @@ import * as $DataStore from "./DataStore";
import * as $MessageAccessories from "./MessageAccessories";
import * as $MessageEventsAPI from "./MessageEvents";
import * as $Notices from "./Notices";
+import * as $ServerList from "./ServerList";
/**
* An API allowing you to listen to Message Clicks or run your own logic
@@ -62,5 +63,9 @@ const MessageAccessories = $MessageAccessories;
* An API allowing you to add badges to user profiles
*/
const Badges = $Badges;
+/**
+ * An API allowing you to add custom elements to the server list
+ */
+const ServerList = $ServerList;
-export { Badges, Commands, DataStore, MessageAccessories, MessageEvents, Notices };
+export { Badges, Commands, DataStore, MessageAccessories, MessageEvents, Notices, ServerList };
diff --git a/src/plugins/apiServerList.ts b/src/plugins/apiServerList.ts
new file mode 100644
index 00000000..134870e2
--- /dev/null
+++ b/src/plugins/apiServerList.ts
@@ -0,0 +1,42 @@
+/*
+ * 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 .
+*/
+
+import { Devs } from "../utils/constants";
+import definePlugin from "../utils/types";
+
+export default definePlugin({
+ name: "ServerListAPI",
+ authors: [Devs.kemo],
+ description: "Api required for plugins that modify the server list",
+ patches: [
+ {
+ find: "Messages.DISCODO_DISABLED",
+ replacement: {
+ match: /(Messages\.DISCODO_DISABLED\);return)(.*?homeIcon.*?)(\}function)/,
+ replace: "$1[$2].concat(Vencord.Api.ServerList.renderAll(Vencord.Api.ServerList.ServerListRenderPosition.Above))$3"
+ }
+ },
+ {
+ find: "Messages.SERVERS",
+ replacement: {
+ match: /(Messages\.SERVERS,children:)(.+?default:return null\}\}\)\))/,
+ replace: "$1Vencord.Api.ServerList.renderAll(Vencord.Api.ServerList.ServerListRenderPosition.In).concat($2)"
+ }
+ }
+ ]
+});
diff --git a/src/plugins/readAllNotificationsButton.tsx b/src/plugins/readAllNotificationsButton.tsx
new file mode 100644
index 00000000..615702b4
--- /dev/null
+++ b/src/plugins/readAllNotificationsButton.tsx
@@ -0,0 +1,71 @@
+/*
+ * 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 .
+*/
+
+import { addServerListElement, removeServerListElement, ServerListRenderPosition } from "../api/ServerList";
+import { Devs } from "../utils/constants";
+import definePlugin from "../utils/types";
+import { Button, FluxDispatcher, GuildChannelStore, GuildStore, React, ReadStateStore } from "../webpack/common";
+
+function onClick() {
+ const channels: Array = [];
+
+ Object.values(GuildStore.getGuilds()).forEach(guild => {
+ GuildChannelStore.getChannels(guild.id).SELECTABLE.forEach((c: { channel: { id: string; }; }) => {
+ if (!ReadStateStore.hasUnread(c.channel.id)) return;
+
+ channels.push({
+ channelId: c.channel.id,
+ // messageId: c.channel?.lastMessageId,
+ messageId: ReadStateStore.lastMessageId(c.channel.id),
+ readStateType: 0
+ });
+ });
+ });
+
+ FluxDispatcher.dispatch({
+ type: "BULK_ACK",
+ context: "APP",
+ channels: channels
+ });
+}
+
+const ReadAllButton = () => (
+
+);
+
+export default definePlugin({
+ name: "ReadAllNotificationsButton",
+ description: "Read all server notifications with a single button click!",
+ authors: [Devs.kemo],
+ dependencies: ["ServerListAPI"],
+
+ renderReadAllButton: () => ,
+
+ start() {
+ addServerListElement(ServerListRenderPosition.In, this.renderReadAllButton);
+ },
+
+ stop() {
+ removeServerListElement(ServerListRenderPosition.In, this.renderReadAllButton);
+ }
+});
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 307de872..7f44ee0d 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -136,5 +136,9 @@ export const Devs = Object.freeze({
KraXen72: {
name: "KraXen72",
id: 379304073515499530n
+ },
+ kemo: {
+ name: "kemo",
+ id: 299693897859465228n
}
});
diff --git a/src/utils/discord.ts b/src/utils/discord.ts
index 75fb079c..7fc5064a 100644
--- a/src/utils/discord.ts
+++ b/src/utils/discord.ts
@@ -18,7 +18,7 @@
import { Guild } from "discord-types/general";
-import { ChannelStore, GuildStore,SelectedChannelStore } from "../webpack/common";
+import { ChannelStore, GuildStore, PrivateChannelsStore, SelectedChannelStore } from "../webpack/common";
export function getCurrentChannel() {
return ChannelStore.getChannel(SelectedChannelStore.getChannelId());
@@ -27,3 +27,7 @@ export function getCurrentChannel() {
export function getCurrentGuild(): Guild | undefined {
return GuildStore.getGuild(getCurrentChannel()?.guild_id);
}
+
+export function openPrivateChannel(userId: string) {
+ PrivateChannelsStore.openPrivateChannel(userId);
+}
diff --git a/src/webpack/common.tsx b/src/webpack/common.tsx
index 9645172b..5853e566 100644
--- a/src/webpack/common.tsx
+++ b/src/webpack/common.tsx
@@ -34,6 +34,9 @@ export const ReactDOM: typeof import("react-dom") = lazyWebpack(filters.byProps(
export const MessageStore = lazyWebpack(filters.byProps("getRawMessages")) as Omit & { getMessages(chanId: string): any; };
export const PermissionStore = lazyWebpack(filters.byProps("can", "getGuildPermissions"));
+export const PrivateChannelsStore = lazyWebpack(filters.byProps("openPrivateChannel"));
+export const GuildChannelStore = lazyWebpack(filters.byProps("getChannels"));
+export const ReadStateStore = lazyWebpack(filters.byProps("lastMessageId"));
export let GuildStore: Stores.GuildStore;
export let UserStore: Stores.UserStore;
export let SelectedChannelStore: Stores.SelectedChannelStore;