Remove Stereo

This commit is contained in:
thororen1234 2024-05-20 15:39:31 -04:00
parent 9d0550bf79
commit 01b490a3af
83 changed files with 0 additions and 5217 deletions

View file

@ -1,331 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Flex } from "@components/Flex";
import { Switch } from "@components/Switch";
import { ModalSize } from "@utils/modal";
import { Card, Forms, Select, Slider, TextInput, useEffect, useState } from "@webpack/common";
import { SelectOption } from "@webpack/types";
import {
ProfilableStore,
SettingsModal,
SettingsModalCard,
SettingsModalCardItem,
SettingsModalCardRow,
SettingsModalProfilesCard,
validateNumberInput,
validateTextInputNumber
} from "../../philsPluginLibrary";
import { Styles } from "../../philsPluginLibrary/styles";
import { MicrophoneProfile, MicrophoneStore } from "../stores";
const simpleVoiceBitrates: readonly SelectOption[] = [
{
label: "Normal",
value: 96
},
{
label: "Medium-High",
value: 160
},
{
label: "High",
value: 320
},
{
label: "Very-High",
value: 512
}
] as const;
export interface MicrophoneSettingsModalProps extends React.ComponentProps<typeof SettingsModal> {
microphoneStore: ProfilableStore<MicrophoneStore, MicrophoneProfile>;
showInfo?: boolean;
}
export const MicrophoneSettingsModal = (props: MicrophoneSettingsModalProps) => {
const { microphoneStore, showInfo } = props;
const {
currentProfile,
simpleMode,
setSimpleMode,
deleteProfile,
duplicateProfile,
getCurrentProfile,
getDefaultProfiles,
getProfile,
getProfiles,
isCurrentProfileADefaultProfile,
profiles,
saveProfile,
setChannels,
setChannelsEnabled,
setCurrentProfile,
setFreq,
setFreqEnabled,
setPacsize,
setPacsizeEnabled,
setRate,
setRateEnabled,
setVoiceBitrate,
setVoiceBitrateEnabled
} = microphoneStore.use();
const {
name,
channels,
channelsEnabled,
freq,
freqEnabled,
pacsize,
pacsizeEnabled,
rate,
rateEnabled,
voiceBitrate,
voiceBitrateEnabled
} = currentProfile;
const [isSaving, setIsSaving] = useState(false);
const [rateInput, setRateInput] = useState<string>(rate ? rate.toString() : "");
const [freqInput, setFreqInput] = useState<string>(freq ? freq.toString() : "");
const [pacsizeInput, setPacsizeInput] = useState<string>(pacsize ? pacsize.toString() : "");
const [channelsInput, setChannelsInput] = useState<string>(channels ? channels.toString() : "");
useEffect(() => {
setRateInput(rate ? rate.toString() : "");
setFreqInput(freq ? freq.toString() : "");
setPacsizeInput(pacsize ? pacsize.toString() : "");
setChannelsInput(channels ? channels.toString() : "");
}, [rate, freq, pacsize, channels]);
const simpleToggle =
<Flex style={{ justifyContent: "center", alignItems: "center", gap: "0.6em" }}>
<Forms.FormTitle style={{ margin: 0 }} tag="h5">Simple</Forms.FormTitle>
<Switch checked={simpleMode ?? false} disabled={isSaving} onChange={checked => setSimpleMode(checked)} />
</Flex>;
const settingsCardVoiceBitrateSimple =
<SettingsModalCard
title="Audio Bitrate"
switchEnabled
flex={0.8}
switchProps={{
checked: voiceBitrateEnabled ?? false,
disabled: isSaving,
onChange: status => setVoiceBitrateEnabled(status)
}}>
<SettingsModalCardItem>
<Select
isDisabled={!voiceBitrateEnabled || isSaving}
options={simpleVoiceBitrates}
select={(value: number) => setVoiceBitrate(value)}
isSelected={(value: number) => value === voiceBitrate}
serialize={() => ""} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardChannelsSimple =
<SettingsModalCard
title="Stereo"
flex={0.2}
switchEnabled
switchProps={{
checked: (channelsEnabled && channels === 2) ?? false,
disabled: isSaving,
onChange: status => void setChannelsEnabled(status) ?? setChannels(2)
}}>
</SettingsModalCard>;
const settingsCardVoiceBitrate =
<SettingsModalCard
title="Audio Bitrate"
switchEnabled
flex={0.4}
switchProps={{
checked: voiceBitrateEnabled ?? false,
disabled: isSaving,
onChange: status => setVoiceBitrateEnabled(status)
}}>
<SettingsModalCardItem title="Kb/s">
<div style={{ paddingTop: "0.3em", paddingRight: "0.4em", paddingLeft: "0.4em", boxSizing: "border-box" }}>
<Slider
disabled={!voiceBitrateEnabled || isSaving}
onValueChange={value => setVoiceBitrate(value)}
initialValue={voiceBitrate || 8}
minValue={8}
maxValue={512}
markers={[8, 96, 320, 512]}
onValueRender={value => `${value.toFixed(0)}kb/s`} />
</div>
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardRate =
<SettingsModalCard
title="Sample Rate"
switchEnabled
switchProps={{
checked: rateEnabled ?? false,
disabled: isSaving,
onChange: status => setRateEnabled(status)
}}>
<SettingsModalCardItem>
<TextInput
disabled={!rateEnabled || isSaving}
value={rateInput}
onChange={value => validateTextInputNumber(value) && setRateInput(value)}
onBlur={e => {
const result = validateNumberInput(e.target.value);
setRate(result);
setRateInput(result ? result.toString() : "");
}} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardFreq =
<SettingsModalCard
title="Sample Frequency"
switchEnabled
switchProps={{
checked: freqEnabled ?? false,
disabled: isSaving,
onChange: status => setFreqEnabled(status)
}}>
<SettingsModalCardItem>
<TextInput
disabled={!freqEnabled || isSaving}
value={freqInput}
onChange={value => validateTextInputNumber(value) && setFreqInput(value)}
onBlur={e => {
const result = validateNumberInput(e.target.value);
setFreq(result);
setFreqInput(result ? result.toString() : "");
}} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardPacsize =
<SettingsModalCard
title="Pac Size"
switchEnabled
switchProps={{
checked: pacsizeEnabled ?? false,
disabled: isSaving,
onChange: status => setPacsizeEnabled(status)
}}>
<SettingsModalCardItem>
<TextInput
disabled={!pacsizeEnabled || isSaving}
value={pacsizeInput}
onChange={value => validateTextInputNumber(value) && setPacsizeInput(value)}
onBlur={e => {
const result = validateNumberInput(e.target.value);
setPacsize(result);
setPacsizeInput(result ? result.toString() : "");
}} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardChannels =
<SettingsModalCard
title="Channels"
switchEnabled
switchProps={{
checked: channelsEnabled ?? false,
disabled: isSaving,
onChange: status => setChannelsEnabled(status)
}}>
<SettingsModalCardItem>
<TextInput
disabled={!channelsEnabled || isSaving}
value={channelsInput}
onChange={value => validateTextInputNumber(value) && setChannelsInput(value)}
onBlur={e => {
const result = validateNumberInput(e.target.value);
setChannels(result);
setChannelsInput(result ? result.toString() : "");
}} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardProfiles =
<SettingsModalProfilesCard
flex={0.6}
onSaveStateChanged={state => setIsSaving(state)}
profileableStore={microphoneStore} />;
const infoCard =
<Card style={{ ...Styles.infoCard }}>
<Forms.FormTitle tag="h5">Important</Forms.FormTitle>
<Forms.FormText>
To take full advantage of this plugin, please disable <span style={{ fontWeight: "bold" }}>Krisp</span> and <span style={{ fontWeight: "bold" }}>Echo Cancellation</span>, otherwise features like Stereo (Channels) will not work.
</Forms.FormText>
</Card>;
return (
<SettingsModal
size={simpleMode ? ModalSize.DYNAMIC : ModalSize.DYNAMIC}
title="Microphone Settings"
closeButtonName="Apply"
footerContent={
<Flex style={{ justifyContent: "center", alignItems: "center", marginLeft: "auto" }}>
{simpleToggle}
</Flex>
}
{...props}
onDone={() => {
props.onClose();
props.onDone && props.onDone();
}}
>
{simpleMode
? <div style={{ width: "30em", display: "flex", flexDirection: "column", gap: "1em" }}>
<SettingsModalCardRow>
{settingsCardVoiceBitrateSimple}
{settingsCardChannelsSimple}
</SettingsModalCardRow>
{showInfo &&
<SettingsModalCardRow>
{infoCard}
</SettingsModalCardRow>
}
</div>
: <div style={{ display: "flex", flexDirection: "column", width: "50em", gap: "1em", maxHeight: "30em" }}>
<SettingsModalCardRow>
{settingsCardFreq}
{settingsCardRate}
{settingsCardPacsize}
{settingsCardChannels}
</SettingsModalCardRow>
<SettingsModalCardRow>
{settingsCardVoiceBitrate}
{settingsCardProfiles}
</SettingsModalCardRow>
{showInfo &&
<SettingsModalCardRow>
{infoCard}
</SettingsModalCardRow>
}
</div>
}
</SettingsModal>
);
};

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./MicrophoneSettingsModal";

View file

@ -1,47 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
import { addSettingsPanelButton, Emitter, MicrophoneSettingsIcon, removeSettingsPanelButton } from "../philsPluginLibrary";
import { openMicrophoneSettingsModal } from "./modals";
import { MicrophonePatcher } from "./patchers";
import { initMicrophoneStore } from "./stores";
let microphonePatcher;
export default definePlugin({
name: "BetterMicrophone",
description: "This plugin allows you to further customize your microphone.",
authors: [Devs.philhk],
dependencies: ["PhilsPluginLibrary"],
microphonePatcher,
start() {
initMicrophoneStore();
this.microphonePatcher = new MicrophonePatcher().patch();
addSettingsPanelButton({ name: "BetterMicrophone", icon: MicrophoneSettingsIcon, tooltipText: "Microphone Settings", onClick: openMicrophoneSettingsModal });
},
stop() {
this.microphonePatcher?.unpatch();
Emitter.removeAllListeners("BetterMicrophone");
removeSettingsPanelButton("BetterMicrophone");
}
});

View file

@ -1,21 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Logger } from "@utils/Logger";
export const logger = new Logger("BetterMicrophone");

View file

@ -1,42 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Devs } from "@utils/constants";
import { openModalLazy } from "@utils/modal";
import { MicrophoneSettingsModal } from "../components";
import Plugin from "../index";
import { microphoneStore } from "../stores";
const onMicrophoneModalDone = () => {
const { microphonePatcher } = Plugin;
if (microphonePatcher)
microphonePatcher.forceUpdateTransportationOptions();
};
export const openMicrophoneSettingsModal =
() => openModalLazy(async () => {
return props =>
<MicrophoneSettingsModal
onDone={onMicrophoneModalDone}
showInfo
microphoneStore={microphoneStore}
author={Devs.philhk}
{...props} />;
});

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./microphone";

View file

@ -1,70 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Emitter, MediaEngineStore, Patcher, types } from "../../philsPluginLibrary";
import { patchConnectionAudioTransportOptions } from "../../philsPluginLibrary/patches/audio";
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,
"BetterMicrophone"
);
return this;
}
public unpatch(): this {
return this._unpatch();
}
}

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./microphoneStore";

View file

@ -1,93 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { createPluginStore, ProfilableInitializer, ProfilableStore, profileable, ProfileableProfile } from "../../philsPluginLibrary";
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<string, MicrophoneProfile & ProfileableProfile>;
export const microphoneStoreDefault: ProfilableInitializer<MicrophoneStore, MicrophoneProfile> = (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<MicrophoneStore, MicrophoneProfile>;
export const initMicrophoneStore = () =>
microphoneStore = createPluginStore(
"BetterMicrophone",
"MicrophoneStore",
profileable(
microphoneStoreDefault,
{ name: "" },
Object.values(defaultMicrophoneProfiles)
)
);

View file

@ -1,62 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<types.WindowPreview[]>([]);
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 (
<Select
options={windowPreviews.map(({ name, id }) => ({
label: name,
value: id
}))}
isSelected={value => audioSource === value}
select={value => setAudioSource(value)}
serialize={() => ""}
{...props}
></Select>
);
};

View file

@ -1,38 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Button } from "@webpack/common";
import React from "react";
import { openScreenshareModal } from "../modals";
export interface OpenScreenshareSettingsButtonProps {
title?: string;
}
export const OpenScreenshareSettingsButton = (props: OpenScreenshareSettingsButtonProps) => {
return (
<Button
size={Button.Sizes.SMALL}
color={Button.Colors.PRIMARY}
onClick={openScreenshareModal}
>
{props.title ? props.title : "Screenshare Settings"}
</Button>
);
};

View file

@ -1,457 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Flex } from "@components/Flex";
import { Switch } from "@components/Switch";
import { ModalSize, openModalLazy } from "@utils/modal";
import { Button, Forms, React, Select, Slider, TextInput, useEffect, useState } from "@webpack/common";
import { SelectOption } from "@webpack/types";
import { MicrophoneSettingsModal } from "../../betterMicrophone.desktop/components";
import {
MediaEngineStore,
ProfilableStore,
SettingsModal,
SettingsModalCard,
SettingsModalCardItem,
SettingsModalCardRow,
SettingsModalProfilesCard,
types,
validateNumberInput,
validateTextInputNumber
} from "../../philsPluginLibrary";
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<typeof SettingsModal> {
screenshareStore: ProfilableStore<ScreenshareStore, ScreenshareProfile>;
screenshareAudioStore?: ProfilableStore<ScreenshareAudioStore, ScreenshareAudioProfile>;
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<types.CodecCapabilities[]>([]);
const [isSaving, setIsSaving] = useState(false);
const [textinputWidth, setTextinputWidth] = useState<string>(width ? width.toString() : "");
const [textinputHeight, setTextinputHeight] = useState<string>(height ? height.toString() : "");
const [textinputFramerate, setTextinputFramerate] = useState<string>(framerate ? framerate.toString() : "");
const [textinputKeyframeInterval, setTextinputKeyframeInterval] = useState<string>(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 =
<SettingsModalCard
title="Resolution"
switchEnabled
switchProps={{
checked: resolutionEnabled ?? false,
disabled: isSaving,
onChange: status => setResolutionEnabled(status)
}}>
<SettingsModalCardItem>
<Select
isDisabled={!resolutionEnabled || isSaving}
options={simpleResolutions}
select={(value: types.Resolution) => void setWidth(value.width) ?? setHeight(value.height)}
isSelected={(value: types.Resolution) => width === value.width && height === value.height}
serialize={() => ""} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardVideoBitrateSimple =
<SettingsModalCard
title="Video Bitrate"
switchEnabled
switchProps={{
checked: videoBitrateEnabled ?? false,
disabled: isSaving,
onChange: status => setVideoBitrateEnabled(status)
}}>
<SettingsModalCardItem>
<Select
isDisabled={!videoBitrateEnabled || isSaving}
options={simpleVideoBitrates}
select={(value: number) => void setVideoBitrate(value)}
isSelected={(value: number) => videoBitrate === value}
serialize={() => ""} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardResolution =
<SettingsModalCard
title="Resolution"
flex={0.5}
switchEnabled
switchProps={{
checked: resolutionEnabled ?? false,
onChange: status => setResolutionEnabled(status),
disabled: isSaving
}}>
<SettingsModalCardItem title="Width">
<TextInput
disabled={!resolutionEnabled || isSaving}
value={textinputWidth}
onChange={value => validateTextInputNumber(value) && setTextinputWidth(value)}
onBlur={e => {
const result = validateNumberInput(e.target.value);
setWidth(result);
setTextinputWidth(result ? result.toString() : "");
}} />
</SettingsModalCardItem>
<SettingsModalCardItem title="Height">
<TextInput
disabled={!resolutionEnabled || isSaving}
value={textinputHeight}
onChange={value => validateTextInputNumber(value) && setTextinputHeight(value)}
onBlur={e => {
const result = validateNumberInput(e.target.value);
setHeight(result);
setTextinputHeight(result ? result.toString() : "");
}} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardItemFramerate =
<SettingsModalCardItem>
<TextInput
disabled={!framerateEnabled || isSaving}
value={textinputFramerate}
onChange={value => validateTextInputNumber(value) && setTextinputFramerate(value)}
onBlur={e => {
const result = validateNumberInput(e.target.value);
setFramerate(result);
setTextinputFramerate(result ? result.toString() : "");
}} />
</SettingsModalCardItem>;
const settingsCardFramerateProps: React.ComponentProps<typeof SettingsModalCard> = {
title: "Framerate",
switchEnabled: true,
switchProps: {
checked: framerateEnabled ?? false,
disabled: isSaving,
onChange: status => setFramerateEnabled(status)
}
};
const settingsCardFramerate =
<SettingsModalCard
{...settingsCardFramerateProps}
flex={0.25}
>
{settingsCardItemFramerate}
</SettingsModalCard>;
const settingsCardFramerateSimple =
<SettingsModalCard
{...settingsCardFramerateProps}
>
{settingsCardItemFramerate}
</SettingsModalCard>;
const settingsCardKeyframeInterval =
<SettingsModalCard
title="Keyframe Interval (ms)"
flex={0.25}
switchEnabled
switchProps={{
checked: keyframeIntervalEnabled ?? false,
disabled: isSaving,
onChange: status => setKeyframeIntervalEnabled(status)
}}>
<SettingsModalCardItem>
<TextInput
disabled={!keyframeIntervalEnabled || isSaving}
value={textinputKeyframeInterval}
onChange={value => validateTextInputNumber(value) && setTextinputKeyframeInterval(value)}
onBlur={e => {
const result = validateNumberInput(e.target.value);
setKeyframeInterval(result);
setTextinputKeyframeInterval(result ? result.toString() : "");
}} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardVideoBitrate =
<SettingsModalCard
title="Video Bitrate"
flex={0.4}
switchEnabled
switchProps={{
checked: videoBitrateEnabled ?? false,
disabled: isSaving,
onChange: status => setVideoBitrateEnabled(status)
}}>
<SettingsModalCardItem title="Kb/s">
<div style={{ paddingTop: "0.3em", paddingRight: "0.4em", paddingLeft: "0.4em", boxSizing: "border-box" }}>
<Slider
disabled={!videoBitrateEnabled || isSaving}
onValueChange={value => setVideoBitrate(value)}
initialValue={videoBitrate || 500}
minValue={500}
maxValue={10000}
markers={[500, 10000]}
onValueRender={value => `${value.toFixed(0)}kb/s`} />
</div>
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardAudioProps: React.ComponentProps<typeof SettingsModalCard> = {
title: "Audio Settings"
};
const settingsCardItemAudio =
<SettingsModalCardItem >
<Button
color={Button.Colors.PRIMARY}
size={Button.Sizes.SMALL}
onClick={() => {
if (screenshareAudioStore)
openModalLazy(async () => {
return props_ =>
<MicrophoneSettingsModal
author={props.author}
contributors={props.contributors}
title="Screenshare Audio Settings"
onDone={onAudioDone}
microphoneStore={screenshareAudioStore}
{...props_} />;
});
}}
children={"Open"} />
</SettingsModalCardItem>;
const settingsCardAudio =
<SettingsModalCard
{...settingsCardAudioProps}
flex={0.2}>
{settingsCardItemAudio}
</SettingsModalCard>;
const settingsCardAudioSimple =
<SettingsModalCard
{...settingsCardAudioProps}>
{settingsCardItemAudio}
</SettingsModalCard>;
const settingsCardVideoCodec =
<SettingsModalCard
title="Video Codec"
flex={0.4}
switchEnabled
switchProps={{
checked: videoCodecEnabled ?? false,
disabled: isSaving,
onChange: status => setVideoCodecEnabled(status)
}}>
<SettingsModalCardItem>
<Select
isDisabled={!videoCodecEnabled || isSaving}
isSelected={value => value === videoCodec}
options={videoCodecs.map(codecCapabilities => ({ label: codecCapabilities.codec, value: codecCapabilities.codec }))}
select={value => setVideoCodec(value)}
serialize={() => ""} />
</SettingsModalCardItem>
</SettingsModalCard>;
const settingsCardHdr =
<SettingsModalCard
title="Hdr"
flex={0.1}
switchEnabled
switchProps={{
checked: hdrEnabled ?? false,
disabled: isSaving,
onChange: status => setHdrEnabled(status)
}} />;
const settingsCardProfiles =
<SettingsModalProfilesCard flex={0.5} onSaveStateChanged={state => setIsSaving(state)} profileableStore={screenshareStore} />;
const simpleToggle =
<Flex style={{ justifyContent: "center", alignItems: "center", gap: "0.6em" }}>
<Forms.FormTitle style={{ margin: 0 }} tag="h5">Simple</Forms.FormTitle>
<Switch checked={simpleMode ?? false} disabled={isSaving} onChange={checked => setSimpleMode(checked)} />
</Flex>;
return (
<SettingsModal
size={simpleMode ? ModalSize.DYNAMIC : ModalSize.LARGE}
title="Screenshare Settings"
closeButtonName="Apply"
footerContent={
<Flex style={{ justifyContent: "center", alignItems: "center", marginLeft: "auto" }}>
{simpleToggle}
</Flex>
}
{...props}
onDone={() => {
props.onClose();
props.onDone && props.onDone();
}}
>
{simpleMode
? <div style={{ width: "55em" }}>
<SettingsModalCardRow>
{settingsCardResolutionSimple}
{settingsCardFramerateSimple}
{settingsCardVideoBitrateSimple}
{screenshareAudioStore && settingsCardAudioSimple}
</SettingsModalCardRow>
</div>
: <>
<SettingsModalCardRow>
{settingsCardResolution}
{settingsCardFramerate}
{settingsCardKeyframeInterval}
</SettingsModalCardRow>
<SettingsModalCardRow>
{settingsCardVideoBitrate}
{settingsCardVideoCodec}
{screenshareAudioStore && settingsCardAudio}
</SettingsModalCardRow>
<SettingsModalCardRow>
{settingsCardHdr}
{settingsCardProfiles}
</SettingsModalCardRow>
</>
}
</SettingsModal>
);
};

View file

@ -1,21 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./AudioSourceSelect";
export * from "./OpenScreenshareSettingsButton";
export * from "./ScreenshareSettingsModal";

View file

@ -1,71 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { addSettingsPanelButton, Emitter, removeSettingsPanelButton, ScreenshareSettingsIcon } from "../philsPluginLibrary";
import { openScreenshareModal } from "./modals";
import { ScreenshareAudioPatcher, ScreensharePatcher } from "./patchers";
import { replacedScreenshareModalComponent } from "./patches";
import { initScreenshareAudioStore, initScreenshareStore } from "./stores";
const settings = definePluginSettings({
hideDefaultSettings: {
type: OptionType.BOOLEAN,
description: "Hide Discord screen sharing settings",
default: true,
}
});
export default definePlugin({
name: "BetterScreenshare",
description: "This plugin allows you to further customize your screen sharing.",
authors: [Devs.philhk],
dependencies: ["PhilsPluginLibrary"],
settings,
patches: [
{
find: "Messages.SCREENSHARE_RELAUNCH",
replacement: {
match: /(function .{1,2}\(.{1,2}\){)(.{1,40}(?=selectGuild).+?(?:]}\)}\)))(})/,
replace: "$1return $self.replacedScreenshareModalComponent(function(){$2}, this, arguments)$3"
}
}
],
replacedScreenshareModalComponent: replacedScreenshareModalComponent,
start(): void {
initScreenshareStore();
initScreenshareAudioStore();
this.screensharePatcher = new ScreensharePatcher().patch();
this.screenshareAudioPatcher = new ScreenshareAudioPatcher().patch();
addSettingsPanelButton({
name: "BetterScreenshare",
icon: ScreenshareSettingsIcon,
tooltipText: "Screenshare Settings",
onClick: openScreenshareModal
});
},
stop() {
this.screensharePatcher?.unpatch();
this.screenshareAudioPatcher?.unpatch();
Emitter.removeAllListeners("BetterScreenshare");
removeSettingsPanelButton("BetterScreenshare");
}
});

View file

@ -1,22 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Logger } from "@utils/Logger";
export const logger = new Logger("BetterScreenshare");

View file

@ -1,54 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Devs } from "@utils/constants";
import { openModalLazy } from "@utils/modal";
import Plugin from "..";
import { ScreenshareSettingsModal } from "../components";
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 =>
<ScreenshareSettingsModal
onAudioDone={onScreenshareAudioModalDone}
onDone={onScreenshareModalDone}
screenshareStore={screenshareStore}
screenshareAudioStore={screenshareAudioStore}
author={Devs.philhk}
{...props} />;
});

View file

@ -1,20 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./screenshare";
export * from "./screenshareAudio";

View file

@ -1,98 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { UserStore } from "@webpack/common";
import { Emitter, MediaEngineStore, Patcher, types } from "../../philsPluginLibrary";
import { patchConnectionVideoSetDesktopSourceWithOptions, patchConnectionVideoTransportOptions } from "../../philsPluginLibrary/patches/video";
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,
"BetterScreenshare"
);
return this;
}
public unpatch(): this {
return this._unpatch();
}
}

View file

@ -1,84 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { UserStore } from "@webpack/common";
import { Emitter, MediaEngineStore, patchConnectionAudioTransportOptions, Patcher, types } from "../../philsPluginLibrary";
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,
"BetterScreenshare"
);
return this;
}
public unpatch(): this {
return this._unpatch();
}
}

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./screenshareModal";

View file

@ -1,97 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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 { screenshareStore } from "../stores";
const ReplacedStreamSettings = () => {
const { use } = screenshareStore;
const { audioSourceEnabled, setAudioSourceEnabled } = use();
const cardProps = { style: { border: "1px solid var(--primary-800)" } };
return (
<div style={{ margin: "1em", display: "flex", flexDirection: "column", gap: "1em" }}>
<SettingsModalCard cardProps={cardProps} title="Stream Settings">
<SettingsModalCardItem>
<Flex flexDirection="column">
<OpenScreenshareSettingsButton title="Advanced Settings" />
</Flex>
</SettingsModalCardItem>
</SettingsModalCard>
<SettingsModalCard
cardProps={cardProps}
switchEnabled
switchProps={{
checked: audioSourceEnabled ?? false,
onChange: status => setAudioSourceEnabled(status)
}}
title="Audio Source">
<SettingsModalCardItem>
<AudioSourceSelect isDisabled={!audioSourceEnabled} />
</SettingsModalCardItem>
</SettingsModalCard>
</div>
);
};
export function replacedScreenshareModalSettingsContentType(oldType: (...args: any[]) => any, thisContext: any, functionArguments: any) {
const { hideDefaultSettings } = Settings.plugins.BetterScreenshare;
const oldTypeResult = Reflect.apply(oldType, thisContext, functionArguments);
if (hideDefaultSettings)
oldTypeResult.props.children = oldTypeResult.props.children.filter(c => !c?.props?.selectedFPS);
oldTypeResult.props.children.push(<ReplacedStreamSettings />);
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;
}

View file

@ -1,20 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./screenshareAudioStore";
export * from "./screenshareStore";

View file

@ -1,40 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {
defaultMicrophoneProfiles as defaultScreenshareAudioProfiles,
MicrophoneProfile as ScreenshareAudioProfile,
MicrophoneStore as ScreenshareAudioStore,
microphoneStoreDefault as screenshareAudioStoreDefault
} from "../../betterMicrophone.desktop/stores";
import { createPluginStore, ProfilableStore, profileable } from "../../philsPluginLibrary";
export let screenshareAudioStore: ProfilableStore<ScreenshareAudioStore, ScreenshareAudioProfile>;
export const initScreenshareAudioStore = () =>
screenshareAudioStore = createPluginStore(
"BetterScreenshare",
"ScreenshareAudioStore",
profileable(
screenshareAudioStoreDefault,
{ name: "" },
Object.values(defaultScreenshareAudioProfiles)
)
);
export { defaultScreenshareAudioProfiles, ScreenshareAudioProfile, ScreenshareAudioStore, screenshareAudioStoreDefault };

View file

@ -1,121 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { createPluginStore, ProfilableInitializer, ProfilableStore, profileable, ProfileableProfile } from "../../philsPluginLibrary";
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<string, ScreenshareProfile & ProfileableProfile>;
export const screenshareStoreDefault: ProfilableInitializer<ScreenshareStore, ScreenshareProfile> = (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<ScreenshareStore, ScreenshareProfile>;
export const initScreenshareStore = () =>
screenshareStore = createPluginStore(
"BetterScreenshare",
"ScreenshareStore",
profileable(
screenshareStoreDefault,
{ name: "" },
Object.values(defaultScreenshareProfiles)
)
);

View file

@ -1,57 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<React.ComponentProps<types.UserSummaryItem>> {
authors: PluginAuthor[];
}
export const AuthorUserSummaryItem = (props: AuthorUserSummaryItemProps) => {
const [users, setUsers] = useState<Partial<User>[]>([]);
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 (
<UserSummaryItem
users={users as User[]}
guildId={undefined}
renderIcon={false}
showDefaultAvatarsForNullUsers
showUserPopout
{...props}
/>
);
};

View file

@ -1,53 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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 (
<Flex style={{ gap: "0.7em" }}>
{author &&
<Flex style={{ justifyContent: "center", alignItems: "center", gap: "0.5em" }}>
<Text variant="text-sm/normal" style={{ color: "var(--text-muted)" }}>
Author: <a onClick={() => author.github && openURL(author.github)}>{`${author.name}`}</a>
</Text>
<AuthorUserSummaryItem authors={[author]} />
</Flex>
}
{(contributors && contributors.length > 0) &&
<Flex style={{ justifyContent: "center", alignItems: "center", gap: "0.5em" }}>
<Text variant="text-sm/normal" style={{ color: "var(--text-muted)" }}>
Contributors:
</Text>
<AuthorUserSummaryItem authors={contributors} />
</Flex>
}
</Flex>
);
};

View file

@ -1,37 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Button } from "@webpack/common";
import React from "react";
import { IconTooltipButton } from ".";
export const CopyButton = (props: typeof Button["defaultProps"]) => {
return (
<IconTooltipButton
color={Button.Colors.PRIMARY}
tooltipText="Copy Profile"
icon={
<svg width="18" height="18" viewBox="0 0 24 24">
<path d="M7.024 3.75c0-.966.784-1.75 1.75-1.75H20.25c.966 0 1.75.784 1.75 1.75v11.498a1.75 1.75 0 0 1-1.75 1.75H8.774a1.75 1.75 0 0 1-1.75-1.75Zm1.75-.25a.25.25 0 0 0-.25.25v11.498c0 .139.112.25.25.25H20.25a.25.25 0 0 0 .25-.25V3.75a.25.25 0 0 0-.25-.25Z" fill="currentColor"></path>
<path d="M1.995 10.749a1.75 1.75 0 0 1 1.75-1.751H5.25a.75.75 0 1 1 0 1.5H3.745a.25.25 0 0 0-.25.25L3.5 20.25c0 .138.111.25.25.25h9.5a.25.25 0 0 0 .25-.25v-1.51a.75.75 0 1 1 1.5 0v1.51A1.75 1.75 0 0 1 13.25 22h-9.5A1.75 1.75 0 0 1 2 20.25l-.005-9.501Z" fill="currentColor"></path>
</svg>
}
{...props} />
);
};

View file

@ -1,39 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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 (
<IconTooltipButton
color={Button.Colors.RED}
tooltipText="Delete Profile"
icon={
<svg width="18" height="18" viewBox="0 0 24 24">
<path d="M16 1.75V3h5.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H8V1.75C8 .784 8.784 0 9.75 0h4.5C15.216 0 16 .784 16 1.75Zm-6.5 0V3h5V1.75a.25.25 0 0 0-.25-.25h-4.5a.25.25 0 0 0-.25.25ZM4.997 6.178a.75.75 0 1 0-1.493.144L4.916 20.92a1.75 1.75 0 0 0 1.742 1.58h10.684a1.75 1.75 0 0 0 1.742-1.581l1.413-14.597a.75.75 0 0 0-1.494-.144l-1.412 14.596a.25.25 0 0 1-.249.226H6.658a.25.25 0 0 1-.249-.226L4.997 6.178Z" fill="currentColor"></path>
<path d="M9.206 7.501a.75.75 0 0 1 .793.705l.5 8.5A.75.75 0 1 1 9 16.794l-.5-8.5a.75.75 0 0 1 .705-.793Zm6.293.793A.75.75 0 1 0 14 8.206l-.5 8.5a.75.75 0 0 0 1.498.088l.5-8.5Z" fill="currentColor"></path>
</svg>
}
{...props} />
);
};

View file

@ -1,44 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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 (
<Tooltip text={props.tooltipText}>
{tooltipProps => <Button
size={Button.Sizes.ICON}
{...props as any}
style={{ aspectRatio: 1, maxHeight: "32px", boxSizing: "border-box", ...props.style }}
>
<Flex style={{ justifyContent: "center", alignItems: "center", width: 24, height: 24 }}>
{props.icon}
</Flex>
<span {...tooltipProps} style={{ position: "absolute", top: 0, right: 0, bottom: 0, left: 0 }} />
</Button>}
</Tooltip >
);
};

View file

@ -1,37 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Button } from "@webpack/common";
import React from "react";
import { IconTooltipButton } from ".";
export const NewButton = (props: typeof Button["defaultProps"]) => {
return (
<IconTooltipButton
color={Button.Colors.PRIMARY}
tooltipText="New Profile"
icon={
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
}
{...props} />
);
};

View file

@ -1,38 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Button } from "@webpack/common";
import React from "react";
import { IconTooltipButton } from ".";
export const SaveButton = (props: typeof Button["defaultProps"]) => {
return (
<IconTooltipButton
color={Button.Colors.GREEN}
tooltipText="Save Profile"
icon={
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" >
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
<polyline points="17 21 17 13 7 13 7 21"></polyline>
<polyline points="7 3 7 8 15 8"></polyline>
</svg>
}
{...props} />
);
};

View file

@ -1,23 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./CopyButton";
export * from "./DeleteButton";
export * from "./IconTooltipButton";
export * from "./NewButton";
export * from "./SaveButton";

View file

@ -1,23 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./AuthorSummaryItem";
export * from "./buttons";
export * from "./ContributorAuthorSummary";
export * from "./settingsModal";
export * from "./settingsPanel";

View file

@ -1,77 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<typeof ModalRoot> {
title?: string;
onClose: () => void;
onDone?: () => void;
footerContent?: JSX.Element;
closeButtonName?: string;
author?: Author,
contributors?: Contributor[];
}
export const SettingsModal = (props: SettingsModalProps) => {
const doneButton =
<Button
size={Button.Sizes.SMALL}
color={Button.Colors.BRAND}
onClick={props.onDone}
>
{props.closeButtonName ?? "Done"}
</Button>;
return (
<ModalRoot {...props}>
<ModalHeader separator={false}>
{props.title && <Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>{props.title}</Text>}
<div style={{ marginLeft: "auto" }}>
<ModalCloseButton onClick={props.onClose} />
</div>
</ModalHeader>
<ModalContent style={{ marginBottom: "1em", display: "flex", flexDirection: "column", gap: "1em" }}>
{props.children}
</ModalContent>
<ModalFooter>
<Flex style={{ width: "100%" }}>
<div style={{ flex: 1, display: "flex" }}>
{(props.author || props.contributors && props.contributors.length > 0) &&
<Flex style={{ justifyContent: "flex-start", alignItems: "center", flex: 1 }}>
<ContributorAuthorSummary
author={props.author}
contributors={props.contributors} />
</Flex>
}
{props.footerContent}
</div>
<div style={{ marginLeft: "auto" }}>{doneButton}</div>
</Flex>
</ModalFooter>
</ModalRoot >
);
};

View file

@ -1,83 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Switch } from "@components/Switch";
import { Card, Forms } from "@webpack/common";
import React from "react";
export interface SettingsModalItemProps extends Pick<React.ComponentProps<"div">,
| "children"> {
title?: string;
switchEnabled?: boolean;
switchProps?: React.ComponentProps<typeof Switch>;
flex?: number;
cardProps?: React.ComponentProps<typeof Card>;
}
export const SettingsModalCard = ({ children, title, switchProps, switchEnabled, flex, cardProps }: SettingsModalItemProps) => {
return (
<Card
{...cardProps}
style={{
padding: "1em",
boxSizing: "border-box",
display: "flex",
flexDirection: "column",
flex: flex ?? 1,
...(cardProps?.style ? cardProps.style : {})
}}>
{title && <Forms.FormTitle tag="h5" style={{ margin: 0 }}>{title}</Forms.FormTitle>}
<div style={{
display: "flex",
gap: "1em",
height: "100%",
justifyContent: "center",
alignItems: "center",
paddingTop: "0.6em",
}}>
{children &&
<div style={{
display: "flex",
alignItems: "flex-end",
gap: "1em",
flex: 1
}}>
{children}
</div>
}
{switchEnabled &&
<div style={{
display: "flex",
height: "100%",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
}}>
<Forms.FormTitle tag="h5">Status</Forms.FormTitle>
<Switch
checked={false}
onChange={() => void 0}
disabled={false}
{...switchProps}
/>
</div>
}
</div>
</Card >
);
};

