+ }
+
+ );
+};
diff --git a/src/equicordplugins/betterMicrophone.desktop/components/index.tsx b/src/equicordplugins/betterMicrophone.desktop/components/index.tsx
new file mode 100644
index 000000000..fb0c72d54
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/components/index.tsx
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./MicrophoneSettingsModal";
diff --git a/src/equicordplugins/betterMicrophone.desktop/constants/constants.ts b/src/equicordplugins/betterMicrophone.desktop/constants/constants.ts
new file mode 100644
index 000000000..961c3d20e
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/constants/constants.ts
@@ -0,0 +1,31 @@
+/*
+ * 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 .
+*/
+
+import { Devs } from "@utils/constants";
+
+import { types } from "../../philsPluginLibrary";
+
+export const PluginInfo = {
+ PLUGIN_NAME: "BetterMicrophone",
+ DESCRIPTION: "This plugin allows you to further customize your microphone.",
+ AUTHOR: {
+ ...Devs.philhk,
+ github: "https://github.com/philhk"
+ },
+ CONTRIBUTORS: {}
+} as const satisfies types.PluginInfo;
diff --git a/src/equicordplugins/betterMicrophone.desktop/constants/index.ts b/src/equicordplugins/betterMicrophone.desktop/constants/index.ts
new file mode 100644
index 000000000..c7b948abd
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/constants/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./constants";
diff --git a/src/equicordplugins/betterMicrophone.desktop/index.tsx b/src/equicordplugins/betterMicrophone.desktop/index.tsx
new file mode 100644
index 000000000..070cdb5b3
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/index.tsx
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+*/
+
+import { PluginAuthor, PluginDef } from "@utils/types";
+
+import { addSettingsPanelButton, Emitter, MicrophoneSettingsIcon, removeSettingsPanelButton } from "../philsPluginLibrary";
+import { PluginInfo } from "./constants";
+import { openMicrophoneSettingsModal } from "./modals";
+import { MicrophonePatcher } from "./patchers";
+import { initMicrophoneStore } from "./stores";
+
+export default new class Plugin implements PluginDef {
+ readonly name: string;
+ readonly description: string;
+ readonly authors: PluginAuthor[];
+ readonly dependencies: string[];
+
+ public microphonePatcher?: MicrophonePatcher;
+
+ constructor() {
+ this.name = PluginInfo.PLUGIN_NAME;
+ this.description = PluginInfo.DESCRIPTION;
+ this.authors = [PluginInfo.AUTHOR, ...Object.values(PluginInfo.CONTRIBUTORS)] as PluginAuthor[];
+ this.dependencies = ["PhilsPluginLibrary"];
+ }
+
+ start(): void {
+ initMicrophoneStore();
+
+ this.microphonePatcher = new MicrophonePatcher().patch();
+
+ addSettingsPanelButton({ name: PluginInfo.PLUGIN_NAME, icon: MicrophoneSettingsIcon, tooltipText: "Microphone Settings", onClick: openMicrophoneSettingsModal });
+ }
+
+ stop(): void {
+ this.microphonePatcher?.unpatch();
+
+ Emitter.removeAllListeners(PluginInfo.PLUGIN_NAME);
+
+ removeSettingsPanelButton(PluginInfo.PLUGIN_NAME);
+ }
+};
diff --git a/src/equicordplugins/betterMicrophone.desktop/logger/index.ts b/src/equicordplugins/betterMicrophone.desktop/logger/index.ts
new file mode 100644
index 000000000..828c0f86c
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/logger/index.ts
@@ -0,0 +1,23 @@
+/*
+ * 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 .
+*/
+
+import { Logger } from "@utils/Logger";
+
+import { PluginInfo } from "../constants";
+
+export const logger = new Logger(PluginInfo.PLUGIN_NAME);
diff --git a/src/equicordplugins/betterMicrophone.desktop/modals/index.tsx b/src/equicordplugins/betterMicrophone.desktop/modals/index.tsx
new file mode 100644
index 000000000..781f5d3cc
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/modals/index.tsx
@@ -0,0 +1,43 @@
+/*
+ * 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 .
+*/
+
+import { openModalLazy } from "@utils/modal";
+
+import { MicrophoneSettingsModal } from "../components";
+import { PluginInfo } from "../constants";
+import Plugin from "../index";
+import { microphoneStore } from "../stores";
+
+const onMicrophoneModalDone = () => {
+ const { microphonePatcher } = Plugin;
+
+ if (microphonePatcher)
+ microphonePatcher.forceUpdateTransportationOptions();
+};
+
+export const openMicrophoneSettingsModal =
+ () => openModalLazy(async () => {
+ return props =>
+ ;
+ });
diff --git a/src/equicordplugins/betterMicrophone.desktop/patchers/index.ts b/src/equicordplugins/betterMicrophone.desktop/patchers/index.ts
new file mode 100644
index 000000000..541fa7441
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/patchers/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./microphone";
diff --git a/src/equicordplugins/betterMicrophone.desktop/patchers/microphone.ts b/src/equicordplugins/betterMicrophone.desktop/patchers/microphone.ts
new file mode 100644
index 000000000..2507f4f8b
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/patchers/microphone.ts
@@ -0,0 +1,71 @@
+/*
+ * 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 .
+*/
+
+import { Emitter, MediaEngineStore, Patcher, types } from "../../philsPluginLibrary";
+import { patchConnectionAudioTransportOptions } from "../../philsPluginLibrary/patches/audio";
+import { PluginInfo } from "../constants";
+import { logger } from "../logger";
+import { microphoneStore } from "../stores";
+
+export class MicrophonePatcher extends Patcher {
+ private mediaEngineStore: types.MediaEngineStore;
+ private mediaEngine: types.MediaEngine;
+ public connection?: types.Connection;
+ public oldSetTransportOptions: (...args: any[]) => void;
+ public forceUpdateTransportationOptions: () => void;
+
+ constructor() {
+ super();
+ this.mediaEngineStore = MediaEngineStore;
+ this.mediaEngine = this.mediaEngineStore.getMediaEngine();
+ this.oldSetTransportOptions = () => void 0;
+ this.forceUpdateTransportationOptions = () => void 0;
+ }
+
+ public patch(): this {
+ this.unpatch();
+
+ const { get } = microphoneStore;
+
+ const connectionEventFunction =
+ (connection: types.Connection) => {
+ if (connection.context !== "default") return;
+
+ this.connection = connection;
+
+ const { oldSetTransportOptions, forceUpdateTransportationOptions } = patchConnectionAudioTransportOptions(connection, get, logger);
+
+ this.oldSetTransportOptions = oldSetTransportOptions;
+ this.forceUpdateTransportationOptions = forceUpdateTransportationOptions;
+ };
+
+ Emitter.addListener(
+ this.mediaEngine.emitter,
+ "on",
+ "connection",
+ connectionEventFunction,
+ PluginInfo.PLUGIN_NAME
+ );
+
+ return this;
+ }
+
+ public unpatch(): this {
+ return this._unpatch();
+ }
+}
diff --git a/src/equicordplugins/betterMicrophone.desktop/stores/index.ts b/src/equicordplugins/betterMicrophone.desktop/stores/index.ts
new file mode 100644
index 000000000..0a95f671a
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/stores/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./microphoneStore";
diff --git a/src/equicordplugins/betterMicrophone.desktop/stores/microphoneStore.ts b/src/equicordplugins/betterMicrophone.desktop/stores/microphoneStore.ts
new file mode 100644
index 000000000..f0a16a26e
--- /dev/null
+++ b/src/equicordplugins/betterMicrophone.desktop/stores/microphoneStore.ts
@@ -0,0 +1,94 @@
+/*
+ * 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 .
+*/
+
+import { createPluginStore, ProfilableInitializer, ProfilableStore, profileable, ProfileableProfile } from "../../philsPluginLibrary";
+import { PluginInfo } from "../constants";
+
+
+export interface MicrophoneProfile {
+ freq?: number,
+ pacsize?: number,
+ channels?: number,
+ rate?: number,
+ voiceBitrate?: number;
+ freqEnabled?: boolean,
+ pacsizeEnabled?: boolean;
+ channelsEnabled?: boolean;
+ rateEnabled?: boolean;
+ voiceBitrateEnabled?: boolean;
+}
+
+export interface MicrophoneStore {
+ simpleMode?: boolean;
+ setSimpleMode: (enabled?: boolean) => void;
+ setFreq: (freq?: number) => void;
+ setPacsize: (pacsize?: number) => void;
+ setChannels: (channels?: number) => void;
+ setRate: (rate?: number) => void;
+ setVoiceBitrate: (voiceBitrate?: number) => void;
+ setFreqEnabled: (enabled?: boolean) => void;
+ setPacsizeEnabled: (enabled?: boolean) => void;
+ setChannelsEnabled: (enabled?: boolean) => void;
+ setRateEnabled: (enabled?: boolean) => void;
+ setVoiceBitrateEnabled: (enabled?: boolean) => void;
+}
+
+export const defaultMicrophoneProfiles = {
+ normal: {
+ name: "Normal",
+ channels: 2,
+ channelsEnabled: true,
+ voiceBitrate: 96,
+ voiceBitrateEnabled: true
+ },
+ high: {
+ name: "High",
+ channels: 2,
+ channelsEnabled: true,
+ voiceBitrate: 320,
+ voiceBitrateEnabled: true
+ },
+} as const satisfies Record;
+
+export const microphoneStoreDefault: ProfilableInitializer = (set, get) => ({
+ simpleMode: true,
+ setSimpleMode: enabled => get().simpleMode = enabled,
+ setChannels: channels => get().currentProfile.channels = channels,
+ setRate: rate => get().currentProfile.rate = rate,
+ setVoiceBitrate: voiceBitrate => get().currentProfile.voiceBitrate = voiceBitrate,
+ setPacsize: pacsize => get().currentProfile.pacsize = pacsize,
+ setFreq: freq => get().currentProfile.freq = freq,
+ setChannelsEnabled: enabled => get().currentProfile.channelsEnabled = enabled,
+ setFreqEnabled: enabled => get().currentProfile.freqEnabled = enabled,
+ setPacsizeEnabled: enabled => get().currentProfile.pacsizeEnabled = enabled,
+ setRateEnabled: enabled => get().currentProfile.rateEnabled = enabled,
+ setVoiceBitrateEnabled: enabled => get().currentProfile.voiceBitrateEnabled = enabled,
+});
+
+export let microphoneStore: ProfilableStore;
+
+export const initMicrophoneStore = () =>
+ microphoneStore = createPluginStore(
+ PluginInfo.PLUGIN_NAME,
+ "MicrophoneStore",
+ profileable(
+ microphoneStoreDefault,
+ { name: "" },
+ Object.values(defaultMicrophoneProfiles)
+ )
+ );
diff --git a/src/equicordplugins/betterScreenshare.desktop/README.md b/src/equicordplugins/betterScreenshare.desktop/README.md
new file mode 100644
index 000000000..e6c793611
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/README.md
@@ -0,0 +1,30 @@
+# Better Screenshare Plugin
+
+## How to use each Setting?
+
+- **Audio Source** - Choose a window from the drop-down list and the audio will be shared whether you're streaming a window or a screen.
+- **Resolution** - Here you can set the width and the height (both are required). The ideal resolution is the resolution of the monitor you are streaming. An example would be `1080p` (height: `1920` width: `1080`).
+- **Framerate** - Here you can set the frame rate. The most common frame rate is `60`, but you can set it higher or lower if you like.
+- **Keyframe Interval** - Here you can set the keyframe interval in milliseconds. If you don't know anything about it, just leave it disabled, but if you want to understand it better, read through this [article](https://filmora.wondershare.com/video-editing/keyframe-interval-obs.html).
+- **Video Bitrate** - This is one of the most important settings as it affects the quality the most. Discord uses a low bitrate by default, so it's important to set it if you want good quality. If you want to find out your optimal bitrate, go to the video bitrate [section](https://github.com/Vendicated/Vencord/tree/main/src/plugins/betterScreenshare#video-bitrate).
+- **Audio Bitrate** - This is almost the same as video bitrate, but it works a little differently for audio. If you want to learn more about it, you can read through this [article](https://www.adobe.com/creativecloud/video/discover/audio-bitrate.html). But I would recommend setting it between `96kb/s` and `320kb/s` (higher means better).
+- **Video Codec** - Here you can set your video codec. Discord currently supports 4 codecs. Each codec offers different quality and performance. The most popular codec is **H264**, which I recommend. However, if you have a 40 series card, use the **AV1** codec.
+ - **AV1** - Only supported on 40-series cards.
+ - **VP8**
+ - **VP9**
+ - **H264**
+- **HDR** - Allows streaming in HDR.
+
+## Bitrate
+
+To find your optimal bitrate, you must first find your upload speed. You can do this by running a speed test on this [website](https://www.speedtest.net/). When you're done, you'll see a number in the upload field that represents your maximum upload speed in (`Mbps`) `Mb/s`. To use the upload you need to convert it from `Mb/s` to `Kb/s` by multiplying it by `1000`. I'd recommend going a bit lower as you probably won't always hit your max upload speed and it will affect your ping. Heres is a example `5000 Kb/s` -> `4000 Kb/s`.
+
+**IMPORTANT**: Discord added a cap of `10000 Kb/s`, if you went higher everyone would experience packet loss. It is not known if there is a bypass for this.
+
+## Presets
+
+If you don't want to do any of the above, you can just try the presets in the Profile Options tab and see what works best for you. And if you want to change a setting in the preset, you can simply copy it and save it as a new one.
+
+## Known Issues
+
+~~When sharing a window directly it can sometimes happen that no changes are applied, the reason for this is currently unknown, but to avoid this you can simply share your whole screen and set the audio source if required.~~
diff --git a/src/equicordplugins/betterScreenshare.desktop/components/AudioSourceSelect.tsx b/src/equicordplugins/betterScreenshare.desktop/components/AudioSourceSelect.tsx
new file mode 100644
index 000000000..01bc9f923
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/components/AudioSourceSelect.tsx
@@ -0,0 +1,62 @@
+/*
+ * 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 .
+*/
+
+import { Select, useEffect, useState } from "@webpack/common";
+import React from "react";
+
+import { MediaEngineStore, types } from "../../philsPluginLibrary";
+import { screenshareStore } from "../stores";
+
+export const AudioSourceSelect = (props?: typeof Select["defaultProps"]) => {
+ const { use } = screenshareStore;
+
+ const { audioSource, setAudioSource } = use();
+
+ const [windowPreviews, setWindowPreviews] = useState([]);
+
+ useEffect(() => {
+ const intervalFn = async () => {
+ const newPreviews = await MediaEngineStore.getMediaEngine().getWindowPreviews(1, 1);
+ setWindowPreviews(oldPreviews => [...oldPreviews, ...newPreviews].filter((preview, index, array) => array.findIndex(t => t.id === preview.id) === index));
+ };
+ intervalFn();
+
+ const intervals = [
+ setInterval(async () => {
+ intervalFn();
+ }, 4000), setInterval(async () => {
+ setWindowPreviews(await MediaEngineStore.getMediaEngine().getWindowPreviews(1, 1));
+ }, 30000)
+ ];
+
+ return () => intervals.forEach(interval => clearInterval(interval));
+ }, []);
+
+ return (
+
+ );
+};
diff --git a/src/equicordplugins/betterScreenshare.desktop/components/OpenScreenshareSettingsButton.tsx b/src/equicordplugins/betterScreenshare.desktop/components/OpenScreenshareSettingsButton.tsx
new file mode 100644
index 000000000..d12493a95
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/components/OpenScreenshareSettingsButton.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 .
+*/
+
+import { Button } from "@webpack/common";
+import React from "react";
+
+import { openScreenshareModal } from "../modals";
+
+export interface OpenScreenshareSettingsButtonProps {
+ title?: string;
+}
+
+export const OpenScreenshareSettingsButton = (props: OpenScreenshareSettingsButtonProps) => {
+ return (
+
+ );
+};
diff --git a/src/equicordplugins/betterScreenshare.desktop/components/ScreenshareSettingsModal.tsx b/src/equicordplugins/betterScreenshare.desktop/components/ScreenshareSettingsModal.tsx
new file mode 100644
index 000000000..ac529445a
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/components/ScreenshareSettingsModal.tsx
@@ -0,0 +1,467 @@
+/*
+ * 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 .
+*/
+
+import { Flex } from "@components/Flex";
+import { Switch } from "@components/Switch";
+import { ModalSize, openModalLazy } from "@utils/modal";
+import { Button, Card, Forms, React, Select, Slider, TextInput, useEffect, useState } from "@webpack/common";
+import { SelectOption } from "@webpack/types";
+
+import { MicrophoneSettingsModal } from "../../betterMicrophone.desktop/components";
+import {
+ MediaEngineStore,
+ openURL,
+ ProfilableStore,
+ SettingsModal,
+ SettingsModalCard,
+ SettingsModalCardItem,
+ SettingsModalCardRow,
+ SettingsModalProfilesCard,
+ types,
+ validateNumberInput,
+ validateTextInputNumber
+} from "../../philsPluginLibrary";
+import { Styles } from "../../philsPluginLibrary/styles";
+import { PluginInfo } from "../constants";
+import { ScreenshareAudioProfile, ScreenshareAudioStore, ScreenshareProfile, ScreenshareStore } from "../stores";
+
+const simpleResolutions: readonly (SelectOption & { value: types.Resolution; })[] = [
+ {
+ label: "480p",
+ value: {
+ height: 480,
+ width: 720
+ }
+ },
+ {
+ label: "720p",
+ value: {
+ height: 720,
+ width: 1280
+ }
+ },
+ {
+ label: "1080p",
+ value: {
+ height: 1080,
+ width: 1920
+ }
+ },
+ {
+ label: "1440p",
+ value: {
+ height: 1440,
+ width: 2560
+ }
+ },
+ {
+ label: "2160p",
+ value: {
+ height: 2160,
+ width: 3840
+ }
+ }
+] as const;
+
+const simpleVideoBitrates: readonly SelectOption[] = [
+ {
+ label: "Low",
+ value: 2500
+ },
+ {
+ label: "Medium",
+ value: 5000
+ },
+ {
+ label: "Medium-High",
+ value: 7500
+ },
+ {
+ label: "High",
+ value: 10000
+ }
+] as const;
+
+export interface ScreenshareSettingsModalProps extends React.ComponentProps {
+ screenshareStore: ProfilableStore;
+ screenshareAudioStore?: ProfilableStore;
+ onAudioDone?: () => void;
+}
+
+export const ScreenshareSettingsModal = (props: ScreenshareSettingsModalProps) => {
+ const { screenshareStore, screenshareAudioStore, onAudioDone } = props;
+
+ const {
+ currentProfile,
+ profiles,
+ simpleMode,
+ setVideoBitrateEnabled,
+ setVideoCodec,
+ setVideoCodecEnabled,
+ setFramerate,
+ setFramerateEnabled,
+ setHeight,
+ setKeyframeInterval,
+ setKeyframeIntervalEnabled,
+ setResolutionEnabled,
+ setVideoBitrate,
+ setWidth,
+ setCurrentProfile,
+ getProfile,
+ saveProfile,
+ setHdrEnabled,
+ setSimpleMode,
+ deleteProfile,
+ duplicateProfile,
+ getCurrentProfile,
+ getProfiles
+ } = screenshareStore.use();
+
+
+ const {
+ name,
+ framerate,
+ framerateEnabled,
+ height,
+ keyframeInterval,
+ keyframeIntervalEnabled,
+ resolutionEnabled,
+ videoBitrate,
+ videoBitrateEnabled,
+ videoCodec,
+ videoCodecEnabled,
+ width,
+ hdrEnabled
+ } = currentProfile;
+
+ const [videoCodecs, setVideoCodecs] = useState([]);
+
+ const [isSaving, setIsSaving] = useState(false);
+
+ const [textinputWidth, setTextinputWidth] = useState(width ? width.toString() : "");
+ const [textinputHeight, setTextinputHeight] = useState(height ? height.toString() : "");
+ const [textinputFramerate, setTextinputFramerate] = useState(framerate ? framerate.toString() : "");
+ const [textinputKeyframeInterval, setTextinputKeyframeInterval] = useState(keyframeInterval ? keyframeInterval.toString() : "");
+
+ useEffect(() => {
+ setTextinputWidth(width ? width.toString() : "");
+ setTextinputHeight(height ? height.toString() : "");
+ setTextinputFramerate(framerate ? framerate.toString() : "");
+ setTextinputKeyframeInterval(keyframeInterval ? keyframeInterval.toString() : "");
+ }, [width, height, framerate, keyframeInterval]);
+
+ useEffect(() => {
+ (async () => {
+ const mediaEngine = MediaEngineStore.getMediaEngine();
+
+ const stringifiedCodecs: types.CodecCapabilities[] = JSON.parse(
+ await new Promise(res => mediaEngine.getCodecCapabilities(res))
+ );
+
+ setVideoCodecs(stringifiedCodecs);
+ })();
+ }, []);
+
+ const settingsCardResolutionSimple =
+ setResolutionEnabled(status)
+ }}>
+
+
+ ;
+
+ const settingsCardVideoBitrateSimple =
+ setVideoBitrateEnabled(status)
+ }}>
+
+
+ ;
+
+ const settingsCardResolution =
+ setResolutionEnabled(status),
+ disabled: isSaving
+ }}>
+
+ validateTextInputNumber(value) && setTextinputWidth(value)}
+ onBlur={e => {
+ const result = validateNumberInput(e.target.value);
+ setWidth(result);
+ setTextinputWidth(result ? result.toString() : "");
+ }} />
+
+
+ validateTextInputNumber(value) && setTextinputHeight(value)}
+ onBlur={e => {
+ const result = validateNumberInput(e.target.value);
+ setHeight(result);
+ setTextinputHeight(result ? result.toString() : "");
+ }} />
+
+ ;
+
+ const settingsCardItemFramerate =
+
+ validateTextInputNumber(value) && setTextinputFramerate(value)}
+ onBlur={e => {
+ const result = validateNumberInput(e.target.value);
+ setFramerate(result);
+ setTextinputFramerate(result ? result.toString() : "");
+ }} />
+ ;
+
+ const settingsCardFramerateProps: React.ComponentProps = {
+ title: "Framerate",
+ switchEnabled: true,
+ switchProps: {
+ checked: framerateEnabled ?? false,
+ disabled: isSaving,
+ onChange: status => setFramerateEnabled(status)
+ }
+ };
+
+ const settingsCardFramerate =
+
+ {settingsCardItemFramerate}
+ ;
+
+ const settingsCardFramerateSimple =
+
+ {settingsCardItemFramerate}
+ ;
+
+ const settingsCardKeyframeInterval =
+ setKeyframeIntervalEnabled(status)
+ }}>
+
+ validateTextInputNumber(value) && setTextinputKeyframeInterval(value)}
+ onBlur={e => {
+ const result = validateNumberInput(e.target.value);
+ setKeyframeInterval(result);
+ setTextinputKeyframeInterval(result ? result.toString() : "");
+ }} />
+
+ ;
+
+ const settingsCardVideoBitrate =
+ setVideoBitrateEnabled(status)
+ }}>
+
+
+ : <>
+
+ {settingsCardResolution}
+ {settingsCardFramerate}
+ {settingsCardKeyframeInterval}
+
+
+ {settingsCardVideoBitrate}
+ {settingsCardVideoCodec}
+ {screenshareAudioStore && settingsCardAudio}
+
+
+ {guideCard}
+ {settingsCardHdr}
+ {settingsCardProfiles}
+
+ >
+ }
+
+ );
+};
diff --git a/src/equicordplugins/betterScreenshare.desktop/components/index.tsx b/src/equicordplugins/betterScreenshare.desktop/components/index.tsx
new file mode 100644
index 000000000..5177495fb
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/components/index.tsx
@@ -0,0 +1,21 @@
+/*
+ * 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 .
+*/
+
+export * from "./AudioSourceSelect";
+export * from "./OpenScreenshareSettingsButton";
+export * from "./ScreenshareSettingsModal";
diff --git a/src/equicordplugins/betterScreenshare.desktop/constants/constants.ts b/src/equicordplugins/betterScreenshare.desktop/constants/constants.ts
new file mode 100644
index 000000000..32d9d44c2
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/constants/constants.ts
@@ -0,0 +1,38 @@
+/*
+ * 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 .
+*/
+
+import { Devs } from "@utils/constants";
+
+import { types } from "../../philsPluginLibrary";
+
+export const PluginInfo = {
+ PLUGIN_NAME: "BetterScreenshare",
+ DESCRIPTION: "This plugin allows you to further customize your screen sharing.",
+ AUTHOR: {
+ ...Devs.philhk,
+ github: "https://github.com/philhk"
+ },
+ CONTRIBUTORS: {
+ walrus: {
+ github: "https://github.com/philhk",
+ id: 305317288775778306n,
+ name: "walrus"
+ },
+ },
+ README: "https://github.com/Vendicated/Vencord/tree/main/src/plugins/betterScreenshare"
+} as const satisfies types.PluginInfo;
diff --git a/src/equicordplugins/betterScreenshare.desktop/constants/index.ts b/src/equicordplugins/betterScreenshare.desktop/constants/index.ts
new file mode 100644
index 000000000..c7b948abd
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/constants/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./constants";
diff --git a/src/equicordplugins/betterScreenshare.desktop/index.tsx b/src/equicordplugins/betterScreenshare.desktop/index.tsx
new file mode 100644
index 000000000..c274c5126
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/index.tsx
@@ -0,0 +1,86 @@
+/*
+ * 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 .
+*/
+
+import { definePluginSettings } from "@api/Settings";
+import { DefinedSettings, OptionType, Patch, PluginAuthor, PluginDef, SettingsDefinition } from "@utils/types";
+
+import { addSettingsPanelButton, Emitter, removeSettingsPanelButton, ScreenshareSettingsIcon } from "../philsPluginLibrary";
+import { PluginInfo } from "./constants";
+import { openScreenshareModal } from "./modals";
+import { ScreenshareAudioPatcher, ScreensharePatcher } from "./patchers";
+import { replacedScreenshareModalComponent } from "./patches";
+import { initScreenshareAudioStore, initScreenshareStore } from "./stores";
+
+export default new class Plugin implements PluginDef {
+ readonly name: string;
+ readonly description: string;
+ readonly authors: PluginAuthor[];
+ readonly patches: Omit[];
+ readonly settings: DefinedSettings;
+ readonly dependencies: string[];
+
+ private readonly replacedScreenshareModalComponent: typeof replacedScreenshareModalComponent;
+ public screensharePatcher?: ScreensharePatcher;
+ public screenshareAudioPatcher?: ScreenshareAudioPatcher;
+
+ constructor() {
+ this.name = PluginInfo.PLUGIN_NAME;
+ this.description = PluginInfo.DESCRIPTION;
+ this.authors = [PluginInfo.AUTHOR, ...Object.values(PluginInfo.CONTRIBUTORS)] as PluginAuthor[];
+ this.patches = [
+ {
+ find: "Messages.SCREENSHARE_RELAUNCH",
+ replacement: {
+ match: /(function .{1,2}\(.{1,2}\){)(.{1,40}(?=selectGuild).+?(?:]}\)}\)))(})/,
+ replace: "$1return $self.replacedScreenshareModalComponent(function(){$2}, this, arguments)$3"
+ }
+ }
+ ];
+ this.settings = definePluginSettings({
+ hideDefaultSettings: {
+ type: OptionType.BOOLEAN,
+ description: "Hide Discord screen sharing settings",
+ default: true,
+ }
+ });
+ this.dependencies = ["PhilsPluginLibrary"];
+ this.replacedScreenshareModalComponent = replacedScreenshareModalComponent;
+ }
+
+ start(): void {
+ initScreenshareStore();
+ initScreenshareAudioStore();
+ this.screensharePatcher = new ScreensharePatcher().patch();
+ this.screenshareAudioPatcher = new ScreenshareAudioPatcher().patch();
+
+ addSettingsPanelButton({
+ name: PluginInfo.PLUGIN_NAME,
+ icon: ScreenshareSettingsIcon,
+ tooltipText: "Screenshare Settings",
+ onClick: openScreenshareModal
+ });
+ }
+
+ stop(): void {
+ this.screensharePatcher?.unpatch();
+ this.screenshareAudioPatcher?.unpatch();
+ Emitter.removeAllListeners(PluginInfo.PLUGIN_NAME);
+
+ removeSettingsPanelButton(PluginInfo.PLUGIN_NAME);
+ }
+};
diff --git a/src/equicordplugins/betterScreenshare.desktop/logger/index.ts b/src/equicordplugins/betterScreenshare.desktop/logger/index.ts
new file mode 100644
index 000000000..828c0f86c
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/logger/index.ts
@@ -0,0 +1,23 @@
+/*
+ * 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 .
+*/
+
+import { Logger } from "@utils/Logger";
+
+import { PluginInfo } from "../constants";
+
+export const logger = new Logger(PluginInfo.PLUGIN_NAME);
diff --git a/src/equicordplugins/betterScreenshare.desktop/modals/index.tsx b/src/equicordplugins/betterScreenshare.desktop/modals/index.tsx
new file mode 100644
index 000000000..6650ed11f
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/modals/index.tsx
@@ -0,0 +1,55 @@
+/*
+ * 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 .
+*/
+
+import { openModalLazy } from "@utils/modal";
+
+import Plugin from "..";
+import { ScreenshareSettingsModal } from "../components";
+import { PluginInfo } from "../constants";
+import { screenshareAudioStore, screenshareStore } from "../stores";
+
+const onScreenshareModalDone = () => {
+ const { screenshareAudioPatcher, screensharePatcher } = Plugin;
+
+ if (screensharePatcher) {
+ screensharePatcher.forceUpdateTransportationOptions();
+ screensharePatcher.forceUpdateDesktopSourceOptions();
+ }
+ if (screenshareAudioPatcher)
+ screenshareAudioPatcher.forceUpdateTransportationOptions();
+};
+
+const onScreenshareAudioModalDone = () => {
+ const { screenshareAudioPatcher } = Plugin;
+
+ if (screenshareAudioPatcher)
+ screenshareAudioPatcher.forceUpdateTransportationOptions();
+};
+
+export const openScreenshareModal =
+ () => openModalLazy(async () => {
+ return props =>
+ ;
+ });
diff --git a/src/equicordplugins/betterScreenshare.desktop/patchers/index.ts b/src/equicordplugins/betterScreenshare.desktop/patchers/index.ts
new file mode 100644
index 000000000..24d37b2ca
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/patchers/index.ts
@@ -0,0 +1,20 @@
+/*
+ * 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 .
+*/
+
+export * from "./screenshare";
+export * from "./screenshareAudio";
diff --git a/src/equicordplugins/betterScreenshare.desktop/patchers/screenshare.ts b/src/equicordplugins/betterScreenshare.desktop/patchers/screenshare.ts
new file mode 100644
index 000000000..51aadbed6
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/patchers/screenshare.ts
@@ -0,0 +1,99 @@
+/*
+ * 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 .
+*/
+
+import { UserStore } from "@webpack/common";
+
+import { Emitter, MediaEngineStore, Patcher, types } from "../../philsPluginLibrary";
+import { patchConnectionVideoSetDesktopSourceWithOptions, patchConnectionVideoTransportOptions } from "../../philsPluginLibrary/patches/video";
+import { PluginInfo } from "../constants";
+import { logger } from "../logger";
+import { screenshareStore } from "../stores";
+
+export class ScreensharePatcher extends Patcher {
+ private mediaEngineStore: types.MediaEngineStore;
+ private mediaEngine: types.MediaEngine;
+ public connection?: types.Connection;
+ public oldSetDesktopSourceWithOptions: (...args: any[]) => void;
+ public oldSetTransportOptions: (...args: any[]) => void;
+ public forceUpdateTransportationOptions: () => void;
+ public forceUpdateDesktopSourceOptions: () => void;
+
+ constructor() {
+ super();
+ this.mediaEngineStore = MediaEngineStore;
+ this.mediaEngine = this.mediaEngineStore.getMediaEngine();
+ this.forceUpdateTransportationOptions = () => void 0;
+ this.forceUpdateDesktopSourceOptions = () => void 0;
+ this.oldSetDesktopSourceWithOptions = () => void 0;
+ this.oldSetTransportOptions = () => void 0;
+ }
+
+ public patch(): this {
+ this.unpatch();
+
+ const { get } = screenshareStore;
+
+ const connectionEventFunction =
+ (connection: types.Connection) => {
+ if (!(connection.context === "stream" && connection.streamUserId === UserStore.getCurrentUser().id)) return;
+
+ this.connection = connection;
+
+ const {
+ oldSetDesktopSourceWithOptions,
+ oldSetTransportOptions,
+ forceUpdateDesktopSourceOptions,
+ forceUpdateTransportationOptions
+ } = {
+ ...patchConnectionVideoTransportOptions(connection, get, logger),
+ ...patchConnectionVideoSetDesktopSourceWithOptions(connection, get, logger)
+ };
+
+ this.oldSetDesktopSourceWithOptions = oldSetDesktopSourceWithOptions;
+ this.oldSetTransportOptions = oldSetTransportOptions;
+ this.forceUpdateDesktopSourceOptions = forceUpdateDesktopSourceOptions;
+ this.forceUpdateTransportationOptions = forceUpdateTransportationOptions;
+
+ Emitter.addListener(connection.emitter, "on", "connected", () => {
+ this.forceUpdateTransportationOptions();
+ this.forceUpdateDesktopSourceOptions();
+ });
+
+ Emitter.addListener(connection.emitter, "on", "destroy", () => {
+ this.forceUpdateTransportationOptions = () => void 0;
+ this.forceUpdateDesktopSourceOptions = () => void 0;
+ this.oldSetTransportOptions = () => void 0;
+ this.oldSetDesktopSourceWithOptions = () => void 0;
+ });
+ };
+
+ Emitter.addListener(
+ this.mediaEngine.emitter,
+ "on",
+ "connection",
+ connectionEventFunction,
+ PluginInfo.PLUGIN_NAME
+ );
+
+ return this;
+ }
+
+ public unpatch(): this {
+ return this._unpatch();
+ }
+}
diff --git a/src/equicordplugins/betterScreenshare.desktop/patchers/screenshareAudio.ts b/src/equicordplugins/betterScreenshare.desktop/patchers/screenshareAudio.ts
new file mode 100644
index 000000000..642050572
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/patchers/screenshareAudio.ts
@@ -0,0 +1,85 @@
+/*
+ * 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 .
+*/
+
+import { UserStore } from "@webpack/common";
+
+import { Emitter, MediaEngineStore, patchConnectionAudioTransportOptions, Patcher, types } from "../../philsPluginLibrary";
+import { PluginInfo } from "../constants";
+import { logger } from "../logger";
+import { screenshareAudioStore } from "../stores/screenshareAudioStore";
+
+export class ScreenshareAudioPatcher extends Patcher {
+ private mediaEngineStore: types.MediaEngineStore;
+ private mediaEngine: types.MediaEngine;
+ public connection?: types.Connection;
+
+ public oldSetTransportOptions: (...args: any[]) => void;
+ public forceUpdateTransportationOptions: () => void;
+
+ constructor() {
+ super();
+ this.mediaEngineStore = MediaEngineStore;
+ this.mediaEngine = this.mediaEngineStore.getMediaEngine();
+
+ this.forceUpdateTransportationOptions = () => void 0;
+ this.oldSetTransportOptions = () => void 0;
+ }
+
+ public patch(): this {
+ this.unpatch();
+
+ const { get } = screenshareAudioStore;
+
+ const connectionEventFunction =
+ (connection: types.Connection) => {
+ if (connection.context !== "stream" || connection.streamUserId !== UserStore.getCurrentUser().id) return;
+
+ this.connection = connection;
+
+ const {
+ forceUpdateTransportationOptions: forceUpdateTransportationOptionsAudio,
+ oldSetTransportOptions: oldSetTransportOptionsAudio
+ } = patchConnectionAudioTransportOptions(connection, get, logger);
+
+ this.forceUpdateTransportationOptions = forceUpdateTransportationOptionsAudio;
+ this.oldSetTransportOptions = oldSetTransportOptionsAudio;
+
+ Emitter.addListener(connection.emitter, "on", "connected", () => {
+ this.forceUpdateTransportationOptions();
+ });
+
+ Emitter.addListener(connection.emitter, "on", "destroy", () => {
+ this.forceUpdateTransportationOptions = () => void 0;
+ });
+ };
+
+ Emitter.addListener(
+ this.mediaEngine.emitter,
+ "on",
+ "connection",
+ connectionEventFunction,
+ PluginInfo.PLUGIN_NAME
+ );
+
+ return this;
+ }
+
+ public unpatch(): this {
+ return this._unpatch();
+ }
+}
diff --git a/src/equicordplugins/betterScreenshare.desktop/patches/index.ts b/src/equicordplugins/betterScreenshare.desktop/patches/index.ts
new file mode 100644
index 000000000..169a8b282
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/patches/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./screenshareModal";
diff --git a/src/equicordplugins/betterScreenshare.desktop/patches/screenshareModal.tsx b/src/equicordplugins/betterScreenshare.desktop/patches/screenshareModal.tsx
new file mode 100644
index 000000000..4b069df08
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/patches/screenshareModal.tsx
@@ -0,0 +1,98 @@
+/*
+ * 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 .
+*/
+
+import { Flex } from "@components/Flex";
+import { React } from "@webpack/common";
+import { Settings } from "Vencord";
+
+import { SettingsModalCard, SettingsModalCardItem } from "../../philsPluginLibrary";
+import Plugin from "..";
+import { AudioSourceSelect, OpenScreenshareSettingsButton } from "../components";
+import { PluginInfo } from "../constants";
+import { screenshareStore } from "../stores";
+
+const ReplacedStreamSettings = () => {
+ const { use } = screenshareStore;
+
+ const { audioSourceEnabled, setAudioSourceEnabled } = use();
+
+ const cardProps = { style: { border: "1px solid var(--primary-800)" } };
+
+ return (
+
+ );
+};
+
+export function replacedScreenshareModalSettingsContentType(oldType: (...args: any[]) => any, thisContext: any, functionArguments: any) {
+ const { hideDefaultSettings } = Settings.plugins[PluginInfo.PLUGIN_NAME];
+ const oldTypeResult = Reflect.apply(oldType, thisContext, functionArguments);
+
+ if (hideDefaultSettings)
+ oldTypeResult.props.children = oldTypeResult.props.children.filter(c => !c?.props?.selectedFPS);
+ oldTypeResult.props.children.push();
+
+ return oldTypeResult;
+}
+
+export function replacedScreenshareModalComponent(oldComponent: (...args: any[]) => any, thisContext: any, functionArguments: any) {
+ const oldComponentResult = Reflect.apply(oldComponent, thisContext, functionArguments);
+
+ const content = oldComponentResult.props.children.props.children[2].props.children[1].props.children[2].props.children.props.children;
+ const oldContentType = content.type;
+
+ content.type = function () {
+ return replacedScreenshareModalSettingsContentType(oldContentType, this, arguments);
+ };
+
+ const [submitBtn, cancelBtn] = oldComponentResult.props.children.props.children[2].props.children[2].props.children;
+
+ submitBtn.props.onClick = () => {
+ const { screensharePatcher, screenshareAudioPatcher } = Plugin;
+
+ if (screensharePatcher) {
+ screensharePatcher.forceUpdateTransportationOptions();
+ if (screensharePatcher.connection?.connectionState === "CONNECTED")
+ screensharePatcher.forceUpdateDesktopSourceOptions();
+ }
+
+ if (screenshareAudioPatcher)
+ screenshareAudioPatcher.forceUpdateTransportationOptions();
+ };
+
+ return oldComponentResult;
+}
diff --git a/src/equicordplugins/betterScreenshare.desktop/stores/index.ts b/src/equicordplugins/betterScreenshare.desktop/stores/index.ts
new file mode 100644
index 000000000..d9e47818c
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/stores/index.ts
@@ -0,0 +1,20 @@
+/*
+ * 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 .
+*/
+
+export * from "./screenshareAudioStore";
+export * from "./screenshareStore";
diff --git a/src/equicordplugins/betterScreenshare.desktop/stores/screenshareAudioStore.ts b/src/equicordplugins/betterScreenshare.desktop/stores/screenshareAudioStore.ts
new file mode 100644
index 000000000..685ad6b74
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/stores/screenshareAudioStore.ts
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+*/
+
+import {
+ defaultMicrophoneProfiles as defaultScreenshareAudioProfiles,
+ MicrophoneProfile as ScreenshareAudioProfile,
+ MicrophoneStore as ScreenshareAudioStore,
+ microphoneStoreDefault as screenshareAudioStoreDefault
+} from "../../betterMicrophone.desktop/stores";
+import { createPluginStore, ProfilableStore, profileable } from "../../philsPluginLibrary";
+import { PluginInfo } from "../constants";
+
+export let screenshareAudioStore: ProfilableStore;
+
+export const initScreenshareAudioStore = () =>
+ screenshareAudioStore = createPluginStore(
+ PluginInfo.PLUGIN_NAME,
+ "ScreenshareAudioStore",
+ profileable(
+ screenshareAudioStoreDefault,
+ { name: "" },
+ Object.values(defaultScreenshareAudioProfiles)
+ )
+ );
+
+export { defaultScreenshareAudioProfiles, ScreenshareAudioProfile, ScreenshareAudioStore, screenshareAudioStoreDefault };
diff --git a/src/equicordplugins/betterScreenshare.desktop/stores/screenshareStore.ts b/src/equicordplugins/betterScreenshare.desktop/stores/screenshareStore.ts
new file mode 100644
index 000000000..7b9d0ed04
--- /dev/null
+++ b/src/equicordplugins/betterScreenshare.desktop/stores/screenshareStore.ts
@@ -0,0 +1,122 @@
+/*
+ * 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 .
+*/
+
+import { createPluginStore, ProfilableInitializer, ProfilableStore, profileable, ProfileableProfile } from "../../philsPluginLibrary";
+import { PluginInfo } from "../constants";
+
+
+export interface ScreenshareProfile {
+ width?: number,
+ height?: number,
+ framerate?: number,
+ videoCodec?: string,
+ keyframeInterval?: number,
+ videoBitrate?: number;
+ videoBitrateEnabled?: boolean;
+ resolutionEnabled?: boolean,
+ framerateEnabled?: boolean,
+ videoCodecEnabled?: boolean;
+ keyframeIntervalEnabled?: boolean;
+ hdrEnabled?: boolean;
+}
+
+export interface ScreenshareStore {
+ audioSource?: string;
+ audioSourceEnabled?: boolean;
+ simpleMode?: boolean;
+ setWidth: (width?: number) => void;
+ setHeight: (height?: number) => void;
+ setFramerate: (framerate?: number) => void;
+ setVideoCodec: (codec?: string) => void;
+ setKeyframeInterval: (keyframeInterval?: number) => void;
+ setVideoBitrate: (bitrate?: number) => void;
+ setKeyframeIntervalEnabled: (enabled?: boolean) => void;
+ setResolutionEnabled: (enabled?: boolean) => void;
+ setFramerateEnabled: (enabled?: boolean) => void;
+ setVideoCodecEnabled: (enabled?: boolean) => void;
+ setVideoBitrateEnabled: (enabled?: boolean) => void;
+ setHdrEnabled: (enabled?: boolean) => void;
+ setAudioSource: (audioSource?: string) => void;
+ setAudioSourceEnabled: (enabled?: boolean) => void;
+ setSimpleMode: (enabled?: boolean) => void;
+}
+
+export const defaultScreenshareProfiles = {
+ low: {
+ name: "Low Quality",
+ width: 1280,
+ height: 720,
+ framerate: 60,
+ videoBitrate: 2500,
+ resolutionEnabled: true,
+ framerateEnabled: true,
+ videoBitrateEnabled: true,
+ },
+ medium: {
+ name: "Medium Quality",
+ width: 1920,
+ height: 1080,
+ framerate: 60,
+ videoBitrate: 5000,
+ resolutionEnabled: true,
+ framerateEnabled: true,
+ videoBitrateEnabled: true,
+ },
+ high: {
+ name: "High Quality",
+ width: 1920,
+ height: 1080,
+ framerate: 60,
+ videoBitrate: 10000,
+ resolutionEnabled: true,
+ framerateEnabled: true,
+ videoBitrateEnabled: true,
+ }
+} as const satisfies Record;
+
+export const screenshareStoreDefault: ProfilableInitializer = (set, get) => ({
+ setVideoBitrate: bitrate => get().currentProfile.videoBitrate = bitrate,
+ setVideoBitrateEnabled: enabled => get().currentProfile.videoBitrateEnabled = enabled,
+ setVideoCodec: codec => get().currentProfile.videoCodec = codec,
+ setVideoCodecEnabled: enabled => get().currentProfile.videoCodecEnabled = enabled,
+ setFramerate: framerate => get().currentProfile.framerate = framerate,
+ setFramerateEnabled: enabled => get().currentProfile.framerateEnabled = enabled,
+ setHeight: height => get().currentProfile.height = height,
+ setWidth: width => get().currentProfile.width = width,
+ setResolutionEnabled: enabled => get().currentProfile.resolutionEnabled = enabled,
+ setKeyframeInterval: keyframeInterval => get().currentProfile.keyframeInterval = keyframeInterval,
+ setKeyframeIntervalEnabled: enabled => get().currentProfile.keyframeIntervalEnabled = enabled,
+ setHdrEnabled: enabled => get().currentProfile.hdrEnabled = enabled,
+ setAudioSource: audioSource => get().audioSource = audioSource,
+ setAudioSourceEnabled: enabled => get().audioSourceEnabled = enabled,
+ setSimpleMode: enabled => get().simpleMode = enabled,
+ simpleMode: true
+});
+
+export let screenshareStore: ProfilableStore;
+
+export const initScreenshareStore = () =>
+ screenshareStore = createPluginStore(
+ PluginInfo.PLUGIN_NAME,
+ "ScreenshareStore",
+ profileable(
+ screenshareStoreDefault,
+ { name: "" },
+ Object.values(defaultScreenshareProfiles)
+ )
+ );
diff --git a/src/equicordplugins/philsPluginLibrary/components/AuthorSummaryItem.tsx b/src/equicordplugins/philsPluginLibrary/components/AuthorSummaryItem.tsx
new file mode 100644
index 000000000..2f1d83b74
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/AuthorSummaryItem.tsx
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+*/
+
+import { PluginAuthor } from "@utils/types";
+import { useEffect, UserUtils, useState } from "@webpack/common";
+import { User } from "discord-types/general";
+import React from "react";
+
+import { createDummyUser, types, UserSummaryItem } from "../../philsPluginLibrary";
+
+export interface AuthorUserSummaryItemProps extends Partial> {
+ authors: PluginAuthor[];
+}
+
+export const AuthorUserSummaryItem = (props: AuthorUserSummaryItemProps) => {
+ const [users, setUsers] = useState[]>([]);
+
+ useEffect(() => {
+ (async () => {
+ props.authors.forEach(author =>
+ UserUtils.getUser(`${author.id}`)
+ .then(user => setUsers(users => [...users, user]))
+ .catch(() => setUsers(users => [...users, createDummyUser({
+ username: author.name,
+ id: `${author.id}`,
+ bot: true,
+ })]))
+ );
+ })();
+ }, []);
+
+ return (
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/ContributorAuthorSummary.tsx b/src/equicordplugins/philsPluginLibrary/components/ContributorAuthorSummary.tsx
new file mode 100644
index 000000000..56f827b48
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/ContributorAuthorSummary.tsx
@@ -0,0 +1,53 @@
+/*
+ * 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 .
+*/
+
+import { Flex } from "@components/Flex";
+import { Text } from "@webpack/common";
+import React from "react";
+
+import { Author, Contributor } from "../types";
+import { openURL } from "../utils";
+import { AuthorUserSummaryItem } from "./AuthorSummaryItem";
+
+export interface ContributorAuthorSummaryProps {
+ author?: Author;
+ contributors?: Contributor[];
+}
+
+export const ContributorAuthorSummary = ({ author, contributors }: ContributorAuthorSummaryProps) => {
+ return (
+
+ {author &&
+
+
+ Author: author.github && openURL(author.github)}>{`${author.name}`}
+
+
+
+ }
+ {(contributors && contributors.length > 0) &&
+
+
+ Contributors:
+
+
+
+ }
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/buttons/CopyButton.tsx b/src/equicordplugins/philsPluginLibrary/components/buttons/CopyButton.tsx
new file mode 100644
index 000000000..e1b46904f
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/buttons/CopyButton.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 .
+*/
+
+import { Button } from "@webpack/common";
+import React from "react";
+
+import { IconTooltipButton } from ".";
+
+export const CopyButton = (props: typeof Button["defaultProps"]) => {
+ return (
+
+
+
+
+ }
+ {...props} />
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/buttons/DeleteButton.tsx b/src/equicordplugins/philsPluginLibrary/components/buttons/DeleteButton.tsx
new file mode 100644
index 000000000..fa3901e78
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/buttons/DeleteButton.tsx
@@ -0,0 +1,39 @@
+/*
+ * 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 .
+*/
+
+import { Button } from "@webpack/common";
+import * as types from "@webpack/types";
+import React from "react";
+
+import { IconTooltipButton } from ".";
+
+export const DeleteButton = (props: types.Button["defaultProps"]) => {
+ return (
+
+
+
+
+ }
+ {...props} />
+ );
+};
+
diff --git a/src/equicordplugins/philsPluginLibrary/components/buttons/IconTooltipButton.tsx b/src/equicordplugins/philsPluginLibrary/components/buttons/IconTooltipButton.tsx
new file mode 100644
index 000000000..7acaac38c
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/buttons/IconTooltipButton.tsx
@@ -0,0 +1,44 @@
+/*
+ * 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 .
+*/
+
+import { Flex } from "@components/Flex";
+import { Button, Tooltip } from "@webpack/common";
+import React from "react";
+
+
+export interface IconTooltipButtonProps {
+ tooltipText?: string;
+ icon?: JSX.Element;
+}
+
+export const IconTooltipButton = (props: typeof Button["defaultProps"] & IconTooltipButtonProps) => {
+ return (
+
+ {tooltipProps => }
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/buttons/NewButton.tsx b/src/equicordplugins/philsPluginLibrary/components/buttons/NewButton.tsx
new file mode 100644
index 000000000..123070300
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/buttons/NewButton.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 .
+*/
+
+import { Button } from "@webpack/common";
+import React from "react";
+
+import { IconTooltipButton } from ".";
+
+export const NewButton = (props: typeof Button["defaultProps"]) => {
+ return (
+
+
+
+
+ }
+ {...props} />
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/buttons/SaveButton.tsx b/src/equicordplugins/philsPluginLibrary/components/buttons/SaveButton.tsx
new file mode 100644
index 000000000..6e1a2a163
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/buttons/SaveButton.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 .
+*/
+
+import { Button } from "@webpack/common";
+import React from "react";
+
+import { IconTooltipButton } from ".";
+
+export const SaveButton = (props: typeof Button["defaultProps"]) => {
+ return (
+
+
+
+
+
+ }
+ {...props} />
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/buttons/index.tsx b/src/equicordplugins/philsPluginLibrary/components/buttons/index.tsx
new file mode 100644
index 000000000..e22ccb661
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/buttons/index.tsx
@@ -0,0 +1,23 @@
+/*
+ * 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 .
+*/
+
+export * from "./CopyButton";
+export * from "./DeleteButton";
+export * from "./IconTooltipButton";
+export * from "./NewButton";
+export * from "./SaveButton";
diff --git a/src/equicordplugins/philsPluginLibrary/components/index.tsx b/src/equicordplugins/philsPluginLibrary/components/index.tsx
new file mode 100644
index 000000000..614223a6d
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/index.tsx
@@ -0,0 +1,23 @@
+/*
+ * 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 .
+*/
+
+export * from "./AuthorSummaryItem";
+export * from "./buttons";
+export * from "./ContributorAuthorSummary";
+export * from "./settingsModal";
+export * from "./settingsPanel";
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModal.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModal.tsx
new file mode 100644
index 000000000..b1de6fd5b
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModal.tsx
@@ -0,0 +1,77 @@
+/*
+ * 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 .
+*/
+
+import { Flex } from "@components/Flex";
+import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot } from "@utils/modal";
+import { Button, Text } from "@webpack/common";
+import React from "react";
+
+import { Author, Contributor } from "../../types";
+import { ContributorAuthorSummary } from "../ContributorAuthorSummary";
+
+
+export interface SettingsModalProps extends React.ComponentProps {
+ title?: string;
+ onClose: () => void;
+ onDone?: () => void;
+ footerContent?: JSX.Element;
+ closeButtonName?: string;
+ author?: Author,
+ contributors?: Contributor[];
+}
+
+export const SettingsModal = (props: SettingsModalProps) => {
+ const doneButton =
+ ;
+
+ return (
+
+
+ {props.title && {props.title}}
+
+
+
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCard.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCard.tsx
new file mode 100644
index 000000000..a532b3b50
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCard.tsx
@@ -0,0 +1,83 @@
+/*
+ * 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 .
+*/
+
+import { Switch } from "@components/Switch";
+import { Card, Forms } from "@webpack/common";
+import React from "react";
+
+export interface SettingsModalItemProps extends Pick,
+ | "children"> {
+ title?: string;
+ switchEnabled?: boolean;
+ switchProps?: React.ComponentProps;
+ flex?: number;
+ cardProps?: React.ComponentProps;
+}
+
+export const SettingsModalCard = ({ children, title, switchProps, switchEnabled, flex, cardProps }: SettingsModalItemProps) => {
+ return (
+
+ {title && {title}}
+
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCardItem.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCardItem.tsx
new file mode 100644
index 000000000..067cc8757
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCardItem.tsx
@@ -0,0 +1,39 @@
+/*
+ * 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 .
+*/
+
+import { Forms } from "@webpack/common";
+import React from "react";
+
+export interface SettingsModalCardItemProps extends Pick,
+ | "children"> {
+ title?: string;
+}
+
+export const SettingsModalCardItem = ({ children, title }: SettingsModalCardItemProps) => {
+ return (
+
+ {title && {title}}
+ {children}
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCardRow.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCardRow.tsx
new file mode 100644
index 000000000..443aa5495
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalCardRow.tsx
@@ -0,0 +1,31 @@
+/*
+ * 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 .
+*/
+
+import React from "react";
+
+export interface SettingsModalRowProps extends Pick,
+ | "children"
+ | "style"> {
+ gap?: string;
+}
+
+export const SettingsModalCardRow = ({ children, style, gap }: SettingsModalRowProps) => {
+ return (
+
{children}
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalProfilesCard.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalProfilesCard.tsx
new file mode 100644
index 000000000..9caecb83e
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsModal/SettingsModalProfilesCard.tsx
@@ -0,0 +1,113 @@
+/*
+ * 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 .
+*/
+
+import { Flex } from "@components/Flex";
+import { Select, TextInput, useEffect, useState } from "@webpack/common";
+
+import { PluginSettings, ProfilableStore } from "../../../philsPluginLibrary";
+import { CopyButton, DeleteButton, NewButton, SaveButton } from "../buttons";
+import { SettingsModalCard } from "./SettingsModalCard";
+import { SettingsModalCardItem } from "./SettingsModalCardItem";
+
+export interface SettingsModalProfilesCardProps extends React.ComponentProps {
+ profileableStore: ProfilableStore;
+ onSaveStateChanged: (isSaving: boolean) => void;
+}
+
+export const SettingsModalProfilesCard = (props: SettingsModalProfilesCardProps) => {
+ const { profileableStore: { use } } = props;
+
+ const {
+ currentProfile,
+ setCurrentProfile,
+ deleteProfile,
+ getCurrentProfile,
+ getDefaultProfiles,
+ getProfile,
+ getProfiles,
+ saveProfile,
+ isCurrentProfileADefaultProfile
+ } = use();
+
+ const { name } = currentProfile;
+
+ const [isSaving, setIsSaving] = useState(false);
+ const [profileNameInput, setProfileNameInput] = useState("");
+
+ useEffect(() => {
+ props.onSaveStateChanged(isSaving);
+ }, [isSaving]);
+
+ const onSaveProfile = () => {
+ if (!isSaving) {
+ setIsSaving(true);
+
+ } else {
+ if (profileNameInput.length && !getDefaultProfiles().some(value => value.name === profileNameInput)) {
+ saveProfile({ ...getCurrentProfile(), name: profileNameInput });
+ setCurrentProfile(getProfile(profileNameInput) || { name: "" });
+ setIsSaving(false);
+ }
+ }
+ };
+
+ const onCopyProfile = () => {
+ setCurrentProfile({ ...getCurrentProfile(), name: "" });
+ };
+
+ const onNewProfile = () => {
+ setCurrentProfile({ name: "" });
+ };
+
+ const onDeleteProfile = () => {
+ deleteProfile(currentProfile);
+ };
+
+ return (
+
+
+
+
+ {isSaving
+ ?
+ :
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsModal/index.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsModal/index.tsx
new file mode 100644
index 000000000..7522d9f45
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsModal/index.tsx
@@ -0,0 +1,23 @@
+/*
+ * 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 .
+*/
+
+export * from "./SettingsModal";
+export * from "./SettingsModalCard";
+export * from "./SettingsModalCardItem";
+export * from "./SettingsModalCardRow";
+export * from "./SettingsModalProfilesCard";
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanel.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanel.tsx
new file mode 100644
index 000000000..654af6bf0
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanel.tsx
@@ -0,0 +1,35 @@
+/*
+ * 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 .
+*/
+
+import { React } from "@webpack/common";
+
+import { panelClasses } from "../../discordModules";
+
+
+export interface SettingsPanelProps {
+ children: React.ComponentProps<"div">["children"];
+}
+
+export const SettingsPanel = ({ children }: SettingsPanelProps) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelButton.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelButton.tsx
new file mode 100644
index 000000000..5531d7ea6
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelButton.tsx
@@ -0,0 +1,40 @@
+/*
+ * 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 .
+*/
+
+import { classes } from "@utils/misc";
+import { Button } from "@webpack/common";
+import React from "react";
+
+import { panelClasses } from "../../../philsPluginLibrary";
+
+export type IconComponent = (props: T) => JSX.Element;
+export interface SettingsPanelButtonProps extends Partial> {
+ icon?: IconComponent;
+}
+
+export const SettingsPanelButton = (props: SettingsPanelButtonProps) => {
+ return (
+ }
+ {...props} />
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelRow.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelRow.tsx
new file mode 100644
index 000000000..71300c92b
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelRow.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 .
+*/
+
+import { classes } from "@utils/misc";
+import React from "react";
+
+import { panelClasses } from "../../discordModules";
+
+export interface SettingsPanelRowProps {
+ children: React.ComponentProps<"div">["children"];
+}
+
+export const SettingsPanelRow = ({ children }: SettingsPanelRowProps) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelTooltipButton.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelTooltipButton.tsx
new file mode 100644
index 000000000..4bb2f7f07
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/SettingsPanelTooltipButton.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 .
+*/
+
+import { Tooltip } from "@webpack/common";
+import React from "react";
+
+import { SettingsPanelButton, SettingsPanelButtonProps } from "./SettingsPanelButton";
+
+export interface SettingsPanelTooltipButtonProps extends SettingsPanelButtonProps {
+ tooltipProps: Omit, "children">;
+}
+
+export const SettingsPanelTooltipButton = (props: SettingsPanelTooltipButtonProps) => {
+ return (
+
+ {tooltipProps => }
+
+ );
+};
diff --git a/src/equicordplugins/philsPluginLibrary/components/settingsPanel/index.tsx b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/index.tsx
new file mode 100644
index 000000000..e8d96aabc
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/components/settingsPanel/index.tsx
@@ -0,0 +1,22 @@
+/*
+ * 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 .
+*/
+
+export * from "./SettingsPanel";
+export * from "./SettingsPanelButton";
+export * from "./SettingsPanelRow";
+export * from "./SettingsPanelTooltipButton";
diff --git a/src/equicordplugins/philsPluginLibrary/constants/constants.ts b/src/equicordplugins/philsPluginLibrary/constants/constants.ts
new file mode 100644
index 000000000..f92808c12
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/constants/constants.ts
@@ -0,0 +1,30 @@
+/*
+ * 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 .
+*/
+
+import { Devs } from "@utils/constants";
+
+import * as types from "../types/constants";
+
+export const PluginInfo: types.PluginInfo = {
+ PLUGIN_NAME: "PhilsPluginLibrary",
+ DESCRIPTION: "A library for phil's plugins",
+ AUTHOR: {
+ ...Devs.philhk,
+ github: "https://github.com/philhk"
+ },
+} as const;
diff --git a/src/equicordplugins/philsPluginLibrary/constants/index.ts b/src/equicordplugins/philsPluginLibrary/constants/index.ts
new file mode 100644
index 000000000..c7b948abd
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/constants/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./constants";
diff --git a/src/equicordplugins/philsPluginLibrary/discordModules/classes.ts b/src/equicordplugins/philsPluginLibrary/discordModules/classes.ts
new file mode 100644
index 000000000..9496bf86d
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/discordModules/classes.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 .
+*/
+
+import { findByPropsLazy } from "@webpack";
+
+import * as types from "../types";
+
+export const panelClasses: types.PanelClasses = findByPropsLazy("button", "buttonContents", "buttonColor");
+
+// waitFor(filters.byProps("button", "buttonContents", "buttonColor"), result => panelClasses = result);
diff --git a/src/equicordplugins/philsPluginLibrary/discordModules/components.tsx b/src/equicordplugins/philsPluginLibrary/discordModules/components.tsx
new file mode 100644
index 000000000..fc38f1e5f
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/discordModules/components.tsx
@@ -0,0 +1,24 @@
+/*
+ * 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 .
+*/
+
+import { LazyComponent } from "@utils/react";
+import { findByCode } from "@webpack";
+
+import { types } from "../";
+
+export const UserSummaryItem = LazyComponent>(() => findByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"));
diff --git a/src/equicordplugins/philsPluginLibrary/discordModules/index.ts b/src/equicordplugins/philsPluginLibrary/discordModules/index.ts
new file mode 100644
index 000000000..af5ab9678
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/discordModules/index.ts
@@ -0,0 +1,22 @@
+/*
+ * 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 .
+*/
+
+export * from "./classes";
+export * from "./components";
+export * from "./modules";
+export * from "./stores";
diff --git a/src/equicordplugins/philsPluginLibrary/discordModules/modules.ts b/src/equicordplugins/philsPluginLibrary/discordModules/modules.ts
new file mode 100644
index 000000000..137154116
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/discordModules/modules.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 .
+*/
+
+import { filters, waitFor } from "@webpack";
+
+import * as types from "../types";
+
+export let utils: types.Utils;
+
+waitFor(filters.byProps("getPidFromDesktopSource"), result => utils = result);
diff --git a/src/equicordplugins/philsPluginLibrary/discordModules/stores.ts b/src/equicordplugins/philsPluginLibrary/discordModules/stores.ts
new file mode 100644
index 000000000..a620e9b1a
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/discordModules/stores.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 .
+*/
+
+import { waitForStore } from "webpack/common/internal";
+
+import * as types from "../types";
+
+export let MediaEngineStore: types.MediaEngineStore;
+
+waitForStore("MediaEngineStore", store => MediaEngineStore = store);
diff --git a/src/equicordplugins/philsPluginLibrary/emitter/emitter.ts b/src/equicordplugins/philsPluginLibrary/emitter/emitter.ts
new file mode 100644
index 000000000..c3643c8ea
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/emitter/emitter.ts
@@ -0,0 +1,86 @@
+/*
+ * 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 .
+*/
+
+import EventEmitter from "events";
+import TypedEmitter from "typed-emitter";
+
+export type TypedEmitterEvents> = J extends TypedEmitter<
+ infer N
+>
+ ? N
+ : never;
+
+export interface EmitterEvent {
+ emitter: TypedEmitter | EventEmitter;
+ event: any;
+ fn: (...args: any[]) => any;
+ plugin?: string;
+}
+
+export class Emitter {
+ private static events: EmitterEvent[] = [];
+
+ public static addListener<
+ T extends TypedEmitter,
+ U extends keyof TypedEmitterEvents,
+ V extends TypedEmitterEvents[U]
+ >(
+ emitter: T,
+ type: keyof Pick,
+ event: U,
+ fn: V,
+ plugin?: string
+ ): () => void;
+
+ public static addListener(
+ emitter: EventEmitter,
+ type: keyof Pick,
+ event: string,
+ fn: (...args: any[]) => void,
+ plugin?: string
+ ): () => void {
+ emitter[type](event, fn);
+ const emitterEvenet: EmitterEvent = {
+ emitter,
+ event,
+ fn,
+ plugin: plugin
+ };
+ this.events.push(emitterEvenet);
+
+ return () => this.removeListener(emitterEvenet);
+ }
+
+ public static removeListener(emitterEvent: EmitterEvent) {
+ emitterEvent.emitter.removeListener(emitterEvent.event, emitterEvent.fn);
+ this.events = this.events.filter(
+ emitterEvent_ => emitterEvent_ !== emitterEvent
+ );
+ }
+
+ public static removeAllListeners(plugin?: string) {
+ if (!plugin) {
+ this.events.forEach(emitterEvent =>
+ this.removeListener(emitterEvent)
+ );
+ } else
+ this.events.forEach(emitterEvent =>
+ plugin === emitterEvent.plugin && this.removeListener(emitterEvent)
+ );
+ }
+}
diff --git a/src/equicordplugins/philsPluginLibrary/emitter/index.ts b/src/equicordplugins/philsPluginLibrary/emitter/index.ts
new file mode 100644
index 000000000..5f6e9fdb9
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/emitter/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./emitter";
diff --git a/src/equicordplugins/philsPluginLibrary/icons/index.tsx b/src/equicordplugins/philsPluginLibrary/icons/index.tsx
new file mode 100644
index 000000000..726a6782f
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/icons/index.tsx
@@ -0,0 +1,142 @@
+/*
+ * 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 .
+*/
+
+export const ScreenshareSettingsIcon =
+ (props: React.ComponentProps<"svg">) =>
+ ;
+
+export const CameraSettingsIcon =
+ (props: React.ComponentProps<"svg">) =>
+ ;
+
+export const MicrophoneSettingsIcon =
+ (props: React.ComponentProps<"svg">) =>
+ ;
diff --git a/src/equicordplugins/philsPluginLibrary/index.tsx b/src/equicordplugins/philsPluginLibrary/index.tsx
new file mode 100644
index 000000000..57b45f831
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/index.tsx
@@ -0,0 +1,55 @@
+/*
+ * 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 .
+*/
+
+import { Patch, PluginAuthor, PluginDef } from "@utils/types";
+
+import { PluginInfo } from "./constants";
+import { replacedUserPanelComponent } from "./patches";
+
+export default new class Plugin implements PluginDef {
+ readonly name: string;
+ readonly description: string;
+ readonly authors: PluginAuthor[];
+ readonly patches: Omit[];
+
+ readonly replacedUserPanelComponent: typeof replacedUserPanelComponent;
+
+ constructor() {
+ this.name = PluginInfo.PLUGIN_NAME;
+ this.description = PluginInfo.DESCRIPTION;
+ this.authors = PluginInfo.AUTHORS as PluginAuthor[];
+ this.patches = [{
+ find: "Messages.ACCOUNT_A11Y_LABEL",
+ replacement: {
+ match: /(?<=function)( .{0,8}(?={).)(.{0,1000}isFullscreenInContext\(\).+?\)]}\))(})/,
+ replace: "$1return $self.replacedUserPanelComponent(function(){$2}, this, arguments)$3"
+ }
+ }];
+ this.replacedUserPanelComponent = replacedUserPanelComponent;
+ }
+};
+
+export * from "./components";
+export * from "./discordModules";
+export * from "./emitter";
+export * from "./icons";
+export * from "./patchers";
+export * from "./patches";
+export * from "./store";
+export * as types from "./types";
+export * from "./utils";
diff --git a/src/equicordplugins/philsPluginLibrary/patchers/index.ts b/src/equicordplugins/philsPluginLibrary/patchers/index.ts
new file mode 100644
index 000000000..a2c10f64a
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/patchers/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./patcher";
diff --git a/src/equicordplugins/philsPluginLibrary/patchers/patcher.ts b/src/equicordplugins/philsPluginLibrary/patchers/patcher.ts
new file mode 100644
index 000000000..88b2b8246
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/patchers/patcher.ts
@@ -0,0 +1,29 @@
+/*
+ * 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 .
+*/
+
+export abstract class Patcher {
+ protected unpatchFunctions: (() => any)[] = [];
+ public abstract patch(): this;
+ public abstract unpatch(): this;
+ protected _unpatch(): this {
+ this.unpatchFunctions.forEach(fn => fn());
+ this.unpatchFunctions = [];
+
+ return this;
+ }
+}
diff --git a/src/equicordplugins/philsPluginLibrary/patches/audio.ts b/src/equicordplugins/philsPluginLibrary/patches/audio.ts
new file mode 100644
index 000000000..005a5330d
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/patches/audio.ts
@@ -0,0 +1,88 @@
+/*
+ * 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 .
+*/
+
+import { Logger } from "@utils/Logger";
+import { lodash } from "@webpack/common";
+
+import { MicrophoneProfile, MicrophoneStore } from "../../betterMicrophone.desktop/stores";
+import { ProfilableStore, replaceObjectValuesIfExist, types } from "../../philsPluginLibrary";
+
+export function getDefaultAudioTransportationOptions(connection: types.Connection) {
+ return {
+ audioEncoder: {
+ ...connection.getCodecOptions("opus").audioEncoder,
+ },
+ encodingVoiceBitRate: 64000
+ };
+}
+
+export function getReplaceableAudioTransportationOptions(connection: types.Connection, get: ProfilableStore["get"]) {
+ const { currentProfile } = get();
+ const {
+ channels,
+ channelsEnabled,
+ freq,
+ freqEnabled,
+ pacsize,
+ pacsizeEnabled,
+ rate,
+ rateEnabled,
+ voiceBitrate,
+ voiceBitrateEnabled
+ } = currentProfile;
+
+ return {
+ ...(voiceBitrateEnabled && voiceBitrate
+ ? {
+ encodingVoiceBitRate: voiceBitrate * 1000
+ }
+ : {}
+ ),
+ audioEncoder: {
+ ...connection.getCodecOptions("opus").audioEncoder,
+ ...(rateEnabled && rate ? { rate } : {}),
+ ...(pacsizeEnabled && pacsize ? { pacsize } : {}),
+ ...(freqEnabled && freq ? { freq } : {}),
+ ...(channelsEnabled && channels ? { channels } : {})
+ }
+ };
+}
+
+export function patchConnectionAudioTransportOptions(
+ connection: types.Connection,
+ get: ProfilableStore["get"],
+ logger?: Logger
+) {
+ const oldSetTransportOptions = connection.conn.setTransportOptions;
+
+ connection.conn.setTransportOptions = function (this: any, options: Record) {
+ replaceObjectValuesIfExist(options, getReplaceableAudioTransportationOptions(connection, get));
+
+ return Reflect.apply(oldSetTransportOptions, this, [options]);
+ };
+
+ const forceUpdateTransportationOptions = () => {
+ const transportOptions = lodash.merge({ ...getDefaultAudioTransportationOptions(connection) }, getReplaceableAudioTransportationOptions(connection, get));
+
+ logger?.info("Overridden Transport Options", transportOptions);
+
+ oldSetTransportOptions(transportOptions);
+ };
+
+ return { oldSetTransportOptions, forceUpdateTransportationOptions };
+}
diff --git a/src/equicordplugins/philsPluginLibrary/patches/index.ts b/src/equicordplugins/philsPluginLibrary/patches/index.ts
new file mode 100644
index 000000000..7341e509a
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/patches/index.ts
@@ -0,0 +1,21 @@
+/*
+ * 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 .
+*/
+
+export * from "./audio";
+export * from "./userPanel";
+export * from "./video";
diff --git a/src/equicordplugins/philsPluginLibrary/patches/userPanel.tsx b/src/equicordplugins/philsPluginLibrary/patches/userPanel.tsx
new file mode 100644
index 000000000..891b78e42
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/patches/userPanel.tsx
@@ -0,0 +1,107 @@
+/*
+ * 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 .
+*/
+
+import { React } from "@webpack/common";
+
+import { SettingsPanel } from "../components";
+import { IconComponent, SettingsPanelButton } from "../components/settingsPanel/SettingsPanelButton";
+import { SettingsPanelRow } from "../components/settingsPanel/SettingsPanelRow";
+import { SettingsPanelTooltipButton } from "../components/settingsPanel/SettingsPanelTooltipButton";
+
+export interface PanelButton {
+ name: string,
+ tooltipText?: string,
+ icon?: IconComponent;
+ onClick?: () => void;
+}
+
+const settingsPanelButtonsSubscriptions = new Set();
+export const settingsPanelButtons: PanelButton[] = new Proxy([], {
+ set: (target, p, newValue) => {
+ target[p] = newValue;
+ settingsPanelButtonsSubscriptions.forEach(fn => fn());
+ return true;
+ },
+});
+
+export const useButtons = () => {
+ const [, forceUpdate] = React.useReducer(() => ({}), {});
+
+ React.useEffect(() => {
+ settingsPanelButtonsSubscriptions.add(forceUpdate);
+ return () => void settingsPanelButtonsSubscriptions.delete(() => forceUpdate);
+ }, []);
+
+ return settingsPanelButtons;
+};
+
+export const ButtonsSettingsPanel = () => {
+ const rawPanelButtons = useButtons();
+
+ const convertRawPanelButtons = (buttons: PanelButton[]) => {
+ const settingsPanelButtonsClone = [...buttons].sort();
+ const groupedButtons: JSX.Element[][] = [];
+
+ while (settingsPanelButtonsClone.length) {
+ const splicedButtons =
+ settingsPanelButtonsClone
+ .splice(0, 3)
+ .map(({ icon, tooltipText, onClick }) =>
+ tooltipText
+ ?
+ :
+ );
+
+ groupedButtons.push(splicedButtons);
+ }
+
+ return groupedButtons;
+ };
+
+ return rawPanelButtons.length > 0
+ ?
+ {...convertRawPanelButtons(rawPanelButtons).map(value => )}
+
+ : <>
+ >;
+};
+
+export function replacedUserPanelComponent(oldComponent: (...args: any[]) => any, thisContext: any, functionArguments: any) {
+ const componentResult: JSX.Element = Reflect.apply(oldComponent, thisContext, functionArguments);
+
+ if (!componentResult?.props) return componentResult;
+
+ const { children } = componentResult.props;
+
+ const userPanel = children.at(-2);
+ const userPanelChildren = userPanel.props.children;
+
+ userPanelChildren.splice(userPanelChildren.length - 1, 0,
+
+ );
+
+ return componentResult;
+}
+
+export function addSettingsPanelButton(settings: PanelButton) {
+ settingsPanelButtons.push(settings);
+}
+
+export function removeSettingsPanelButton(name: string) {
+ settingsPanelButtons.splice(0, settingsPanelButtons.length, ...settingsPanelButtons.filter(value => value.name !== name));
+}
diff --git a/src/equicordplugins/philsPluginLibrary/patches/video.ts b/src/equicordplugins/philsPluginLibrary/patches/video.ts
new file mode 100644
index 000000000..83517537e
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/patches/video.ts
@@ -0,0 +1,253 @@
+/*
+ * 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 .
+*/
+
+import { Logger } from "@utils/Logger";
+import { lodash } from "@webpack/common";
+
+import { ScreenshareProfile, ScreenshareStore } from "../../betterScreenshare.desktop/stores";
+import { ProfilableStore, replaceObjectValuesIfExist, types, utils } from "../../philsPluginLibrary";
+
+
+export function getDefaultVideoTransportationOptions(connection: types.Connection) {
+ return {
+ ...connection.videoQualityManager.applyQualityConstraints({}).constraints,
+ videoEncoder: {
+ ...connection.getCodecOptions("", "H264", "stream").videoEncoder
+ },
+ streamParameters: connection.videoStreamParameters[0],
+ keyframeInterval: 0,
+ };
+}
+
+export function getDefaultVideoDesktopSourceOptions(connection: types.Connection) {
+ const [type, sourceId] = connection.goLiveSourceIdentifier?.split(":") ?? ["screen", 0];
+
+ return {
+ hdrCaptureMode: "never",
+ allowScreenCaptureKit: true,
+ useQuartzCapturer: true,
+ useGraphicsCapture: true,
+ useVideoHook: true,
+ sourceId: sourceId,
+ type: type
+ };
+}
+
+export function getStreamParameters(connection: types.Connection, get: ProfilableStore["get"]) {
+ const { currentProfile } = get();
+ const {
+ framerate,
+ framerateEnabled,
+ height,
+ resolutionEnabled,
+ videoBitrate,
+ videoBitrateEnabled,
+ width,
+ } = currentProfile;
+
+ const { bitrateMax, capture } = connection.applyQualityConstraints({}).quality;
+
+ return {
+ ...connection.videoStreamParameters[0],
+ ...(videoBitrateEnabled && videoBitrate
+ ? {
+ maxBitrate: videoBitrate * 1000,
+ }
+ : {
+ maxBitrate: bitrateMax
+ }
+ ),
+ ...((resolutionEnabled && width && height)
+ ? {
+ maxResolution: {
+ height: height,
+ width: width,
+ type: "fixed"
+ },
+ maxPixelCount: width * height
+ }
+ : {
+ maxResolution: !capture.height || !capture.width ? {
+ height: capture.height,
+ width: capture.width,
+ type: "source"
+ } : {
+ height: capture.height,
+ width: capture.width,
+ type: "fixed"
+ }
+ }
+ ),
+ ...(framerateEnabled && framerate
+ ? {
+ maxFrameRate: framerate,
+ }
+ : {
+ maxFrameRate: capture.framerate
+ }
+ ),
+ active: true,
+ };
+}
+
+export function getReplaceableVideoTransportationOptions(connection: types.Connection, get: ProfilableStore["get"]) {
+ const { currentProfile, audioSource, audioSourceEnabled } = get();
+ const {
+ framerate,
+ framerateEnabled,
+ height,
+ keyframeInterval,
+ keyframeIntervalEnabled,
+ resolutionEnabled,
+ videoBitrate,
+ videoBitrateEnabled,
+ videoCodec,
+ videoCodecEnabled,
+ width,
+ } = currentProfile;
+
+ return {
+ ...(videoBitrateEnabled && videoBitrate
+ ? {
+ encodingVideoBitRate: videoBitrate * 1000,
+ encodingVideoMinBitRate: videoBitrate * 1000,
+ encodingVideoMaxBitRate: videoBitrate * 1000,
+ callBitRate: videoBitrate * 1000,
+ callMinBitRate: videoBitrate * 1000,
+ callMaxBitRate: videoBitrate * 1000
+ }
+ : {}
+ ),
+ ...((resolutionEnabled && width && height)
+ ? {
+ encodingVideoHeight: height,
+ encodingVideoWidth: width,
+ remoteSinkWantsPixelCount: height * width
+ }
+ : {}
+ ),
+ ...(framerateEnabled && framerate
+ ? {
+ encodingVideoFrameRate: framerate,
+ remoteSinkWantsMaxFramerate: framerate
+ }
+ : {}
+ ),
+ ...(keyframeIntervalEnabled && keyframeInterval
+ ? {
+ keyframeInterval: keyframeInterval
+ }
+ : {}
+ ),
+ ...(videoCodecEnabled && videoCodec
+ ? {
+ videoEncoder: connection.getCodecOptions("", videoCodec, "stream").videoEncoder
+ }
+ : {}
+ ),
+ ...(audioSourceEnabled && audioSource && utils.getPidFromDesktopSource(audioSource)
+ ? {
+ soundsharePid: utils.getPidFromDesktopSource(audioSource),
+ soundshareEventDriven: true,
+ soundshareLoopback: true
+ }
+ : {}
+ ),
+ streamParameters: getStreamParameters(connection, get)
+ };
+}
+
+export function getReplaceableVideoDesktopSourceOptions(get: ProfilableStore["get"]) {
+ const { currentProfile } = get();
+ const {
+ hdrEnabled,
+ } = currentProfile;
+
+ return {
+ ...(hdrEnabled
+ ? {
+ hdrCaptureMode: "always"
+ }
+ : {}
+ ),
+ };
+}
+
+export function patchConnectionVideoSetDesktopSourceWithOptions(
+ connection: types.Connection,
+ get: ProfilableStore["get"],
+ logger?: Logger
+) {
+ const oldSetDesktopSourceWithOptions = connection.conn.setDesktopSourceWithOptions;
+
+ connection.conn.setDesktopSourceWithOptions = function (this: any, options: Record) {
+ const replaceableDesktopSourceOptions = getReplaceableVideoDesktopSourceOptions(get);
+ replaceObjectValuesIfExist(options, replaceableDesktopSourceOptions);
+
+ logger?.info("Overridden Desktop Source Options", options);
+
+ return Reflect.apply(oldSetDesktopSourceWithOptions, this, [options]);
+ };
+
+ const forceUpdateDesktopSourceOptions = () => {
+ const desktopSourceOptions = lodash.merge({ ...getDefaultVideoDesktopSourceOptions(connection) }, getReplaceableVideoDesktopSourceOptions(get));
+
+ logger?.info("Force Updated Desktop Source Options", desktopSourceOptions);
+
+ oldSetDesktopSourceWithOptions(desktopSourceOptions);
+ };
+
+ return {
+ oldSetDesktopSourceWithOptions,
+ forceUpdateDesktopSourceOptions
+ };
+}
+
+export function patchConnectionVideoTransportOptions(
+ connection: types.Connection,
+ get: ProfilableStore["get"],
+ logger?: Logger
+) {
+ const oldSetTransportOptions = connection.conn.setTransportOptions;
+
+ connection.conn.setTransportOptions = function (this: any, options: Record) {
+ const replaceableTransportOptions = getReplaceableVideoTransportationOptions(connection, get);
+
+ if (options.streamParameters)
+ connection.videoStreamParameters = Array.isArray(options.streamParameters) ? options.streamParameters : [options.streamParameters];
+
+ replaceObjectValuesIfExist(options, replaceableTransportOptions);
+
+ logger?.info("Overridden Transport Options", options);
+
+ return Reflect.apply(oldSetTransportOptions, this, [options]);
+ };
+
+ const forceUpdateTransportationOptions = () => {
+ const transportOptions = lodash.merge({ ...getDefaultVideoTransportationOptions(connection) }, getReplaceableVideoTransportationOptions(connection, get));
+
+ logger?.info("Force Updated Transport Options", transportOptions);
+
+ oldSetTransportOptions(transportOptions);
+ };
+
+ return {
+ oldSetTransportOptions,
+ forceUpdateTransportationOptions,
+ };
+}
diff --git a/src/equicordplugins/philsPluginLibrary/store/index.ts b/src/equicordplugins/philsPluginLibrary/store/index.ts
new file mode 100644
index 000000000..4e1e78a14
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/store/index.ts
@@ -0,0 +1,20 @@
+/*
+ * 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 .
+*/
+
+export * from "./profileable";
+export * from "./store";
diff --git a/src/equicordplugins/philsPluginLibrary/store/profileable.ts b/src/equicordplugins/philsPluginLibrary/store/profileable.ts
new file mode 100644
index 000000000..5113a8430
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/store/profileable.ts
@@ -0,0 +1,85 @@
+/*
+ * 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 .
+*/
+
+import { PluginInitializer, PluginSettings, PluginStore } from "./store";
+
+export interface ProfileableProfile {
+ name: string;
+}
+
+export interface ProfileableSettings {
+ currentProfile: B;
+ profiles: B[];
+ setCurrentProfile: (f: ((currentProfile: B) => B | undefined) | B | undefined) => void;
+ getCurrentProfile: () => B;
+ duplicateProfile: (profile: string | B, name: string) => void;
+ deleteProfile: (profile: string | B) => void;
+ saveProfile: (profile: B) => void;
+ getProfile: (profile: string) => B | undefined;
+ getProfiles: (defaultProfiles: boolean) => B[],
+ isCurrentProfileADefaultProfile: () => boolean;
+ getDefaultProfiles: () => B[];
+}
+
+export type ProfilableStore<
+ T extends PluginSettings = {},
+ S extends PluginSettings = {}
+> = PluginStore>;
+
+export type ProfilableMiddleware<
+ T extends PluginSettings = {},
+ S extends PluginSettings = {},
+ B = T & ProfileableSettings
+> = PluginInitializer, B>;
+
+export type ProfilableInitializer<
+ T extends PluginSettings = {},
+ S extends PluginSettings = {}
+> = ProfilableMiddleware>>;
+
+export function profileable<
+ T extends PluginSettings = {},
+ S extends PluginSettings = {}
+>(f: ProfilableInitializer, defaultProfile: ProfileableProfile & S, defaultProfiles: (ProfileableProfile & S)[] = []): ProfilableMiddleware {
+ return (set, get) => ({
+ currentProfile: defaultProfile,
+ profiles: [],
+ getCurrentProfile: () => get().currentProfile,
+ getProfile: profile => [...get().profiles, ...(defaultProfiles ?? [])].find(p => p.name === profile),
+ deleteProfile: profile => get().profiles = get().profiles.filter(p => typeof profile === "string" ? p.name !== profile : p.name !== profile.name),
+ duplicateProfile: (profile, name) => {
+ const foundProfile = get().profiles.find(p => typeof profile === "string" ? p.name === profile : p.name === profile.name);
+ if (foundProfile) {
+ foundProfile.name = name;
+ get().profiles.push(foundProfile);
+ }
+ },
+ setCurrentProfile: f => {
+ const currProfile = get().currentProfile;
+ get().currentProfile = (typeof f === "function" ? f(currProfile) ?? currProfile : f ?? currProfile);
+ },
+ saveProfile: profile => {
+ get().deleteProfile(profile.name);
+ get().profiles.push(profile);
+ },
+ isCurrentProfileADefaultProfile: () => defaultProfiles.some(profile => get().currentProfile.name === profile.name),
+ getDefaultProfiles: () => defaultProfiles,
+ getProfiles: defaultProfiles => [...get().profiles, ...(defaultProfiles ? get().getDefaultProfiles() : [])],
+ ...f(set as any, get as any)
+ });
+}
diff --git a/src/equicordplugins/philsPluginLibrary/store/store.ts b/src/equicordplugins/philsPluginLibrary/store/store.ts
new file mode 100644
index 000000000..1e5251e48
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/store/store.ts
@@ -0,0 +1,102 @@
+/*
+ * 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 .
+*/
+
+import { Settings, useSettings } from "@api/Settings";
+
+export type PluginSettings = {
+ [key: string]: any;
+};
+
+export type PluginUse = () => Z;
+export type PluginGet = () => Z;
+export type PluginSet = (s: Z | ((settings: Z) => Z | undefined)) => Z;
+export type PluginInitializer = (set: PluginSet, get: PluginGet) => T;
+export interface PluginStore {
+ use: PluginUse,
+ get: PluginGet,
+ set: PluginSet;
+}
+
+function createObjectProxy(obj1: T, onUpdate: (updatedObject: T) => void): T {
+ const handler: ProxyHandler = {
+ set(target, property, value, receiver) {
+ const success = Reflect.set(target, property, value, receiver);
+ const nestedObj = target[property];
+
+ if (typeof nestedObj === "object") {
+ target[property] = createObjectProxy(nestedObj, () => { onUpdate(obj1); }); // On update will call itself until the top level object
+ }
+
+ onUpdate(obj1); // This will recursively call on nested objects
+ return success;
+ }
+ };
+
+ return new Proxy(obj1, handler);
+}
+
+
+const startupStates = {};
+const settingStorage = new Map();
+export function createPluginStore(pluginName: string, storeName: string, f: PluginInitializer): PluginStore {
+ if (!Settings.plugins[pluginName])
+ throw new Error("The specified plugin does not exist");
+
+ if (!Settings.plugins[pluginName].stores)
+ Settings.plugins[pluginName].stores = {};
+
+ if (!Settings.plugins[pluginName].stores[storeName]) // Just incase the store doesn't exist we create it here (otherwise we crash)
+ Settings.plugins[pluginName].stores[storeName] = {};
+
+ const get: PluginGet = () => {
+ const storeSettings = settingStorage.get(storeName);
+
+ if (!startupStates[storeName]) { // We do this so that we can load all the saved data without the proxy attempting to overwrite it
+ const startupInfo = Settings.plugins[pluginName].stores[storeName];
+ Object.keys(startupInfo).forEach(prop => storeSettings[prop] = startupInfo[prop]);
+
+ startupStates[storeName] = true;
+ }
+
+ return storeSettings;
+ };
+
+ const set: PluginSet = (s: ((settings: Z) => Z | undefined) | Z) =>
+ (typeof s === "function" ? s(get()) : s) || get();
+
+ const use: PluginUse = () => { useSettings().plugins[pluginName].stores[storeName]; return get(); }; // useSettings is called to update renderer (after settings change)
+
+ const initialSettings: Z = f(set, get);
+ const proxiedSettings = createObjectProxy(initialSettings as unknown, updateCallback); // Setup our proxy that allows us connections to the datastore
+
+ function updateCallback(updatedObject: any) {
+ if (!startupStates[storeName]) return; // Wait for the startup information to overwrite the blank proxy
+ Settings.plugins[pluginName].stores[storeName] = JSON.parse(JSON.stringify(updatedObject));
+ }
+
+ for (const key of Object.keys(initialSettings)) { proxiedSettings[key] = initialSettings[key]; } // Set them so the nested objects also become proxies
+ settingStorage.set(storeName, proxiedSettings);
+
+ updateCallback(initialSettings);
+
+ return {
+ use,
+ get,
+ set
+ };
+}
diff --git a/src/equicordplugins/philsPluginLibrary/styles/index.ts b/src/equicordplugins/philsPluginLibrary/styles/index.ts
new file mode 100644
index 000000000..c38f75358
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/styles/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./styles";
diff --git a/src/equicordplugins/philsPluginLibrary/styles/styles.ts b/src/equicordplugins/philsPluginLibrary/styles/styles.ts
new file mode 100644
index 000000000..9c99b5fc4
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/styles/styles.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 .
+*/
+
+export const Styles = {
+ infoCard: {
+ padding: "1em",
+ width: "100%",
+ boxSizing: "border-box"
+ },
+} as const satisfies Record;
diff --git a/src/equicordplugins/philsPluginLibrary/types/common/index.ts b/src/equicordplugins/philsPluginLibrary/types/common/index.ts
new file mode 100644
index 000000000..2521026b5
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/common/index.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 .
+*/
+
+export interface Resolution {
+ width: number;
+ height: number;
+}
+
+export interface Framerate {
+ framerate: number;
+}
+
+export interface Bitrate {
+ min: number;
+ target: number;
+ max: number;
+}
+
+export type DeepPartial = T extends Function
+ ? T
+ : T extends Array
+ ? DeepPartialArray
+ : T extends object
+ ? DeepPartialObject
+ : T | undefined;
+
+interface DeepPartialArray extends Array> { }
+
+type DeepPartialObject = {
+ [key in keyof T]?: DeepPartial;
+};
diff --git a/src/equicordplugins/philsPluginLibrary/types/constants/index.ts b/src/equicordplugins/philsPluginLibrary/types/constants/index.ts
new file mode 100644
index 000000000..df7ec4179
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/constants/index.ts
@@ -0,0 +1,31 @@
+/*
+ * 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 .
+*/
+
+import { PluginAuthor } from "@utils/types";
+
+export type Author = PluginAuthor & { github?: string; };
+export type Contributor = Author;
+
+export interface PluginInfo {
+ [key: string]: any;
+ PLUGIN_NAME: string,
+ DESCRIPTION: string,
+ AUTHOR: PluginAuthor & { github?: string; },
+ CONTRIBUTORS?: Record,
+ README?: string;
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/classes/index.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/classes/index.ts
new file mode 100644
index 000000000..584d422e6
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/classes/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./panelClasses";
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/classes/panelClasses.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/classes/panelClasses.ts
new file mode 100644
index 000000000..f78850cd5
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/classes/panelClasses.ts
@@ -0,0 +1,53 @@
+/*
+ * 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 .
+*/
+
+export interface PanelClasses {
+ container: string;
+ inner: string;
+ channel: string;
+ statusWithPopout: string;
+ hotspot: string;
+ customStatusContainer: string;
+ noiseCancellationPopout: string;
+ noiseCancellationTooltip: string;
+ krispLogo: string;
+ krispLink: string;
+ micTestButton: string;
+ beta: string;
+ connection: string;
+ voiceUsers: string;
+ actionButtons: string;
+ button: string;
+ buttonColor: string;
+ buttonActive: string;
+ fauxDisabled: string;
+ buttonDeveloperActivityShelf: string;
+ active: string;
+ buttonContents: string;
+ buttonIcon: string;
+ withText: string;
+ voicePanelIntroductionHeader: string;
+ voicePanelIntroductionText: string;
+ voicePanelIntroductionButton: string;
+ voicePanelIntroductionWrapper: string;
+ wrapper: string;
+ viewAsRolesWarning: string;
+ viewAsRolesWarningText: string;
+ viewAsRolesWarningButton: string;
+ disabled: string;
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/components/index.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/components/index.ts
new file mode 100644
index 000000000..57f4385eb
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/components/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./userSummaryItem";
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/components/userSummaryItem.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/components/userSummaryItem.ts
new file mode 100644
index 000000000..8e04ab96c
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/components/userSummaryItem.ts
@@ -0,0 +1,35 @@
+/*
+ * 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 .
+*/
+
+import { User } from "discord-types/general";
+import type { ComponentType } from "react";
+
+export interface UserSummaryItemProps {
+ guildId?: string;
+ className?: string;
+ users?: User[];
+ renderUser?: (...props: any[]) => any;
+ renderMoreUsers?: (...props: any[]) => any;
+ max?: number;
+ showUserPopout?: boolean;
+ renderIcon?: boolean;
+ showDefaultAvatarsForNullUsers?: boolean;
+ size?: number;
+}
+
+export type UserSummaryItem = ComponentType;
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/index.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/index.ts
new file mode 100644
index 000000000..af5ab9678
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/index.ts
@@ -0,0 +1,22 @@
+/*
+ * 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 .
+*/
+
+export * from "./classes";
+export * from "./components";
+export * from "./modules";
+export * from "./stores";
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/conn.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/conn.ts
new file mode 100644
index 000000000..d9b969e8b
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/conn.ts
@@ -0,0 +1,56 @@
+/*
+ * 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 .
+*/
+
+export interface Conn {
+ destroy: (...args: any[]) => any;
+ setTransportOptions: (options: Record) => any;
+ setSelfMute: (...args: any[]) => any;
+ setSelfDeafen: (...args: any[]) => any;
+ mergeUsers: (...args: any[]) => any;
+ destroyUser: (...args: any[]) => any;
+ setLocalVolume: (...args: any[]) => any;
+ setLocalMute: (...args: any[]) => any;
+ setLocalPan: (...args: any[]) => any;
+ setDisableLocalVideo: (...args: any[]) => any;
+ setMinimumOutputDelay: (...args: any[]) => any;
+ getEncryptionModes: (...args: any[]) => any;
+ configureConnectionRetries: (...args: any[]) => any;
+ setOnSpeakingCallback: (...args: any[]) => any;
+ setOnSpeakingWhileMutedCallback: (...args: any[]) => any;
+ setPingInterval: (...args: any[]) => any;
+ setPingCallback: (...args: any[]) => any;
+ setPingTimeoutCallback: (...args: any[]) => any;
+ setRemoteUserSpeakingStatus: (...args: any[]) => any;
+ setRemoteUserCanHavePriority: (...args: any[]) => any;
+ setOnVideoCallback: (...args: any[]) => any;
+ setVideoBroadcast: (...args: any[]) => any;
+ setDesktopSource: (...args: any[]) => any;
+ setDesktopSourceWithOptions: (...args: any[]) => any;
+ clearDesktopSource: (...args: any[]) => any;
+ setDesktopSourceStatusCallback: (...args: any[]) => any;
+ setOnDesktopSourceEnded: (...args: any[]) => any;
+ setOnSoundshare: (...args: any[]) => any;
+ setOnSoundshareEnded: (...args: any[]) => any;
+ setOnSoundshareFailed: (...args: any[]) => any;
+ setPTTActive: (...args: any[]) => any;
+ getStats: (...args: any[]) => any;
+ getFilteredStats: (...args: any[]) => any;
+ startReplay: (...args: any[]) => any;
+ startSamplesPlayback: (...args: any[]) => any;
+ stopSamplesPlayback: (...args: any[]) => any;
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/connection.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/connection.ts
new file mode 100644
index 000000000..4809c4712
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/connection.ts
@@ -0,0 +1,387 @@
+/*
+ * 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 .
+*/
+
+import TypedEmitter from "typed-emitter";
+
+import { Framerate, Resolution } from "../../../types";
+import { Conn, FramerateReducer, VideoQualityManager } from "./";
+
+export const ConnectionEvent = {
+ SPEAKING: "speaking",
+ MUTE: "mute",
+ NEW_LISTENER: "newListener",
+ DESTORY: "destroy",
+ CONNECTED: "connected",
+ SILENCE: "silence",
+ DESKTOP_SOURCE_END: "desktopsourceend",
+ SOUNDSHARE_ATTACHED: "soundshareattached",
+ SOUNDSHARE_FAILED: "soundsharefailed",
+ SOUNDSHARE_SPEAKING: "soundsharespeaking",
+ SOUNDSHARE_TRACE: "soundsharetrace",
+ INTERACTION_REQUIRED: "interactionrequired",
+ VIDEOHOOK_INITIALIZED: "videohook-initialize",
+ SCREENSHARE_FAILED: "screenshare-finish",
+ NOISE_CANCELLER_ERROR: "noisecancellererror",
+ VOICE_ACTIVITY_DETECTOR_ERROR: "voiceactivitydetectorerror",
+ VIDEO_STATE: "video-state",
+ VIDEO: "video",
+ FIRST_FRAME: "first-frame",
+ ERROR: "error",
+ CONNECTION_STATE_CHANGE: "connectionstatechange",
+ PING: "ping",
+ PING_TIMEOUT: "pingtimeout",
+ OUTBOUND_LOSSRATE: "outboundlossrate",
+ LOCAL_VIDEO_DISABLED: "local-video-disabled",
+ STATS: "stats",
+} as const;
+
+export type ConnectionEvent = typeof ConnectionEvent;
+
+export type ConnectionEvents = {
+ [ConnectionEvent.SPEAKING]: (...args: any[]) => any;
+ [ConnectionEvent.MUTE]: (...args: any[]) => any;
+ [ConnectionEvent.NEW_LISTENER]: (...args: any[]) => any;
+ [ConnectionEvent.DESTORY]: (...args: any[]) => any;
+ [ConnectionEvent.CONNECTED]: (...args: any[]) => any;
+ [ConnectionEvent.SILENCE]: (...args: any[]) => any;
+ [ConnectionEvent.DESKTOP_SOURCE_END]: (...args: any[]) => any;
+ [ConnectionEvent.SOUNDSHARE_ATTACHED]: (...args: any[]) => any;
+ [ConnectionEvent.SOUNDSHARE_FAILED]: (...args: any[]) => any;
+ [ConnectionEvent.SOUNDSHARE_SPEAKING]: (...args: any[]) => any;
+ [ConnectionEvent.SOUNDSHARE_TRACE]: (...args: any[]) => any;
+ [ConnectionEvent.INTERACTION_REQUIRED]: (...args: any[]) => any;
+ [ConnectionEvent.VIDEOHOOK_INITIALIZED]: (...args: any[]) => any;
+ [ConnectionEvent.SCREENSHARE_FAILED]: (...args: any[]) => any;
+ [ConnectionEvent.NOISE_CANCELLER_ERROR]: (...args: any[]) => any;
+ [ConnectionEvent.VOICE_ACTIVITY_DETECTOR_ERROR]: (...args: any[]) => any;
+ [ConnectionEvent.VIDEO_STATE]: (...args: any[]) => any;
+ [ConnectionEvent.VIDEO]: (...args: any[]) => any;
+ [ConnectionEvent.FIRST_FRAME]: (...args: any[]) => any;
+ [ConnectionEvent.ERROR]: (...args: any[]) => any;
+ [ConnectionEvent.CONNECTION_STATE_CHANGE]: (...args: any[]) => any;
+ [ConnectionEvent.PING]: (...args: any[]) => any;
+ [ConnectionEvent.PING_TIMEOUT]: (...args: any[]) => any;
+ [ConnectionEvent.OUTBOUND_LOSSRATE]: (...args: any[]) => any;
+ [ConnectionEvent.LOCAL_VIDEO_DISABLED]: (...args: any[]) => any;
+ [ConnectionEvent.STATS]: (...args: any[]) => any;
+};
+
+export type Connection = TypedEmitter &
+ Connection__ &
+ Connection_ & {
+ streamUserId: string,
+ goLiveSourceIdentifier?: string;
+ emitter: TypedEmitter;
+ mediaEngineConnectionId: string;
+ destroyed: boolean;
+ audioSSRC: number;
+ selfDeaf: boolean;
+ localMutes: LocalMutes;
+ disabledLocalVideos: LocalMutes;
+ localVolumes: LocalVolumes;
+ isActiveOutputSinksEnabled: boolean;
+ activeOutputSinks: LocalMutes;
+ videoSupported: boolean;
+ useElectronVideo: boolean;
+ voiceBitrate: number;
+ remoteSinkWantsMaxFramerate: number;
+ wantsPriority: Set;
+ localSpeakingFlags: LocalSpeakingFlags;
+ videoReady: boolean;
+ videoStreamParameters: VideoStreamParameter[];
+ remoteVideoSinkWants: VideoSinkWants;
+ localVideoSinkWants: VideoSinkWants;
+ connectionState: string;
+ experimentFlags: string[];
+ context: string;
+ ids: Ids;
+ selfMute: boolean;
+ selfVideo: boolean;
+ forceAudioNormal: boolean;
+ forceAudioPriority: boolean;
+ codecs: Codec[];
+ desktopDegradationPreference: number;
+ sourceDesktopDegradationPreference: number;
+ videoDegradationPreference: number;
+ localPans: LocalMutes;
+ remoteAudioSSRCs: LocalMutes;
+ remoteVideoSSRCs: LocalMutes;
+ inputMode: string;
+ vadThreshold: number;
+ vadAutoThreshold: boolean;
+ vadUseKrisp: boolean;
+ vadLeading: number;
+ vadTrailing: number;
+ pttReleaseDelay: number;
+ soundshareActive: boolean;
+ soundshareId?: any;
+ soundshareSentSpeakingEvent: boolean;
+ echoCancellation: boolean;
+ noiseSuppression: boolean;
+ automaticGainControl: boolean;
+ noiseCancellation: boolean;
+ experimentalEncoders: boolean;
+ hardwareH264: boolean;
+ attenuationFactor: number;
+ attenuateWhileSpeakingSelf: boolean;
+ attenuateWhileSpeakingOthers: boolean;
+ qos: boolean;
+ minimumJitterBufferLevel: number;
+ postponeDecodeLevel: number;
+ reconnectInterval: number;
+ keyframeInterval: number;
+ conn: Conn;
+ stats: Stats;
+ framerateReducer: FramerateReducer;
+ videoQualityManager: VideoQualityManager;
+ handleSpeakingNative: (...args: any[]) => any;
+ handleSpeakingFlags: (...args: any[]) => any;
+ handleSpeakingWhileMuted: (...args: any[]) => any;
+ handlePing: (...args: any[]) => any;
+ handlePingTimeout: (...args: any[]) => any;
+ handleVideo: (...args: any[]) => any;
+ handleFirstFrame: (...args: any[]) => any;
+ handleNoInput: (...args: any[]) => any;
+ handleDesktopSourceEnded: (...args: any[]) => any;
+ handleSoundshare: (...args: any[]) => any;
+ handleSoundshareFailed: (...args: any[]) => any;
+ handleSoundshareEnded: (...args: any[]) => any;
+ handleNewListenerNative: (...args: any[]) => any;
+ handleStats: (...args: any[]) => any;
+ __proto__: Connection_;
+ };
+
+interface Connection_ {
+ initialize: (...args: any[]) => any;
+ destroy: (...args: any[]) => any;
+ setCodecs: (audioCodec: string, videoCodec: string, context: string) => any;
+ getStats: (...args: any[]) => any;
+ createUser: (...args: any[]) => any;
+ destroyUser: (...args: any[]) => any;
+ setSelfMute: (...args: any[]) => any;
+ setSelfDeaf: (...args: any[]) => any;
+ setSoundshareSource: (id: number, loopback: boolean) => void;
+ setLocalMute: (...args: any[]) => any;
+ setLocalVideoDisabled: (...args: any[]) => any;
+ setMinimumJitterBufferLevel: (...args: any[]) => any;
+ setPostponeDecodeLevel: (...args: any[]) => any;
+ setClipRecordSsrc: (...args: any[]) => any;
+ getLocalVolume: (...args: any[]) => any;
+ setLocalVolume: (...args: any[]) => any;
+ setLocalPan: (...args: any[]) => any;
+ isAttenuating: (...args: any[]) => any;
+ setAttenuation: (...args: any[]) => any;
+ setCanHavePriority: (...args: any[]) => any;
+ setBitRate: (...args: any[]) => any;
+ setVoiceBitRate: (target: number) => void;
+ setCameraBitRate: (target: number, min: number, max: number) => void;
+ setEchoCancellation: (...args: any[]) => any;
+ setNoiseSuppression: (...args: any[]) => any;
+ setAutomaticGainControl: (...args: any[]) => any;
+ setNoiseCancellation: (...args: any[]) => any;
+ setExperimentalEncoders: (...args: any[]) => any;
+ setHardwareH264: (...args: any[]) => any;
+ setQoS: (...args: any[]) => any;
+ setInputMode: (...args: any[]) => any;
+ setSilenceThreshold: (...args: any[]) => any;
+ setForceAudioInput: (...args: any[]) => any;
+ setSpeakingFlags: (...args: any[]) => any;
+ clearAllSpeaking: (...args: any[]) => any;
+ setEncryption: (...args: any[]) => any;
+ setReconnectInterval: (...args: any[]) => any;
+ setKeyframeInterval: (keyframeInterval: number) => void;
+ setVideoBroadcast: (...args: any[]) => any;
+ setDesktopSource: (
+ source: string | null,
+ options?: DesktopSourceOptions
+ ) => void;
+ clearDesktopSource: (...args: any[]) => any;
+ setDesktopSourceStatusCallback: (...args: any[]) => any;
+ hasDesktopSource: (...args: any[]) => any;
+ setDesktopEncodingOptions: (
+ width: number,
+ height: number,
+ framerate: number
+ ) => void;
+ setSDP: (...args: any[]) => any;
+ setRemoteVideoSinkWants: (...args: any[]) => any;
+ setLocalVideoSinkWants: (...args: any[]) => any;
+ startSamplesPlayback: (...args: any[]) => any;
+ stopSamplesPlayback: (...args: any[]) => any;
+ startSamplesLocalPlayback: (...args: any[]) => any;
+ stopAllSamplesLocalPlayback: (...args: any[]) => any;
+ stopSamplesLocalPlayback: (...args: any[]) => any;
+ updateVideoQualityCore: (...args: any[]) => any;
+ setStreamParameters: (...args: any[]) => any;
+ applyVideoTransportOptions: (...args: any[]) => any;
+ chooseEncryptionMode: (...args: any[]) => any;
+ getUserOptions: (...args: any[]) => any;
+ createInputModeOptions: (...args: any[]) => any;
+ getAttenuationOptions: (...args: any[]) => any;
+ getCodecParams: (...args: any[]) => any;
+ getCodecOptions: (...args: any[]) => any;
+ getConnectionTransportOptions: (...args: any[]) => any;
+ setStream: (...args: any[]) => any;
+ getUserIdBySsrc: (...args: any[]) => any;
+ setRtcLogEphemeralKey: (...args: any[]) => any;
+ setRtcLogMarker: (...args: any[]) => any;
+ __proto__: Connection__;
+}
+
+interface Connection__ {
+ destroy: (...args: any[]) => any;
+ getLocalMute: (...args: any[]) => any;
+ getLocalVideoDisabled: (...args: any[]) => any;
+ setLocalVideoDisabled: (...args: any[]) => any;
+ getHasActiveVideoOutputSink: (...args: any[]) => any;
+ setHasActiveVideoOutputSink: (...args: any[]) => any;
+ getActiveOutputSinkTrackingEnabled: (...args: any[]) => any;
+ setUseElectronVideo: (...args: any[]) => any;
+ setClipRecordSsrc: (...args: any[]) => any;
+ getStreamParameters: (...args: any[]) => any;
+ setExperimentFlag: (...args: any[]) => any;
+ setConnectionState: (...args: any[]) => any;
+ updateVideoQuality: (...args: any[]) => any;
+ applyVideoQualityMode: (...args: any[]) => any;
+ overwriteQualityForTesting: (args: {
+ encode: Resolution & Framerate;
+ capture: Resolution & Framerate;
+ bitrateMin: number;
+ bitrateMax: number;
+ bitrateTarget: number;
+ }) => any;
+ applyQualityConstraints: (...args: any[]) => any;
+ pickProperties: (...args: any[]) => any;
+ initializeStreamParameters: (...args: any[]) => any;
+ getLocalWant: (...args: any[]) => any;
+ emitStats: (...args: any[]) => any;
+ __proto__: TypedEmitter;
+}
+
+export interface Stats {
+ mediaEngineConnectionId: string;
+ transport: Transport;
+ camera?: any;
+ rtp: Rtp;
+}
+
+export interface Rtp {
+ inbound: LocalMutes;
+ outbound: Outbound[];
+}
+
+export interface Outbound {
+ type: string;
+ ssrc: number;
+ sinkWant: string;
+ codec: OutboundCodec;
+ bytesSent: number;
+ packetsSent: number;
+ packetsLost: number;
+ fractionLost: number;
+ audioLevel: number;
+ audioDetected: number;
+ framesCaptured: number;
+ framesRendered: number;
+ noiseCancellerProcessTime: number;
+}
+
+export interface OutboundCodec {
+ id: number;
+ name: string;
+}
+
+export interface Transport {
+ availableOutgoingBitrate: number;
+ ping: number;
+ decryptionFailures: number;
+ routingFailures: number;
+ localAddress: string;
+ pacerDelay: number;
+ receiverReports: any[];
+ receiverBitrateEstimate: number;
+ outboundBitrateEstimate: number;
+ inboundBitrateEstimate: number;
+ bytesSent: number;
+}
+
+export interface Codec {
+ type: string;
+ name: string;
+ priority: number;
+ payloadType: number;
+ rtxPayloadType?: number;
+ encode?: boolean;
+ decode?: boolean;
+}
+
+export interface Ids {
+ userId: string;
+ channelId: string;
+ guildId: string;
+}
+
+export interface VideoSinkWants {
+ any: number;
+}
+
+export interface VideoStreamParameter {
+ type: string;
+ active: boolean;
+ rid: string;
+ ssrc: number;
+ rtxSsrc: number;
+ quality: number;
+ maxBitrate: number;
+ maxFrameRate: number;
+ maxResolution: MaxResolution;
+ maxPixelCount: number;
+}
+
+export type MaxResolution = Partial & {
+ type: "fixed" | "source";
+};
+
+export interface LocalSpeakingFlags {
+ [key: string]: number;
+}
+
+export interface LocalVolumes {
+ [key: string]: number;
+}
+
+export interface LocalMutes {
+ [key: string]: any;
+}
+
+export const HdrCaptureMode = {
+ NEVER: "never",
+ ALWAYS: "always",
+ PERMITTED_DEVICES_ONLY: "permittedDevicesOnly",
+} as const;
+
+export type HdrCaptureMode = typeof HdrCaptureMode;
+
+export interface DesktopSourceOptions extends Partial {
+ fps?: number;
+ useVideoHook?: boolean;
+ useGraphicsCapture?: boolean;
+ useQuartzCapturer?: boolean;
+ allowScreenCaptureKit?: boolean;
+ hdrCaptureMode?: HdrCaptureMode[keyof HdrCaptureMode];
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/framerateReducer.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/framerateReducer.ts
new file mode 100644
index 000000000..6d659cf7b
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/framerateReducer.ts
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+*/
+
+import { Connection, VideoQualityManager } from "./";
+
+export type FramerateReducer = FramerateReducer_ & {
+ connection: Connection;
+ sinkWants: VideoQualityManager;
+ framerateReductionTimeout?: number;
+ handleSelfMute: (...args: any[]) => any;
+ handleSpeaking: (...args: any[]) => any;
+ __proto__: FramerateReducer_;
+};
+
+export interface FramerateReducer_ {
+ destroy: (...args: any[]) => any;
+ destroyFramerateScaleFactorTimers: (...args: any[]) => any;
+ initialize: (...args: any[]) => any;
+ updateRemoteWantsFramerate: (...args: any[]) => any;
+ userSpeakingChange: (...args: any[]) => any;
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/index.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/index.ts
new file mode 100644
index 000000000..7f2f06cb0
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/index.ts
@@ -0,0 +1,24 @@
+/*
+ * 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 .
+*/
+
+export * from "./conn";
+export * from "./connection";
+export * from "./framerateReducer";
+export * from "./mediaEngine";
+export * from "./utils";
+export * from "./videoQualityManager";
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/mediaEngine.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/mediaEngine.ts
new file mode 100644
index 000000000..2a51eb6b0
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/mediaEngine.ts
@@ -0,0 +1,148 @@
+/*
+ * 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 .
+*/
+
+import TypedEmitter from "typed-emitter";
+
+import { Connection } from "./";
+
+export const MediaEngineEvent = {
+ REMOVE_LISTENER: "removeListener",
+ NEW_LISTENER: "newListener",
+ DESTORY: "destroy",
+ CONNECTION: "connection",
+ DEVICE_CHANGE: "devicechange",
+ VOLUME_CHANGE: "volumechange",
+ DESKTOP_SOURCE_END: "desktopsourceend",
+ AUDIO_PERMISSION: "audio-permission",
+ VIDEO_PERMISSION: "video-permission",
+ WATCHDOG_TIMEOUT: "watchdogtimeout",
+ VIDEO_INPUT_INITIALIZED: "video-input-initialized",
+ CONNECTION_STATS: "connection-stats",
+} as const;
+
+export type MediaEngineEvents = {
+ [MediaEngineEvent.REMOVE_LISTENER]: (...args: any[]) => any;
+ [MediaEngineEvent.NEW_LISTENER]: (...args: any[]) => any;
+ [MediaEngineEvent.DESTORY]: (...args: any[]) => any;
+ [MediaEngineEvent.CONNECTION]: (connection: Connection) => void;
+ [MediaEngineEvent.DEVICE_CHANGE]: (...args: any[]) => any;
+ [MediaEngineEvent.VOLUME_CHANGE]: (...args: any[]) => any;
+ [MediaEngineEvent.DESKTOP_SOURCE_END]: (...args: any[]) => any;
+ [MediaEngineEvent.AUDIO_PERMISSION]: (...args: any[]) => any;
+ [MediaEngineEvent.VIDEO_PERMISSION]: (...args: any[]) => any;
+ [MediaEngineEvent.WATCHDOG_TIMEOUT]: (...args: any[]) => any;
+ [MediaEngineEvent.VIDEO_INPUT_INITIALIZED]: (...args: any[]) => any;
+ [MediaEngineEvent.CONNECTION_STATS]: (...args: any[]) => any;
+ [MediaEngineEvent.REMOVE_LISTENER]: (...args: any[]) => any;
+};
+
+export type MediaEngine = TypedEmitter &
+ MediaEngine_ & {
+ Video: (...args: any[]) => any;
+ Camera: (...args: any[]) => any;
+ handleDeviceChange: (...args: any[]) => any;
+ handleVolumeChange: (...args: any[]) => any;
+ handleVoiceActivity: (...args: any[]) => any;
+ handleActiveSinksChange: (...args: any[]) => any;
+ handleNewListener: (...args: any[]) => any;
+ handleRemoveListener: (...args: any[]) => any;
+ handleVideoInputInitialization: (...args: any[]) => any;
+ emitter: TypedEmitter;
+ videoInputDeviceId: string;
+ lastVoiceActivity: number;
+ audioSubsystem: string;
+ audioLayer: string;
+ loopback: boolean;
+ deviceChangeGeneration: number;
+ consecutiveWatchdogFailures: number;
+ codecSurvey?: any;
+ connections: Set;
+ __proto__: MediaEngine_;
+ };
+
+export interface MediaEngine_ {
+ destroy: (...args: any[]) => any;
+ interact: (...args: any[]) => any;
+ supported: (...args: any[]) => any;
+ supports: (...args: any[]) => any;
+ connect: (...args: any[]) => any;
+ shouldConnectionBroadcastVideo: (...args: any[]) => any;
+ eachConnection: (callback: (connection: Connection) => void) => void;
+ enable: (...args: any[]) => any;
+ setInputVolume: (...args: any[]) => any;
+ setOutputVolume: (...args: any[]) => any;
+ getAudioInputDevices: (...args: any[]) => any;
+ setAudioInputDevice: (...args: any[]) => any;
+ getAudioOutputDevices: (...args: any[]) => any;
+ setAudioOutputDevice: (...args: any[]) => any;
+ getVideoInputDevices: (...args: any[]) => any;
+ setVideoInputDevice: (...args: any[]) => any;
+ getSupportedVideoCodecs: (...args: any[]) => any;
+ getCodecCapabilities: (callback: (codecs: string) => void) => void;
+ setDesktopSource: (...args: any[]) => any;
+ setSoundshareSource: (...args: any[]) => any;
+ getDesktopSource: (...args: any[]) => any;
+ getDesktopSources: (...args: any[]) => any;
+ getScreenPreviews: (...args: any[]) => any;
+ setClipBufferLength: (...args: any[]) => any;
+ saveClip: (...args: any[]) => any;
+ updateClipMetadata: (...args: any[]) => any;
+ exportClip: (...args: any[]) => any;
+ getWindowPreviews: (
+ width: number,
+ height: number
+ ) => Promise;
+ setAudioSubsystem: (...args: any[]) => any;
+ getAudioSubsystem: (...args: any[]) => any;
+ getAudioLayer: (...args: any[]) => any;
+ getDebugLogging: (...args: any[]) => any;
+ setDebugLogging: (...args: any[]) => any;
+ setExperimentalAdm: (...args: any[]) => any;
+ setLoopback: (...args: any[]) => any;
+ getLoopback: (...args: any[]) => any;
+ setH264Enabled: (...args: any[]) => any;
+ setAv1Enabled: (...args: any[]) => any;
+ getCodecSurvey: () => Promise;
+ writeAudioDebugState: (...args: any[]) => any;
+ startAecDump: (...args: any[]) => any;
+ stopAecDump: (...args: any[]) => any;
+ setAecDump: (...args: any[]) => any;
+ rankRtcRegions: (...args: any[]) => any;
+ getSoundshareStatus: (...args: any[]) => any;
+ enableSoundshare: (...args: any[]) => any;
+ createReplayConnection: (...args: any[]) => any;
+ setUseDirectVideo: (...args: any[]) => any;
+ setMaxSyncDelayOverride: (...args: any[]) => any;
+ applyMediaFilterSettings: (...args: any[]) => any;
+ startLocalAudioRecording: (...args: any[]) => any;
+ stopLocalAudioRecording: (...args: any[]) => any;
+ watchdogTick: (...args: any[]) => any;
+ __proto__: TypedEmitter;
+}
+
+export interface CodecCapabilities {
+ codec: string;
+ decode: boolean;
+ encode: boolean;
+}
+
+export interface WindowPreview {
+ id: string;
+ url: string;
+ name: string;
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/utils.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/utils.ts
new file mode 100644
index 000000000..af25211d9
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/utils.ts
@@ -0,0 +1,103 @@
+/*
+ * 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 .
+*/
+
+export interface Utils {
+ requireModule: (...args: any[]) => any;
+ ensureModule: (...args: any[]) => any;
+ getCrashReporterMetadata: (...args: any[]) => any;
+ getSetting: (...args: any[]) => any;
+ beforeUnload: (...args: any[]) => any;
+ inputEventRegister: (...args: any[]) => any;
+ inputEventUnregister: (...args: any[]) => any;
+ setOnInputEventCallback: (...args: any[]) => any;
+ setFocused: (...args: any[]) => any;
+ getIdleMilliseconds: (...args: any[]) => any;
+ setObservedGamesCallback: (...args: any[]) => any;
+ setCandidateGamesCallback: (...args: any[]) => any;
+ clearCandidateGamesCallback: (...args: any[]) => any;
+ setGameCandidateOverrides: (...args: any[]) => any;
+ detectPid: (...args: any[]) => any;
+ undetectPid: (...args: any[]) => any;
+ shouldDisplayNotifications: (...args: any[]) => any;
+ getVoiceEngine: (...args: any[]) => any;
+ getDiscordUtils: (...args: any[]) => any;
+ isSystemDarkMode: (...args: any[]) => any;
+ getGameUtils: (...args: any[]) => any;
+ getCloudSync: (...args: any[]) => any;
+ getDispatch: (...args: any[]) => any;
+ setBadge: (...args: any[]) => any;
+ setSystemTrayIcon: (...args: any[]) => any;
+ setThumbarButtons: (...args: any[]) => any;
+ bounceDock: (...args: any[]) => any;
+ setSystemTrayApplications: (...args: any[]) => any;
+ architecture: (...args: any[]) => any;
+ moduleVersions: (...args: any[]) => any;
+ copy: (...args: any[]) => any;
+ copyImage: (...args: any[]) => any;
+ saveImage: (...args: any[]) => any;
+ saveFile: (...args: any[]) => any;
+ canCopyImage: (...args: any[]) => any;
+ cut: (...args: any[]) => any;
+ paste: (...args: any[]) => any;
+ readClipboard: (...args: any[]) => any;
+ on: (...args: any[]) => any;
+ invoke: (...args: any[]) => any;
+ send: (...args: any[]) => any;
+ flashFrame: (...args: any[]) => any;
+ minimize: (...args: any[]) => any;
+ restore: (...args: any[]) => any;
+ maximize: (...args: any[]) => any;
+ focus: (...args: any[]) => any;
+ blur: (...args: any[]) => any;
+ fullscreen: (...args: any[]) => any;
+ close: (...args: any[]) => any;
+ setAlwaysOnTop: (...args: any[]) => any;
+ isAlwaysOnTop: (...args: any[]) => any;
+ purgeMemory: (...args: any[]) => any;
+ updateCrashReporter: (...args: any[]) => any;
+ flushDNSCache: (...args: any[]) => any;
+ supportsFeature: (...args: any[]) => any;
+ getEnableHardwareAcceleration: (...args: any[]) => any;
+ setEnableHardwareAcceleration: (...args: any[]) => any;
+ getGPUDriverVersions: (...args: any[]) => any;
+ setZoomFactor: (...args: any[]) => any;
+ setBackgroundThrottling: (...args: any[]) => any;
+ getPidFromDesktopSource: (...args: any[]) => any;
+ getDesktopSourceFromPid: (...args: any[]) => any;
+ generateSessionFromPid: (...args: any[]) => any;
+ getAudioPid: (...args: any[]) => any;
+ setForegroundProcess: (...args: any[]) => any;
+ getDiscordMemoryUsage: (...args: any[]) => any;
+ showOpenDialog: (...args: any[]) => any;
+ flushStorageData: (...args: any[]) => any;
+ flushCookies: (...args: any[]) => any;
+ setCrashInformation: (...args: any[]) => any;
+ blockDisplaySleep: (...args: any[]) => any;
+ unblockDisplaySleep: (...args: any[]) => any;
+ cleanupDisplaySleep: (...args: any[]) => any;
+ relaunch: (...args: any[]) => any;
+ makeChunkedRequest: (...args: any[]) => any;
+ submitLiveCrashReport: (...args: any[]) => any;
+ crash: (...args: any[]) => any;
+ setApplicationBackgroundColor: (...args: any[]) => any;
+ asyncify: (...args: any[]) => any;
+ releaseChannel: string,
+ canBootstrapNewUpdater: boolean;
+ buildNumber: number;
+ version: number[];
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/videoQualityManager.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/videoQualityManager.ts
new file mode 100644
index 000000000..fee629342
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/modules/videoQualityManager.ts
@@ -0,0 +1,81 @@
+/*
+ * 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 .
+*/
+
+import { Bitrate, Framerate, Resolution } from "../../";
+import { Connection } from "./";
+
+export type VideoQualityManager = VideoQualityManager_ & {
+ connection: Connection;
+ contextType: string;
+ isMuted: boolean;
+ isStreamContext: boolean;
+ ladder: Ladder;
+ options: Options;
+ qualityOverwrite: QualityOverwrite;
+ __proto__: VideoQualityManager_;
+};
+
+export interface VideoQualityManager_ {
+ applyQualityConstraints: (...args: any[]) => any;
+ getDesktopQuality: (...args: any[]) => any;
+ getQuality: (...args: any[]) => any;
+ getVideoQuality: (...args: any[]) => any;
+ setQuality: (...args: any[]) => any;
+}
+
+export interface QualityOverwrite {
+ bitrateMax?: number;
+ bitrateMin?: number;
+ bitrateTarget?: number;
+ capture?: Resolution & Framerate;
+ encode?: Resolution & Framerate;
+}
+
+export interface Options {
+ videoBudget: VideoBudget;
+ videoCapture: VideoBudget;
+ videoBitrate: VideoBitrate;
+ desktopBitrate: DesktopBitrate;
+ videoBitrateFloor: number;
+}
+
+export type DesktopBitrate = Bitrate;
+
+export type VideoBitrate = Omit;
+
+export type VideoBudget = Resolution & Framerate;
+
+export interface Ladder {
+ pixelBudget: number;
+ ladder: {
+ [key: number]: LadderValue;
+ };
+ orderedLadder: OrderedLadder[];
+}
+
+export interface OrderedLadder extends Resolution, Framerate {
+ pixelCount: number;
+ wantValue: number;
+ budgetPortion: number;
+ mutedFramerate: Framerate;
+}
+
+export interface LadderValue extends Resolution, Framerate {
+ budgetPortion: number;
+ mutedFramerate: Framerate;
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/stores/index.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/stores/index.ts
new file mode 100644
index 000000000..ead1316a8
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/stores/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./mediaEngineStore";
diff --git a/src/equicordplugins/philsPluginLibrary/types/discordModules/stores/mediaEngineStore.ts b/src/equicordplugins/philsPluginLibrary/types/discordModules/stores/mediaEngineStore.ts
new file mode 100644
index 000000000..97c52fddc
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/discordModules/stores/mediaEngineStore.ts
@@ -0,0 +1,119 @@
+/*
+ * 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 .
+*/
+
+import { types } from "../../..";
+
+export type MediaEngineStore = MediaEngineStore__ &
+ MediaEngineStore_ & {
+ __proto__: MediaEngineStore_;
+ };
+
+export interface MediaEngineStore_ {
+ initialize: (...args: any[]) => any;
+ supports: (...args: any[]) => any;
+ supportsInApp: (...args: any[]) => any;
+ isSupported: (...args: any[]) => any;
+ isExperimentalEncodersSupported: (...args: any[]) => any;
+ isNoiseSuppressionSupported: (...args: any[]) => any;
+ isNoiseCancellationSupported: (...args: any[]) => any;
+ isNoiseCancellationError: (...args: any[]) => any;
+ isAutomaticGainControlSupported: (...args: any[]) => any;
+ isAdvancedVoiceActivitySupported: (...args: any[]) => any;
+ isAecDumpSupported: (...args: any[]) => any;
+ isSimulcastSupported: (...args: any[]) => any;
+ getAecDump: (...args: any[]) => any;
+ getMediaEngine: () => types.MediaEngine;
+ getVideoComponent: (...args: any[]) => any;
+ getCameraComponent: (...args: any[]) => any;
+ isEnabled: (...args: any[]) => any;
+ isMute: (...args: any[]) => any;
+ isDeaf: (...args: any[]) => any;
+ hasContext: (...args: any[]) => any;
+ isSelfMutedTemporarily: (...args: any[]) => any;
+ isSelfMute: (...args: any[]) => any;
+ isHardwareMute: (...args: any[]) => any;
+ isSelfDeaf: (...args: any[]) => any;
+ isVideoEnabled: (...args: any[]) => any;
+ isVideoAvailable: (...args: any[]) => any;
+ isScreenSharing: (...args: any[]) => any;
+ isSoundSharing: (...args: any[]) => any;
+ isLocalMute: (...args: any[]) => any;
+ supportsDisableLocalVideo: (...args: any[]) => any;
+ isLocalVideoDisabled: (...args: any[]) => any;
+ isLocalVideoAutoDisabled: (...args: any[]) => any;
+ isMediaFilterSettingLoading: (...args: any[]) => any;
+ isNativeAudioPermissionReady: (...args: any[]) => any;
+ getDesktopSource: (...args: any[]) => any;
+ getDesktopSourceContext: (...args: any[]) => any;
+ getLocalPan: (...args: any[]) => any;
+ getLocalVolume: (...args: any[]) => any;
+ getInputVolume: (...args: any[]) => any;
+ getOutputVolume: (...args: any[]) => any;
+ getMode: (...args: any[]) => any;
+ getModeOptions: (...args: any[]) => any;
+ getShortcuts: (...args: any[]) => any;
+ getInputDeviceId: (...args: any[]) => any;
+ getOutputDeviceId: (...args: any[]) => any;
+ getVideoDeviceId: (...args: any[]) => any;
+ getInputDevices: (...args: any[]) => any;
+ getOutputDevices: (...args: any[]) => any;
+ getVideoDevices: (...args: any[]) => any;
+ getEchoCancellation: (...args: any[]) => any;
+ getLoopback: (...args: any[]) => any;
+ getNoiseSuppression: (...args: any[]) => any;
+ getAutomaticGainControl: (...args: any[]) => any;
+ getNoiseCancellation: (...args: any[]) => any;
+ getExperimentalEncoders: (...args: any[]) => any;
+ getHardwareH264: (...args: any[]) => any;
+ getEnableSilenceWarning: (...args: any[]) => any;
+ getDebugLogging: (...args: any[]) => any;
+ getQoS: (...args: any[]) => any;
+ getAttenuation: (...args: any[]) => any;
+ getAttenuateWhileSpeakingSelf: (...args: any[]) => any;
+ getAttenuateWhileSpeakingOthers: (...args: any[]) => any;
+ getAudioSubsystem: (...args: any[]) => any;
+ getSettings: (...args: any[]) => any;
+ getState: (...args: any[]) => any;
+ getInputDetected: (...args: any[]) => any;
+ getNoInputDetectedNotice: (...args: any[]) => any;
+ getPacketDelay: (...args: any[]) => any;
+ setCanHavePriority: (...args: any[]) => any;
+ isInteractionRequired: (...args: any[]) => any;
+ getVideoHook: (...args: any[]) => any;
+ getExperimentalSoundshare: (...args: any[]) => any;
+ supportsExperimentalSoundshare: (...args: any[]) => any;
+ getOpenH264: (...args: any[]) => any;
+ getAv1Enabled: (...args: any[]) => any;
+ getEverSpeakingWhileMuted: (...args: any[]) => any;
+ getSoundshareEnabled: (...args: any[]) => any;
+ supportsEnableSoundshare: (...args: any[]) => any;
+ getVideoStreamParameters: (...args: any[]) => any;
+ __proto__: MediaEngineStore__;
+}
+
+export interface MediaEngineStore__ {
+ registerActionHandlers: (...args: any[]) => any;
+ getName: (...args: any[]) => any;
+ initializeIfNeeded: (...args: any[]) => any;
+ initialize: (...args: any[]) => any;
+ syncWith: (...args: any[]) => any;
+ waitFor: (...args: any[]) => any;
+ emitChange: (...args: any[]) => any;
+ getDispatchToken: (...args: any[]) => any;
+ mustEmitChanges: (...args: any[]) => any;
+}
diff --git a/src/equicordplugins/philsPluginLibrary/types/index.ts b/src/equicordplugins/philsPluginLibrary/types/index.ts
new file mode 100644
index 000000000..d3268dfdb
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/types/index.ts
@@ -0,0 +1,21 @@
+/*
+ * 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 .
+*/
+
+export * from "./common";
+export * from "./constants";
+export * from "./discordModules";
diff --git a/src/equicordplugins/philsPluginLibrary/utils/index.ts b/src/equicordplugins/philsPluginLibrary/utils/index.ts
new file mode 100644
index 000000000..adc94f678
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/utils/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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 .
+*/
+
+export * from "./utils";
diff --git a/src/equicordplugins/philsPluginLibrary/utils/utils.ts b/src/equicordplugins/philsPluginLibrary/utils/utils.ts
new file mode 100644
index 000000000..3568f2998
--- /dev/null
+++ b/src/equicordplugins/philsPluginLibrary/utils/utils.ts
@@ -0,0 +1,27 @@
+/*
+ * 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 .
+*/
+
+import { UserStore } from "@webpack/common";
+import { User } from "discord-types/general";
+
+export const createDummyUser = (props: Partial) => new (UserStore.getCurrentUser().constructor as any)(props);
+export const openURL = (url: string) => VencordNative.native.openExternal(url);
+export const validateNumberInput = (value: string) => parseInt(value) ? parseInt(value) : undefined;
+export const validateTextInputNumber = (value: string) => /^[0-9\b]+$/.test(value) || value === "";
+export const replaceObjectValuesIfExist =
+ (target: Object, replace: Object) => Object.entries(target).forEach(([key, value]) => replace[key] && (target[key] = replace[key]));
diff --git a/src/plugins/biggerStreamPreview/index.tsx b/src/plugins/biggerStreamPreview/index.tsx
index 8cca912bc..a86e3fcaa 100644
--- a/src/plugins/biggerStreamPreview/index.tsx
+++ b/src/plugins/biggerStreamPreview/index.tsx
@@ -88,7 +88,7 @@ export const userContextPatch: NavContextMenuPatchCallback = (children, { user }
export default definePlugin({
name: "BiggerStreamPreview",
description: "This plugin allows you to enlarge stream previews",
- authors: [Devs.phil],
+ authors: [Devs.philhk],
contextMenus: {
"user-context": userContextPatch,
"stream-context": streamContextPatch
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index c866f0f4f..f9185d633 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -320,8 +320,8 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "amia",
id: 142007603549962240n
},
- phil: {
- name: "phil",
+ philhk: {
+ name: "philhk",
id: 305288513941667851n
},
ImLvna: {