add hardware video acceleration switch & improve settings ui

This commit is contained in:
Vendicated
2025-06-08 20:56:28 +02:00
parent 6e7d912b95
commit 48e9aea47e
8 changed files with 98 additions and 47 deletions

View File

@@ -39,12 +39,14 @@ function init() {
if (hardwareAcceleration === false) { if (hardwareAcceleration === false) {
app.disableHardwareAcceleration(); app.disableHardwareAcceleration();
} else { } else {
enabledFeatures.add("AcceleratedVideoEncoder"); if (Settings.store.hardwareVideoAcceleration) {
enabledFeatures.add("AcceleratedVideoDecoder"); enabledFeatures.add("AcceleratedVideoEncoder");
enabledFeatures.add("AcceleratedVideoDecoder");
if (isLinux) { if (isLinux) {
enabledFeatures.add("AcceleratedVideoDecodeLinuxGL"); enabledFeatures.add("AcceleratedVideoDecodeLinuxGL");
enabledFeatures.add("AcceleratedVideoDecodeLinuxZeroCopyGL"); enabledFeatures.add("AcceleratedVideoDecodeLinuxZeroCopyGL");
}
} }
} }

View File

@@ -4,15 +4,16 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
import { Switch, useState } from "@vencord/types/webpack/common"; import { useState } from "@vencord/types/webpack/common";
import { SettingsComponent } from "./Settings"; import { SettingsComponent } from "./Settings";
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
export const AutoStartToggle: SettingsComponent = () => { export const AutoStartToggle: SettingsComponent = () => {
const [autoStartEnabled, setAutoStartEnabled] = useState(VesktopNative.autostart.isEnabled()); const [autoStartEnabled, setAutoStartEnabled] = useState(VesktopNative.autostart.isEnabled());
return ( return (
<Switch <VesktopSettingsSwitch
value={autoStartEnabled} value={autoStartEnabled}
onChange={async v => { onChange={async v => {
await VesktopNative.autostart[v ? "enable" : "disable"](); await VesktopNative.autostart[v ? "enable" : "disable"]();
@@ -21,6 +22,6 @@ export const AutoStartToggle: SettingsComponent = () => {
note="Automatically start Vesktop on computer start-up" note="Automatically start Vesktop on computer start-up"
> >
Start With System Start With System
</Switch> </VesktopSettingsSwitch>
); );
}; };

View File

@@ -4,14 +4,14 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
import { Switch } from "@vencord/types/webpack/common";
import { setBadge } from "renderer/appBadge"; import { setBadge } from "renderer/appBadge";
import { SettingsComponent } from "./Settings"; import { SettingsComponent } from "./Settings";
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
export const NotificationBadgeToggle: SettingsComponent = ({ settings }) => { export const NotificationBadgeToggle: SettingsComponent = ({ settings }) => {
return ( return (
<Switch <VesktopSettingsSwitch
value={settings.appBadge ?? true} value={settings.appBadge ?? true}
onChange={v => { onChange={v => {
settings.appBadge = v; settings.appBadge = v;
@@ -21,6 +21,6 @@ export const NotificationBadgeToggle: SettingsComponent = ({ settings }) => {
note="Show mention badge on the app icon" note="Show mention badge on the app icon"
> >
Notification Badge Notification Badge
</Switch> </VesktopSettingsSwitch>
); );
}; };

View File

@@ -7,7 +7,7 @@
import "./settings.css"; import "./settings.css";
import { ErrorBoundary } from "@vencord/types/components"; import { ErrorBoundary } from "@vencord/types/components";
import { Forms, Switch, Text } from "@vencord/types/webpack/common"; import { Forms, Text } from "@vencord/types/webpack/common";
import { ComponentType } from "react"; import { ComponentType } from "react";
import { Settings, useSettings } from "renderer/settings"; import { Settings, useSettings } from "renderer/settings";
import { isMac, isWindows } from "renderer/utils"; import { isMac, isWindows } from "renderer/utils";
@@ -16,6 +16,7 @@ import { AutoStartToggle } from "./AutoStartToggle";
import { DeveloperOptionsButton } from "./DeveloperOptions"; import { DeveloperOptionsButton } from "./DeveloperOptions";
import { DiscordBranchPicker } from "./DiscordBranchPicker"; import { DiscordBranchPicker } from "./DiscordBranchPicker";
import { NotificationBadgeToggle } from "./NotificationBadgeToggle"; import { NotificationBadgeToggle } from "./NotificationBadgeToggle";
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
import { WindowsTransparencyControls } from "./WindowsTransparencyControls"; import { WindowsTransparencyControls } from "./WindowsTransparencyControls";
interface BooleanSetting { interface BooleanSetting {
@@ -38,6 +39,14 @@ const SettingsOptions: Record<string, Array<BooleanSetting | SettingsComponent>>
title: "Hardware Acceleration", title: "Hardware Acceleration",
description: "Enable hardware acceleration", description: "Enable hardware acceleration",
defaultValue: true defaultValue: true
},
{
key: "hardwareVideoAcceleration",
title: "Video Hardware Acceleration",
description:
"Enable hardware video acceleration. This can improve performance of screenshare and video playback, but may cause graphical glitches and infinitely loading streams.",
defaultValue: false,
disabled: () => !Settings.store.hardwareAcceleration
} }
], ],
"User Interface": [ "User Interface": [
@@ -132,32 +141,35 @@ const SettingsOptions: Record<string, Array<BooleanSetting | SettingsComponent>>
function SettingsSections() { function SettingsSections() {
const Settings = useSettings(); const Settings = useSettings();
const sections = Object.entries(SettingsOptions).map(([title, settings]) => ( const sections = Object.entries(SettingsOptions).map(([title, settings], i, arr) => (
<Forms.FormSection <div key={title} className="vcd-settings-category">
title={title} <Text variant="heading-lg/semibold" color="header-primary" className="vcd-settings-category-title">
key={title} {title}
className="vcd-settings-section" </Text>
titleClassName="vcd-settings-title"
>
{settings.map(Setting => {
if (typeof Setting === "function") return <Setting settings={Settings} />;
const { defaultValue, title, description, key, disabled, invisible } = Setting; <div className="vcd-settings-category-content">
if (invisible?.()) return null; {settings.map(Setting => {
if (typeof Setting === "function") return <Setting settings={Settings} />;
return ( const { defaultValue, title, description, key, disabled, invisible } = Setting;
<Switch if (invisible?.()) return null;
value={Settings[key as any] ?? defaultValue}
onChange={v => (Settings[key as any] = v)} return (
note={description} <VesktopSettingsSwitch
disabled={disabled?.()} value={Settings[key as any] ?? defaultValue}
key={key} onChange={v => (Settings[key as any] = v)}
> note={description}
{title} disabled={disabled?.()}
</Switch> key={key}
); >
})} {title}
</Forms.FormSection> </VesktopSettingsSwitch>
);
})}
</div>
{i < arr.length - 1 && <Forms.FormDivider className="vcd-settings-category-divider" />}
</div>
)); ));
return <>{sections}</>; return <>{sections}</>;
@@ -167,10 +179,11 @@ export default ErrorBoundary.wrap(
function SettingsUI() { function SettingsUI() {
return ( return (
<Forms.FormSection> <Forms.FormSection>
<Text variant="heading-lg/semibold" style={{ color: "var(--header-primary)" }} tag="h2"> {/* FIXME: Outdated type */}
{/* @ts-expect-error Outdated type */}
<Text variant="heading-xl/semibold" color="header-primary" className="vcd-settings-title">
Vesktop Settings Vesktop Settings
</Text> </Text>
<SettingsSections /> <SettingsSections />
</Forms.FormSection> </Forms.FormSection>
); );

View File

@@ -0,0 +1,16 @@
/*
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
* Copyright (c) 2025 Vendicated and Vesktop contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { Switch } from "@vencord/types/webpack/common";
import { ComponentProps } from "react";
export function VesktopSettingsSwitch(props: ComponentProps<typeof Switch>) {
return (
<Switch {...props} hideBorder className="vcd-settings-switch">
{props.children}
</Switch>
);
}

View File

@@ -13,8 +13,8 @@ export const WindowsTransparencyControls: SettingsComponent = ({ settings }) =>
if (!VesktopNative.app.supportsWindowsTransparency()) return null; if (!VesktopNative.app.supportsWindowsTransparency()) return null;
return ( return (
<> <div>
<Forms.FormTitle className={Margins.top16 + " " + Margins.bottom8}>Transparency Options</Forms.FormTitle> <Forms.FormTitle className={Margins.bottom8}>Transparency Options</Forms.FormTitle>
<Forms.FormText className={Margins.bottom8}> <Forms.FormText className={Margins.bottom8}>
Requires a full restart. You will need a theme that supports transparency for this to work. Requires a full restart. You will need a theme that supports transparency for this to work.
</Forms.FormText> </Forms.FormText>
@@ -42,8 +42,6 @@ export const WindowsTransparencyControls: SettingsComponent = ({ settings }) =>
isSelected={v => v === settings.transparencyOption} isSelected={v => v === settings.transparencyOption}
serialize={s => s} serialize={s => s}
/> />
</div>
<Forms.FormDivider className={Margins.top16 + " " + Margins.bottom16} />
</>
); );
}; };

View File

@@ -5,10 +5,30 @@
margin-top: 0.5em; margin-top: 0.5em;
} }
.vcd-settings-section { .vcd-settings-title {
margin-top: 1.5rem; margin-bottom: 32px;
} }
.vcd-settings-title { .vcd-settings-category {
margin-bottom: 0.5rem; display: flex;
flex-direction: column;
}
.vcd-settings-category-title {
margin-bottom: 16px;
}
.vcd-settings-category-content {
display: flex;
flex-direction: column;
gap: 24px;
}
.vcd-settings-category-divider {
margin-top: 32px;
margin-bottom: 32px;
}
.vcd-settings-switch {
margin-bottom: 0;
} }

View File

@@ -16,6 +16,7 @@ export interface Settings {
enableMenu?: boolean; enableMenu?: boolean;
disableSmoothScroll?: boolean; disableSmoothScroll?: boolean;
hardwareAcceleration?: boolean; hardwareAcceleration?: boolean;
hardwareVideoAcceleration?: boolean;
arRPC?: boolean; arRPC?: boolean;
appBadge?: boolean; appBadge?: boolean;
disableMinSize?: boolean; disableMinSize?: boolean;