View file

@ -1,39 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Forms } from "@webpack/common";
import React from "react";
export interface SettingsModalCardItemProps extends Pick<React.ComponentProps<"div">,
| "children"> {
title?: string;
}
export const SettingsModalCardItem = ({ children, title }: SettingsModalCardItemProps) => {
return (
<div style={{
display: "flex",
flexDirection: "column",
gap: "0.4em",
width: "100%"
}}>
{title && <Forms.FormTitle tag="h5" style={{ margin: 0 }}>{title}</Forms.FormTitle>}
{children}
</div>
);
};

View file

@ -1,31 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import React from "react";
export interface SettingsModalRowProps extends Pick<React.ComponentProps<"div">,
| "children"
| "style"> {
gap?: string;
}
export const SettingsModalCardRow = ({ children, style, gap }: SettingsModalRowProps) => {
return (
<div style={{ display: "flex", gap: gap ?? "1em", ...style }}>{children}</div>
);
};

View file

@ -1,113 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<T extends PluginSettings = {}> extends React.ComponentProps<typeof SettingsModalCard> {
profileableStore: ProfilableStore<T, any>;
onSaveStateChanged: (isSaving: boolean) => void;
}
export const SettingsModalProfilesCard = <T extends PluginSettings = {},>(props: SettingsModalProfilesCardProps<T>) => {
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<string>("");
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 (
<SettingsModalCard
title="Profile"
{...props}>
<SettingsModalCardItem>
<Flex style={{ alignItems: "center" }}>
<div style={{ flex: 1 }}>
{isSaving
? <TextInput
style={{ width: "100%" }}
placeholder="Insert name"
value={profileNameInput}
onChange={setProfileNameInput} />
: <Select
isSelected={value => name === value}
options={getProfiles(true).map(profile => ({
label: profile.name,
value: profile.name
}))}
select={value => setCurrentProfile(getProfile(value) || { name: "" })}
serialize={() => ""} />}
</div>
<Flex style={{ gap: "0.8em" }}>
<SaveButton onClick={onSaveProfile} />
<NewButton onClick={onNewProfile} disabled={isSaving} />
<CopyButton onClick={onCopyProfile} disabled={isSaving} />
<DeleteButton onClick={onDeleteProfile} disabled={isSaving || isCurrentProfileADefaultProfile() || !currentProfile.name.length} />
</Flex>
</Flex>
</SettingsModalCardItem>
</SettingsModalCard>
);
};

View file

@ -1,23 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./SettingsModal";
export * from "./SettingsModalCard";
export * from "./SettingsModalCardItem";
export * from "./SettingsModalCardRow";
export * from "./SettingsModalProfilesCard";

View file

@ -1,35 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { React } from "@webpack/common";
import { panelClasses } from "../../discordModules";
export interface SettingsPanelProps {
children: React.ComponentProps<"div">["children"];
}
export const SettingsPanel = ({ children }: SettingsPanelProps) => {
return (
<div
className={panelClasses.container}>
{children}
</div>
);
};

View file

@ -1,40 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { classes } from "@utils/misc";
import { Button } from "@webpack/common";
import React from "react";
import { panelClasses } from "../../../philsPluginLibrary";
export type IconComponent = <T extends { className: string; }>(props: T) => JSX.Element;
export interface SettingsPanelButtonProps extends Partial<React.ComponentProps<typeof Button>> {
icon?: IconComponent;
}
export const SettingsPanelButton = (props: SettingsPanelButtonProps) => {
return (
<Button
size={Button.Sizes.SMALL}
className={classes(panelClasses.button, panelClasses.buttonColor)}
innerClassName={classes(panelClasses.buttonContents)}
wrapperClassName={classes(panelClasses.button)}
children={props.icon && <props.icon className={classes(panelClasses.buttonIcon)} />}
{...props} />
);
};

View file

@ -1,37 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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 (
<div
className={classes(panelClasses.actionButtons)}
style={{ padding: 0 }}
>
{children}
</div>
);
};

View file

@ -1,34 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Tooltip } from "@webpack/common";
import React from "react";
import { SettingsPanelButton, SettingsPanelButtonProps } from "./SettingsPanelButton";
export interface SettingsPanelTooltipButtonProps extends SettingsPanelButtonProps {
tooltipProps: Omit<React.ComponentProps<typeof Tooltip>, "children">;
}
export const SettingsPanelTooltipButton = (props: SettingsPanelTooltipButtonProps) => {
return (
<Tooltip {...props.tooltipProps}>
{tooltipProps => <SettingsPanelButton {...tooltipProps} {...props} />}
</Tooltip>
);
};

View file

@ -1,22 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./SettingsPanel";
export * from "./SettingsPanelButton";
export * from "./SettingsPanelRow";
export * from "./SettingsPanelTooltipButton";

View file

@ -1,25 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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);

View file

@ -1,24 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { LazyComponent } from "@utils/react";
import { findByCode } from "@webpack";
import { types } from "../";
export const UserSummaryItem = LazyComponent<React.ComponentProps<types.UserSummaryItem>>(() => findByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"));

View file

@ -1,22 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./classes";
export * from "./components";
export * from "./modules";
export * from "./stores";

View file

@ -1,25 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { filters, waitFor } from "@webpack";
import * as types from "../types";
export let utils: types.Utils;
waitFor(filters.byProps("getPidFromDesktopSource"), result => utils = result);

View file

@ -1,25 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { waitForStore } from "webpack/common/internal";
import * as types from "../types";
export let MediaEngineStore: types.MediaEngineStore;
waitForStore("MediaEngineStore", store => MediaEngineStore = store);

View file

@ -1,86 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import EventEmitter from "events";
import TypedEmitter from "typed-emitter";
export type TypedEmitterEvents<J extends TypedEmitter<any>> = J extends TypedEmitter<
infer N
>
? N
: never;
export interface EmitterEvent {
emitter: TypedEmitter<any> | EventEmitter;
event: any;
fn: (...args: any[]) => any;
plugin?: string;
}
export class Emitter {
private static events: EmitterEvent[] = [];
public static addListener<
T extends TypedEmitter<any>,
U extends keyof TypedEmitterEvents<T>,
V extends TypedEmitterEvents<T>[U]
>(
emitter: T,
type: keyof Pick<EventEmitter, "on" | "once">,
event: U,
fn: V,
plugin?: string
): () => void;
public static addListener(
emitter: EventEmitter,
type: keyof Pick<EventEmitter, "on" | "once">,
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)
);
}
}

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./emitter";

View file

