mirror of
https://github.com/RobinRMC/VencordPlus.git
synced 2025-05-10 17:35:39 +02:00
Update BetterClips, BetterMicrophone, BetterScreenshare, FakeDeafen & PhilsPluginLibrary
This commit is contained in:
parent
7c861c620b
commit
b969ad2bd1
8 changed files with 178 additions and 188 deletions
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
|
@ -4974,7 +4974,7 @@ snapshots:
|
|||
|
||||
typed-emitter@2.1.0:
|
||||
optionalDependencies:
|
||||
rxjs: 7.8.1
|
||||
rxjs: 7.8.2
|
||||
|
||||
typescript-eslint@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2):
|
||||
dependencies:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
|
@ -20,6 +20,12 @@ const settings = definePluginSettings({
|
|||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
moreClipDurations: {
|
||||
description: "Adds more clip durations",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -32,7 +38,7 @@ export default definePlugin({
|
|||
patches: [
|
||||
{
|
||||
predicate: () => settings.store.clipAllStreams,
|
||||
find: "isViewerClippingAllowedForUser",
|
||||
find: "}isViewerClippingAllowedForUser",
|
||||
replacement: {
|
||||
match: /isViewerClippingAllowedForUser\(\w+\){/,
|
||||
replace: "$&return true;"
|
||||
|
@ -40,11 +46,27 @@ export default definePlugin({
|
|||
},
|
||||
{
|
||||
predicate: () => settings.store.clipAllParticipants,
|
||||
find: "isVoiceRecordingAllowedForUser",
|
||||
find: "}isVoiceRecordingAllowedForUser",
|
||||
replacement: {
|
||||
match: /isVoiceRecordingAllowedForUser\(\w+\){/,
|
||||
replace: "$&return true;"
|
||||
}
|
||||
},
|
||||
{
|
||||
predicate: () => settings.store.moreClipDurations,
|
||||
find: "MINUTES_2=",
|
||||
replacement: {
|
||||
match: /((\i)\[(\i)\.MINUTES_2=2\*(\i)\.(\i)\.(\i)\.MINUTE\]="MINUTES_2",)/,
|
||||
replace: "$&$2[$3.MINUTES_3=3*$4.$5.$6.MINUTE]=\"MINUTES_3\",$2[$3.MINUTES_5=5*$4.$5.$6.MINUTE]=\"MINUTES_5\","
|
||||
}
|
||||
},
|
||||
{
|
||||
predicate: () => settings.store.moreClipDurations,
|
||||
find: "count:2})",
|
||||
replacement: {
|
||||
match: /\{value:(\i)\.(\i)\.MINUTES_2,label:(\i)\.(\i)\.formatToPlainString\((\i)\.(\i)\.(\w+),\{count:2\}\)\}/,
|
||||
replace: "$&,{value:$1.$2.MINUTES_3,label:$3.$4.formatToPlainString($5.$6.$7,{count:3})},{value:$1.$2.MINUTES_5,label:$3.$4.formatToPlainString($5.$6.$7,{count:5})}"
|
||||
}
|
||||
}
|
||||
],
|
||||
description: "Enables extra clipping options for streams"
|
||||
|
|
|
@ -4,35 +4,67 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
|
||||
import { addSettingsPanelButton, Emitter, MicrophoneSettingsIcon, removeSettingsPanelButton } from "../philsPluginLibrary";
|
||||
import { Emitter, MicrophoneSettingsIcon } from "../philsPluginLibrary";
|
||||
import { PluginInfo } from "./constants";
|
||||
import { openMicrophoneSettingsModal } from "./modals";
|
||||
import { MicrophonePatcher } from "./patchers";
|
||||
import { initMicrophoneStore } from "./stores";
|
||||
|
||||
const Button = findComponentByCodeLazy(".NONE,disabled:", ".PANEL_BUTTON");
|
||||
|
||||
function micSettingsButton() {
|
||||
const { hideSettingsIcon } = settings.use(["hideSettingsIcon"]);
|
||||
if (hideSettingsIcon) return null;
|
||||
return (
|
||||
<Button
|
||||
tooltipText="Change screenshare settings"
|
||||
icon={MicrophoneSettingsIcon}
|
||||
role="button"
|
||||
onClick={openMicrophoneSettingsModal}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const settings = definePluginSettings({
|
||||
hideSettingsIcon: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Hide the settings icon",
|
||||
default: true,
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterMicrophone",
|
||||
description: "This plugin allows you to further customize your microphone",
|
||||
description: "This plugin allows you to further customize your microphone.",
|
||||
authors: [Devs.phil],
|
||||
dependencies: ["PhilsPluginLibrary"],
|
||||
patches: [
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /className:\i\.buttons,.{0,50}children:\[/,
|
||||
replace: "$&$self.micSettingsButton(),"
|
||||
}
|
||||
}
|
||||
],
|
||||
settings: settings,
|
||||
start(): void {
|
||||
initMicrophoneStore();
|
||||
|
||||
this.microphonePatcher = new MicrophonePatcher().patch();
|
||||
|
||||
addSettingsPanelButton({ name: PluginInfo.PLUGIN_NAME, icon: MicrophoneSettingsIcon, tooltipText: "Microphone Settings", onClick: openMicrophoneSettingsModal });
|
||||
},
|
||||
stop(): void {
|
||||
this.microphonePatcher?.unpatch();
|
||||
|
||||
Emitter.removeAllListeners(PluginInfo.PLUGIN_NAME);
|
||||
|
||||
removeSettingsPanelButton(PluginInfo.PLUGIN_NAME);
|
||||
},
|
||||
toolboxActions: {
|
||||
"Open Microphone Settings": openMicrophoneSettingsModal
|
||||
},
|
||||
micSettingsButton
|
||||
});
|
||||
|
|
|
@ -7,14 +7,29 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
|
||||
import { addSettingsPanelButton, Emitter, removeSettingsPanelButton, ScreenshareSettingsIcon } from "../philsPluginLibrary";
|
||||
import { Emitter, ScreenshareSettingsIcon } from "../philsPluginLibrary";
|
||||
import { PluginInfo } from "./constants";
|
||||
import { openScreenshareModal } from "./modals";
|
||||
import { ScreenshareAudioPatcher, ScreensharePatcher } from "./patchers";
|
||||
import { GoLivePanelWrapper, replacedSubmitFunction } from "./patches";
|
||||
import { initScreenshareAudioStore, initScreenshareStore } from "./stores";
|
||||
|
||||
const Button = findComponentByCodeLazy(".NONE,disabled:", ".PANEL_BUTTON");
|
||||
|
||||
function screenshareSettingsButton() {
|
||||
|
||||
return (
|
||||
<Button
|
||||
tooltipText="Change screenshare settings"
|
||||
icon={ScreenshareSettingsIcon}
|
||||
role="button"
|
||||
onClick={openScreenshareModal}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterScreenshare",
|
||||
description: "This plugin allows you to further customize your screen sharing",
|
||||
|
@ -34,6 +49,13 @@ export default definePlugin({
|
|||
match: /\(.{0,10}(,{.{0,100}modalContent)/,
|
||||
replace: "($self.GoLivePanelWrapper$1"
|
||||
}
|
||||
},
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /className:\i\.buttons,.{0,50}children:\[/,
|
||||
replace: "$&$self.screenshareSettingsButton(),"
|
||||
}
|
||||
}
|
||||
],
|
||||
settings: definePluginSettings({
|
||||
|
@ -49,23 +71,16 @@ export default definePlugin({
|
|||
this.screensharePatcher = new ScreensharePatcher().patch();
|
||||
this.screenshareAudioPatcher = new ScreenshareAudioPatcher().patch();
|
||||
|
||||
addSettingsPanelButton({
|
||||
name: PluginInfo.PLUGIN_NAME,
|
||||
icon: ScreenshareSettingsIcon,
|
||||
tooltipText: "Screenshare Settings",
|
||||
onClick: openScreenshareModal
|
||||
});
|
||||
},
|
||||
stop(): void {
|
||||
this.screensharePatcher?.unpatch();
|
||||
this.screenshareAudioPatcher?.unpatch();
|
||||
Emitter.removeAllListeners(PluginInfo.PLUGIN_NAME);
|
||||
|
||||
removeSettingsPanelButton(PluginInfo.PLUGIN_NAME);
|
||||
},
|
||||
toolboxActions: {
|
||||
"Open Screenshare Settings": openScreenshareModal
|
||||
},
|
||||
replacedSubmitFunction,
|
||||
GoLivePanelWrapper
|
||||
GoLivePanelWrapper,
|
||||
screenshareSettingsButton
|
||||
});
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
|
||||
import { addSettingsPanelButton, DeafenIcon, removeSettingsPanelButton } from "../philsPluginLibrary";
|
||||
import { toggle } from "@utils/quickCss";
|
||||
|
||||
export let fakeD = false;
|
||||
|
||||
const Button = findComponentByCodeLazy(".NONE,disabled:", ".PANEL_BUTTON");
|
||||
|
||||
function mute() {
|
||||
(document.querySelector('[aria-label="Mute"]') as HTMLElement).click();
|
||||
}
|
||||
|
@ -21,6 +23,78 @@ function deafen() {
|
|||
(document.querySelector('[aria-label="Deafen"]') as HTMLElement).click();
|
||||
}
|
||||
|
||||
function makeDeafenIcon(useFakeState: boolean) {
|
||||
return function DeafenIconComponent() {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
{/* Ear Icon Paths */}
|
||||
<path
|
||||
d="M5.274 5.876c0.396-0.89 0.744-1.934 1.611-2.476 4.086-2.554 8.316 1.441 7.695 5.786-0.359 2.515-3.004 3.861-4.056 5.965-0.902 1.804-4.457 3.494-4.742 0.925"
|
||||
stroke={useFakeState ? "var(--status-danger)" : "currentColor"}
|
||||
strokeOpacity={0.9}
|
||||
strokeWidth={0.8}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M11.478 11.931c2.111-2.239 1.579-7.495-1.909-7.337-2.625 0.119-2.012 3.64-1.402 4.861"
|
||||
stroke={useFakeState ? "var(--status-danger)" : "currentColor"}
|
||||
strokeOpacity={0.9}
|
||||
strokeWidth={0.8}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M7.636 7.755c2.796-0.194 3.747 2.749 1.933 4.563-0.472 0.472-1.386-0.214-1.933 0.06-0.547 0.274-0.957 1.136-1.497 0.507"
|
||||
stroke={useFakeState ? "var(--status-danger)" : "currentColor"}
|
||||
strokeOpacity={0.9}
|
||||
strokeWidth={0.8}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
|
||||
{/* Strike-through (only shown in fake state) */}
|
||||
{useFakeState && (
|
||||
<path
|
||||
d="M19 1L1 19"
|
||||
stroke="var(--status-danger)"
|
||||
strokeWidth="1.7"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
)}
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function fakeDeafenToggleButton() {
|
||||
|
||||
return (
|
||||
<Button
|
||||
tooltipText="Fake Deafen"
|
||||
icon={makeDeafenIcon(fakeD)}
|
||||
role="switch"
|
||||
aria-checked={!fakeD}
|
||||
onClick={() => {
|
||||
fakeD = !fakeD;
|
||||
deafen();
|
||||
setTimeout(deafen, 250);
|
||||
|
||||
if (settings.store.muteUponFakeDeafen)
|
||||
setTimeout(mute, 300);
|
||||
}
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const settings = definePluginSettings({
|
||||
muteUponFakeDeafen: {
|
||||
type: OptionType.BOOLEAN,
|
||||
|
@ -49,6 +123,7 @@ export default definePlugin({
|
|||
description: "You're deafened, but you're not",
|
||||
dependencies: ["PhilsPluginLibrary"],
|
||||
authors: [Devs.desu],
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: "}voiceStateUpdate(",
|
||||
|
@ -56,8 +131,16 @@ export default definePlugin({
|
|||
match: /self_mute:([^,]+),self_deaf:([^,]+),self_video:([^,]+)/,
|
||||
replace: "self_mute:$self.toggle($1, 'mute'),self_deaf:$self.toggle($2, 'deaf'),self_video:$self.toggle($3, 'video')"
|
||||
}
|
||||
},
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /className:\i\.buttons,.{0,50}children:\[/,
|
||||
replace: "$&$self.fakeDeafenToggleButton(),"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
settings,
|
||||
toggle: (au: any, what: string) => {
|
||||
if (fakeD === false)
|
||||
|
@ -69,31 +152,6 @@ export default definePlugin({
|
|||
case "video": return settings.store.cam;
|
||||
}
|
||||
},
|
||||
fakeDeafenToggleButton: ErrorBoundary.wrap(fakeDeafenToggleButton, { noop: true }),
|
||||
|
||||
start() {
|
||||
addSettingsPanelButton({
|
||||
name: "faked", icon: DeafenIcon, tooltipText: "Fake Deafen", onClick: () => {
|
||||
fakeD = !fakeD;
|
||||
deafen();
|
||||
setTimeout(deafen, 250);
|
||||
|
||||
if (settings.store.muteUponFakeDeafen)
|
||||
setTimeout(mute, 300);
|
||||
}
|
||||
});
|
||||
},
|
||||
stop() {
|
||||
removeSettingsPanelButton("faked");
|
||||
},
|
||||
|
||||
toolboxActions: {
|
||||
"Toggle Fake Deafen": () => {
|
||||
fakeD = !fakeD;
|
||||
deafen();
|
||||
setTimeout(deafen, 250);
|
||||
|
||||
if (settings.store.muteUponFakeDeafen)
|
||||
setTimeout(mute, 300);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,21 +7,12 @@
|
|||
import { Devs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import { fakeD } from "../fakeDeafen";
|
||||
import { replacedUserPanelComponent } from "./patches";
|
||||
|
||||
const plugin = definePlugin({
|
||||
name: "PhilsPluginLibrary",
|
||||
description: "A library for phil's plugins",
|
||||
authors: [Devs.phil],
|
||||
patches: [
|
||||
{
|
||||
find: '"--custom-app-panels-height",',
|
||||
replacement: {
|
||||
match: /{}\)}\),/,
|
||||
replace: "{})}),$self.replacedUserPanelComponent(),"
|
||||
}
|
||||
},
|
||||
{
|
||||
find: "Unknown frame rate",
|
||||
replacement: [
|
||||
|
@ -39,40 +30,8 @@ const plugin = definePlugin({
|
|||
});
|
||||
|
||||
|
||||
plugin.replacedUserPanelComponent = replacedUserPanelComponent.bind(plugin);
|
||||
|
||||
|
||||
export default plugin;
|
||||
|
||||
export const DeafenIcon = (props: React.ComponentProps<"svg">) => {
|
||||
const isFakeD = fakeD;
|
||||
|
||||
return (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
{isFakeD ? (
|
||||
<>
|
||||
{
|
||||
<><path d="M6.16204 15.0065C6.10859 15.0022 6.05455 15 6 15H4V12C4 7.588 7.589 4 12 4C13.4809 4 14.8691 4.40439 16.0599 5.10859L17.5102 3.65835C15.9292 2.61064 14.0346 2 12 2C6.486 2 2 6.485 2 12V19.1685L6.16204 15.0065Z" fill="var(--interactive-normal)"></path><path d="M19.725 9.91686C19.9043 10.5813 20 11.2796 20 12V15H18C16.896 15 16 15.896 16 17V20C16 21.104 16.896 22 18 22H20C21.105 22 22 21.104 22 20V12C22 10.7075 21.7536 9.47149 21.3053 8.33658L19.725 9.91686Z" fill="var(--interactive-normal)"></path><path d="M3.20101 23.6243L1.7868 22.2101L21.5858 2.41113L23 3.82535L3.20101 23.6243Z" fill="currentColor"></path></>
|
||||
}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{
|
||||
<><svg width="24" height="24" viewBox="0 0 24 24"><path d="M12 2.00305C6.486 2.00305 2 6.48805 2 12.0031V20.0031C2 21.1071 2.895 22.0031 4 22.0031H6C7.104 22.0031 8 21.1071 8 20.0031V17.0031C8 15.8991 7.104 15.0031 6 15.0031H4V12.0031C4 7.59105 7.589 4.00305 12 4.00305C16.411 4.00305 20 7.59105 20 12.0031V15.0031H18C16.896 15.0031 16 15.8991 16 17.0031V20.0031C16 21.1071 16.896 22.0031 18 22.0031H20C21.104 22.0031 22 21.1071 22 20.0031V12.0031C22 6.48805 17.514 2.00305 12 2.00305Z" fill="var(--interactive-normal)"></path></svg></>
|
||||
}
|
||||
</>
|
||||
)}
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export * from "./components";
|
||||
export * from "./discordModules";
|
||||
export * from "./emitter";
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
export * from "./audio";
|
||||
export * from "./userPanel";
|
||||
export * from "./video";
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { React } from "@webpack/common";
|
||||
import { JSX } from "react";
|
||||
|
||||
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 }, index) =>
|
||||
tooltipText
|
||||
? <SettingsPanelTooltipButton
|
||||
key={`tooltip-button-${index}`} // Add a unique key here
|
||||
tooltipProps={{ text: tooltipText }}
|
||||
icon={icon}
|
||||
onClick={onClick}
|
||||
/>
|
||||
: <SettingsPanelButton
|
||||
key={`button-${index}`} // Add a unique key here
|
||||
icon={icon}
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
|
||||
groupedButtons.push(splicedButtons);
|
||||
}
|
||||
|
||||
return groupedButtons;
|
||||
};
|
||||
|
||||
return rawPanelButtons.length > 0
|
||||
? <SettingsPanel>
|
||||
{convertRawPanelButtons(rawPanelButtons).map((value, index) => (
|
||||
<SettingsPanelRow key={`panel-row-${index}`}>
|
||||
{value}
|
||||
</SettingsPanelRow>
|
||||
))}
|
||||
</SettingsPanel>
|
||||
: null;
|
||||
};
|
||||
|
||||
export function replacedUserPanelComponent(oldComponent) {
|
||||
return <ButtonsSettingsPanel />;
|
||||
}
|
||||
|
||||
export function addSettingsPanelButton(settings: PanelButton) {
|
||||
settingsPanelButtons.push(settings);
|
||||
}
|
||||
|
||||
export function removeSettingsPanelButton(name: string) {
|
||||
settingsPanelButtons.splice(0, settingsPanelButtons.length, ...settingsPanelButtons.filter(value => value.name !== name));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue