mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-09 22:53:02 -04:00
Remove Stereo
This commit is contained in:
parent
9d0550bf79
commit
01b490a3af
83 changed files with 0 additions and 5217 deletions
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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";
|
|
@ -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");
|
||||
}
|
||||
});
|
|
@ -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");
|
|
@ -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} />;
|
||||
});
|
|
@ -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";
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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";
|
|
@ -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)
|
||||
)
|
||||
);
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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";
|
|
@ -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");
|
||||
}
|
||||
});
|
|
@ -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");
|
|
@ -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} />;
|
||||
});
|
|
@ -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";
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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";
|
|
@ -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;
|
||||
}
|
|
@ -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";
|
|
@ -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 };
|
|
@ -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)
|
||||
)
|
||||
);
|
|
@ -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}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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} />
|
||||
);
|
||||
};
|
|
@ -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} />
|
||||
);
|
||||
};
|
||||
|
|
@ -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 >
|
||||
);
|
||||
};
|
|
@ -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} />
|
||||
);
|
||||
};
|
|
@ -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} />
|
||||
);
|
||||
};
|
|
@ -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";
|
|
@ -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";
|
|
@ -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 >
|
||||
);
|
||||
};
|
|
@ -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 >
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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";
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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} />
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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";
|
|
@ -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);
|
|
@ -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"));
|
|
@ -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";
|
|
@ -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);
|
|
@ -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);
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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";
|
|
@ -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>;
|
|
@ -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";
|
|
@ -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";
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 };
|
||||
}
|
|
@ -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";
|
|
@ -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));
|
||||
}
|
|
@ -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,
|
||||
};
|
||||
}
|
|
@ -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";
|
|
@ -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)
|
||||
});
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
|
@ -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";
|
|
@ -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>;
|
|
@ -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]>;
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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";
|
|
@ -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;
|
||||
}
|
|
@ -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";
|
|
@ -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>;
|
|
@ -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";
|
|
@ -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;
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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";
|
|
@ -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;
|
||||
}
|
|
@ -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[];
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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";
|
|
@ -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;
|
||||
}
|
|
@ -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";
|
|
@ -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";
|
|
@ -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]));
|
Loading…
Add table
Add a link
Reference in a new issue