@ -1,142 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export const ScreenshareSettingsIcon =
(props: React.ComponentProps<"svg">) =>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1000"
height="1000"
viewBox="0 0 1000 1000"
{...props}
>
<defs>
<mask id="screenshareSettingsIconMask">
<path
fill="currentColor"
fillRule="evenodd"
d="M2 4.5c0-1.103.897-2 2-2h16c1.103 0 2 .897 2 2v11c0 1.104-.897 2-2 2h-7v2h4v2H7v-2h4v-2H4c-1.103 0-2-.896-2-2v-11zm11.2 9.838V11.6c-3.336 0-5.532 1.063-7.2 3.4.672-3.338 2.532-6.662 7.2-7.338V5L18 9.662l-4.8 4.675z"
transform="matrix(43.2813 0 0 43.3063 567.187 588.59) translate(-12 -12)"
vectorEffect="non-scaling-stroke"
></path>
<path
fill="#000"
strokeWidth="0"
// Circle
d="M132.5 67.5c0 35.899-29.101 65-65 65-35.898 0-65-29.101-65-65 0-35.898 29.102-65 65-65 35.899 0 65 29.102 65 65z"
transform="translate(229.14 230.807) scale(4.9157) translate(-67.5 -67.5)"
vectorEffect="non-scaling-stroke"
></path>
</mask>
</defs>
<rect width="100%" height="100%" fill="#fff" mask="url(#screenshareSettingsIconMask)"></rect>
<path
fill="currentColor"
fillRule="evenodd"
strokeWidth="0"
// Settings Icon
d="M19.738 10H22v4h-2.261a7.952 7.952 0 01-1.174 2.564L20 18l-2 2-1.435-1.436A7.946 7.946 0 0114 19.738V22h-4v-2.262a7.94 7.94 0 01-2.564-1.174L6 20l-2-2 1.436-1.436A7.911 7.911 0 014.262 14H2v-4h2.262a7.9 7.9 0 011.174-2.564L4 6l2-2 1.436 1.436A7.9 7.9 0 0110 4.262V2h4v2.261a7.967 7.967 0 012.565 1.174L18 3.999l2 2-1.436 1.437A7.93 7.93 0 0119.738 10zM12 16a4 4 0 100-8 4 4 0 000 8z"
transform="translate(229.812 230.81) scale(23.0217) translate(-12 -12)"
vectorEffect="non-scaling-stroke"
></path>
</svg>;
export const CameraSettingsIcon =
(props: React.ComponentProps<"svg">) =>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1000"
height="1000"
viewBox="0 0 1000 1000"
{...props}
>
<defs>
<mask id="m">
<path
fill="currentColor"
fillRule="evenodd"
d="M21.526 8.149a1 1 0 00-.973-.044L18 9.382V7c0-1.103-.897-2-2-2H4c-1.103 0-2 .897-2 2v10c0 1.104.897 2 2 2h12c1.103 0 2-.896 2-2v-2.382l2.553 1.276a.992.992 0 00.973-.043c.294-.183.474-.504.474-.851V9c0-.347-.18-.668-.474-.851z"
transform="translate(586.527 617.666) scale(41.3472) translate(-12 -12)"
vectorEffect="non-scaling-stroke"
></path>
<path
fill="#000"
strokeWidth="0"
// Circle
d="M132.5 67.5c0 35.899-29.101 65-65 65-35.898 0-65-29.101-65-65 0-35.898 29.102-65 65-65 35.899 0 65 29.102 65 65z"
transform="translate(229.14 230.807) scale(4.9157) translate(-67.5 -67.5)"
vectorEffect="non-scaling-stroke"
></path>
</mask>
</defs>
<rect width="100%" height="100%" fill="#fff" mask="url(#m)"></rect>
<path
fill="currentColor"
fillRule="evenodd"
strokeWidth="0"
// Settings Icon
d="M19.738 10H22v4h-2.261a7.952 7.952 0 01-1.174 2.564L20 18l-2 2-1.435-1.436A7.946 7.946 0 0114 19.738V22h-4v-2.262a7.94 7.94 0 01-2.564-1.174L6 20l-2-2 1.436-1.436A7.911 7.911 0 014.262 14H2v-4h2.262a7.9 7.9 0 011.174-2.564L4 6l2-2 1.436 1.436A7.9 7.9 0 0110 4.262V2h4v2.261a7.967 7.967 0 012.565 1.174L18 3.999l2 2-1.436 1.437A7.93 7.93 0 0119.738 10zM12 16a4 4 0 100-8 4 4 0 000 8z"
transform="translate(229.812 230.81) scale(23.0217) translate(-12 -12)"
vectorEffect="non-scaling-stroke"
></path>
</svg>;
export const MicrophoneSettingsIcon =
(props: React.ComponentProps<"svg">) =>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1000"
height="1000"
viewBox="0 0 1000 1000"
{...props}
>
<defs>
<mask id="microphoneSettingsIcon">
<path
fill="currentColor"
fillRule="evenodd"
d="M14.99 11c0 1.66-1.33 3-2.99 3-1.66 0-3-1.34-3-3V5c0-1.66 1.34-3 3-3s3 1.34 3 3l-.01 6zM12 16.1c2.76 0 5.3-2.1 5.3-5.1H19c0 3.42-2.72 6.24-6 6.72V21h-2v-3.28c-3.28-.49-6-3.31-6-6.72h1.7c0 3 2.54 5.1 5.3 5.1zM12 4c-.8 0-1 .667-1 1v6c0 .333.2 1 1 1s1-.667 1-1V5c0-.333-.2-1-1-1z"
transform="translate(689.616 574.556) scale(48.6222) translate(0 -.417) scale(.8333) translate(-12 -11.5)"
></path>
<path
fill="currentColor"
fillRule="evenodd"
d="M14.99 11c0 1.66-1.33 3-2.99 3-1.66 0-3-1.34-3-3V5c0-1.66 1.34-3 3-3s3 1.34 3 3l-.01 6zM12 16.1c2.76 0 5.3-2.1 5.3-5.1H19c0 3.42-2.72 6.24-6 6.72V22h-2v-4.28c-3.28-.49-6-3.31-6-6.72h1.7c0 3 2.54 5.1 5.3 5.1z"
transform="translate(689.616 574.556) scale(48.6222) scale(.8333) translate(-12 -12)"
></path>
<path
fill="#000"
strokeWidth="0"
// Circle
d="M132.5 67.5c0 35.899-29.101 65-65 65-35.898 0-65-29.101-65-65 0-35.898 29.102-65 65-65 35.899 0 65 29.102 65 65z"
transform="translate(229.14 230.807) scale(4.9157) translate(-67.5 -67.5)"
vectorEffect="non-scaling-stroke"
></path>
</mask>
</defs>
<rect width="100%" height="100%" fill="#fff" mask="url(#microphoneSettingsIcon)"></rect>
<path
fill="currentColor"
fillRule="evenodd"
strokeWidth="0"
// Settings Icon
d="M19.738 10H22v4h-2.261a7.952 7.952 0 01-1.174 2.564L20 18l-2 2-1.435-1.436A7.946 7.946 0 0114 19.738V22h-4v-2.262a7.94 7.94 0 01-2.564-1.174L6 20l-2-2 1.436-1.436A7.911 7.911 0 014.262 14H2v-4h2.262a7.9 7.9 0 011.174-2.564L4 6l2-2 1.436 1.436A7.9 7.9 0 0110 4.262V2h4v2.261a7.967 7.967 0 012.565 1.174L18 3.999l2 2-1.436 1.437A7.93 7.93 0 0119.738 10zM12 16a4 4 0 100-8 4 4 0 000 8z"
transform="translate(229.812 230.81) scale(23.0217) translate(-12 -12)"
vectorEffect="non-scaling-stroke"
></path>
</svg>;

View file

@ -1,46 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
import { replacedUserPanelComponent } from "./patches";
export default definePlugin({
name: "PhilsPluginLibrary",
description: "A library for phil's plugins",
authors: [Devs.philhk],
patches: [{
find: "Messages.ACCOUNT_A11Y_LABEL",
replacement: {
match: /(?<=function)( .{0,8}(?={).)(.{0,1000}isFullscreenInContext\(\).+?\)]}\))(})/,
replace: "$1return $self.replacedUserPanelComponent(function(){$2}, this, arguments)$3"
}
}],
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";

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./patcher";

View file

@ -1,29 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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;
}
}

View file

@ -1,88 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<MicrophoneStore, MicrophoneProfile>["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<MicrophoneStore, MicrophoneProfile>["get"],
logger?: Logger
) {
const oldSetTransportOptions = connection.conn.setTransportOptions;
connection.conn.setTransportOptions = function (this: any, options: Record<string, any>) {
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 };
}

View file

@ -1,21 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./audio";
export * from "./userPanel";
export * from "./video";

View file

@ -1,107 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<React.DispatchWithoutAction>();
export const settingsPanelButtons: PanelButton[] = new Proxy<PanelButton[]>([], {
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
? <SettingsPanelTooltipButton tooltipProps={{ text: tooltipText }} icon={icon} onClick={onClick} />
: <SettingsPanelButton icon={icon} onClick={onClick} />
);
groupedButtons.push(splicedButtons);
}
return groupedButtons;
};
return rawPanelButtons.length > 0
? <SettingsPanel>
{...convertRawPanelButtons(rawPanelButtons).map(value => <SettingsPanelRow children={value} />)}
</SettingsPanel>
: <>
</>;
};
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,
<ButtonsSettingsPanel />
);
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));
}

View file

@ -1,253 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<ScreenshareStore, ScreenshareProfile>["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<ScreenshareStore, ScreenshareProfile>["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<ScreenshareStore, ScreenshareProfile>["get"]) {
const { currentProfile } = get();
const {
hdrEnabled,
} = currentProfile;
return {
...(hdrEnabled
? {
hdrCaptureMode: "always"
}
: {}
),
};
}
export function patchConnectionVideoSetDesktopSourceWithOptions(
connection: types.Connection,
get: ProfilableStore<ScreenshareStore, ScreenshareProfile>["get"],
logger?: Logger
) {
const oldSetDesktopSourceWithOptions = connection.conn.setDesktopSourceWithOptions;
connection.conn.setDesktopSourceWithOptions = function (this: any, options: Record<string, any>) {
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<ScreenshareStore, ScreenshareProfile>["get"],
logger?: Logger
) {
const oldSetTransportOptions = connection.conn.setTransportOptions;
connection.conn.setTransportOptions = function (this: any, options: Record<string, any>) {
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,
};
}

View file

@ -1,20 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./profileable";
export * from "./store";

View file

@ -1,85 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { PluginInitializer, PluginSettings, PluginStore } from "./store";
export interface ProfileableProfile {
name: string;
}
export interface ProfileableSettings<T extends PluginSettings = {}, B extends ProfileableProfile & T = T & ProfileableProfile> {
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<T & ProfileableSettings<S>>;
export type ProfilableMiddleware<
T extends PluginSettings = {},
S extends PluginSettings = {},
B = T & ProfileableSettings<S>
> = PluginInitializer<T & ProfileableSettings<S>, B>;
export type ProfilableInitializer<
T extends PluginSettings = {},
S extends PluginSettings = {}
> = ProfilableMiddleware<T, S, T & Partial<ProfileableSettings<S>>>;
export function profileable<
T extends PluginSettings = {},
S extends PluginSettings = {}
>(f: ProfilableInitializer<T, S>, defaultProfile: ProfileableProfile & S, defaultProfiles: (ProfileableProfile & S)[] = []): ProfilableMiddleware<T, S> {
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)
});
}

View file

@ -1,102 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Settings, useSettings } from "@api/Settings";
export type PluginSettings = {
[key: string]: any;
};
export type PluginUse<Z extends PluginSettings> = () => Z;
export type PluginGet<Z extends PluginSettings> = () => Z;
export type PluginSet<Z extends PluginSettings> = (s: Z | ((settings: Z) => Z | undefined)) => Z;
export type PluginInitializer<Z extends PluginSettings, T = Z> = (set: PluginSet<Z>, get: PluginGet<Z>) => T;
export interface PluginStore<Z extends PluginSettings> {
use: PluginUse<Z>,
get: PluginGet<Z>,
set: PluginSet<Z>;
}
function createObjectProxy<T extends object>(obj1: T, onUpdate: (updatedObject: T) => void): T {
const handler: ProxyHandler<T> = {
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<Z extends PluginSettings = {}>(pluginName: string, storeName: string, f: PluginInitializer<Z>): PluginStore<Z> {
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<Z> = () => {
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<Z> = (s: ((settings: Z) => Z | undefined) | Z) =>
(typeof s === "function" ? s(get()) : s) || get();
const use: PluginUse<Z> = () => { 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 object, 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
};
}

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./styles";

View file

@ -1,25 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export const Styles = {
infoCard: {
padding: "1em",
width: "100%",
boxSizing: "border-box"
},
} as const satisfies Record<string, React.CSSProperties>;

View file

@ -1,46 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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> = T extends Function
? T
: T extends Array<infer InferredArrayMember>
? DeepPartialArray<InferredArrayMember>
: T extends object
? DeepPartialObject<T>
: T | undefined;
interface DeepPartialArray<T> extends Array<DeepPartial<T>> { }
type DeepPartialObject<T> = {
[key in keyof T]?: DeepPartial<T[key]>;
};

View file

@ -1,31 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<string, PluginAuthor & { github?: string; }>,
README?: string;
}

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./panelClasses";

View file

@ -1,53 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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;
}

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./userSummaryItem";

View file

@ -1,35 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<UserSummaryItemProps>;

View file

@ -1,22 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./classes";
export * from "./components";
export * from "./modules";
export * from "./stores";

View file

@ -1,56 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export interface Conn {
destroy: (...args: any[]) => any;
setTransportOptions: (options: Record<string, any>) => 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;
}

View file

@ -1,387 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 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<ConnectionEvents> &
Connection__ &
Connection_ & {
streamUserId: string,
goLiveSourceIdentifier?: string;
emitter: TypedEmitter<ConnectionEvents>;
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<any>;
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<ConnectionEvents>;
}
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<Resolution> & {
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<Resolution> {
fps?: number;
useVideoHook?: boolean;
useGraphicsCapture?: boolean;
useQuartzCapturer?: boolean;
allowScreenCaptureKit?: boolean;
hdrCaptureMode?: HdrCaptureMode[keyof HdrCaptureMode];
}

View file

@ -1,36 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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;
}

View file

@ -1,24 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./conn";
export * from "./connection";
export * from "./framerateReducer";
export * from "./mediaEngine";
export * from "./utils";
export * from "./videoQualityManager";

View file

@ -1,148 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 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<MediaEngineEvents> &
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<MediaEngineEvents>;
videoInputDeviceId: string;
lastVoiceActivity: number;
audioSubsystem: string;
audioLayer: string;
loopback: boolean;
deviceChangeGeneration: number;
consecutiveWatchdogFailures: number;
codecSurvey?: any;
connections: Set<Connection>;
__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<WindowPreview[]>;
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<string>;
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<MediaEngineEvents>;
}
export interface CodecCapabilities {
codec: string;
decode: boolean;
encode: boolean;
}
export interface WindowPreview {
id: string;
url: string;
name: string;
}

View file

@ -1,103 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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[];
}

View file

@ -1,81 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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<Bitrate, "target">;
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;
}

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./mediaEngineStore";

View file

@ -1,119 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { 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;
}

View file

@ -1,21 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./common";
export * from "./constants";
export * from "./discordModules";

View file

@ -1,19 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "./utils";

View file

@ -1,27 +0,0 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { UserStore } from "@webpack/common";
import { User } from "discord-types/general";
export const createDummyUser = (props: Partial<User>) => 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]));