fix ScreensharePicker ui & modernise all UI
This commit is contained in:
+1
-1
@@ -38,7 +38,7 @@
|
|||||||
"@stylistic/eslint-plugin": "^5.6.1",
|
"@stylistic/eslint-plugin": "^5.6.1",
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"@types/react": "19.2.1",
|
"@types/react": "19.2.1",
|
||||||
"@vencord/types": "^1.13.2",
|
"@vencord/types": "^1.13.7",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"electron": "^39.2.3",
|
"electron": "^39.2.3",
|
||||||
"electron-builder": "^26.0.12",
|
"electron-builder": "^26.0.12",
|
||||||
|
|||||||
Generated
+19
-12
@@ -36,8 +36,8 @@ importers:
|
|||||||
specifier: 19.2.1
|
specifier: 19.2.1
|
||||||
version: 19.2.1
|
version: 19.2.1
|
||||||
'@vencord/types':
|
'@vencord/types':
|
||||||
specifier: ^1.13.2
|
specifier: ^1.13.7
|
||||||
version: 1.13.2(@types/react-dom@18.3.1)(@types/react@19.2.1)
|
version: 1.13.7(@types/react-dom@18.3.1)(@types/react@19.2.1)
|
||||||
dotenv:
|
dotenv:
|
||||||
specifier: ^17.2.3
|
specifier: ^17.2.3
|
||||||
version: 17.2.3
|
version: 17.2.3
|
||||||
@@ -629,6 +629,9 @@ packages:
|
|||||||
'@types/node@22.19.1':
|
'@types/node@22.19.1':
|
||||||
resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==}
|
resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==}
|
||||||
|
|
||||||
|
'@types/node@22.19.2':
|
||||||
|
resolution: {integrity: sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==}
|
||||||
|
|
||||||
'@types/node@24.10.1':
|
'@types/node@24.10.1':
|
||||||
resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==}
|
resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==}
|
||||||
|
|
||||||
@@ -714,8 +717,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': ^19.0.10
|
'@types/react': ^19.0.10
|
||||||
|
|
||||||
'@vencord/types@1.13.2':
|
'@vencord/types@1.13.7':
|
||||||
resolution: {integrity: sha512-5RifSCC1X4xzoNaDTMANRLVZreEsHWWsGs6iBooqnBkLeigfP7FqAQfn6onogk/2+YQKNMTQT8N+MD+HGes5EA==}
|
resolution: {integrity: sha512-MThrBwMEJ0CvKMrVgJC4cvJuDwwFXEhgSOJnmDZxmJeKOByVWLo7xxjn1suHkE1/euw9J5lGTfz1QTiYVXbLqA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': 18.3.1
|
'@types/react': 18.3.1
|
||||||
'@types/react-dom': 18.3.1
|
'@types/react-dom': 18.3.1
|
||||||
@@ -2983,8 +2986,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4'
|
typescript: '>=4.8.4'
|
||||||
|
|
||||||
ts-pattern@5.8.0:
|
ts-pattern@5.9.0:
|
||||||
resolution: {integrity: sha512-kIjN2qmWiHnhgr5DAkAafF9fwb0T5OhMVSWrm8XEdTFnX6+wfXwYOFjeF86UZ54vduqiR7BfqScFmXSzSaH8oA==}
|
resolution: {integrity: sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==}
|
||||||
|
|
||||||
tsconfig-paths@3.15.0:
|
tsconfig-paths@3.15.0:
|
||||||
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
|
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
|
||||||
@@ -3236,7 +3239,7 @@ snapshots:
|
|||||||
make-fetch-happen: 10.2.1
|
make-fetch-happen: 10.2.1
|
||||||
nopt: 6.0.0
|
nopt: 6.0.0
|
||||||
proc-log: 2.0.1
|
proc-log: 2.0.1
|
||||||
semver: 7.7.3
|
semver: 7.7.2
|
||||||
tar: 6.2.1
|
tar: 6.2.1
|
||||||
which: 2.0.2
|
which: 2.0.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -3574,7 +3577,7 @@ snapshots:
|
|||||||
'@npmcli/fs@2.1.2':
|
'@npmcli/fs@2.1.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@gar/promisify': 1.1.3
|
'@gar/promisify': 1.1.3
|
||||||
semver: 7.7.3
|
semver: 7.7.2
|
||||||
|
|
||||||
'@npmcli/move-file@2.0.1':
|
'@npmcli/move-file@2.0.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3641,6 +3644,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.21.0
|
undici-types: 6.21.0
|
||||||
|
|
||||||
|
'@types/node@22.19.2':
|
||||||
|
dependencies:
|
||||||
|
undici-types: 6.21.0
|
||||||
|
|
||||||
'@types/node@24.10.1':
|
'@types/node@24.10.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 7.16.0
|
undici-types: 7.16.0
|
||||||
@@ -3770,16 +3777,16 @@ snapshots:
|
|||||||
moment: 2.30.1
|
moment: 2.30.1
|
||||||
type-fest: 4.41.0
|
type-fest: 4.41.0
|
||||||
|
|
||||||
'@vencord/types@1.13.2(@types/react-dom@18.3.1)(@types/react@19.2.1)':
|
'@vencord/types@1.13.7(@types/react-dom@18.3.1)(@types/react@19.2.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/lodash': 4.17.15
|
'@types/lodash': 4.17.15
|
||||||
'@types/node': 22.19.1
|
'@types/node': 22.19.2
|
||||||
'@types/react': 19.2.1
|
'@types/react': 19.2.1
|
||||||
'@types/react-dom': 18.3.1
|
'@types/react-dom': 18.3.1
|
||||||
'@vencord/discord-types': 1.0.0(@types/react@19.2.1)
|
'@vencord/discord-types': 1.0.0(@types/react@19.2.1)
|
||||||
highlight.js: 11.11.1
|
highlight.js: 11.11.1
|
||||||
moment: 2.30.1
|
moment: 2.30.1
|
||||||
ts-pattern: 5.8.0
|
ts-pattern: 5.9.0
|
||||||
type-fest: 4.41.0
|
type-fest: 4.41.0
|
||||||
|
|
||||||
'@vencord/venmic@6.1.0':
|
'@vencord/venmic@6.1.0':
|
||||||
@@ -6597,7 +6604,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
|
|
||||||
ts-pattern@5.8.0: {}
|
ts-pattern@5.9.0: {}
|
||||||
|
|
||||||
tsconfig-paths@3.15.0:
|
tsconfig-paths@3.15.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -7,10 +7,31 @@
|
|||||||
import "./screenSharePicker.css";
|
import "./screenSharePicker.css";
|
||||||
|
|
||||||
import { classNameFactory } from "@vencord/types/api/Styles";
|
import { classNameFactory } from "@vencord/types/api/Styles";
|
||||||
import { CogWheel, FormSwitch, RestartIcon } from "@vencord/types/components";
|
import {
|
||||||
import { closeModal, Logger, Modals, ModalSize, openModal, useAwaiter, useForceUpdater } from "@vencord/types/utils";
|
BaseText,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
CogWheel,
|
||||||
|
FormSwitch,
|
||||||
|
Heading,
|
||||||
|
HeadingTertiary,
|
||||||
|
Margins,
|
||||||
|
Paragraph,
|
||||||
|
RestartIcon,
|
||||||
|
Span
|
||||||
|
} from "@vencord/types/components";
|
||||||
|
import {
|
||||||
|
closeModal,
|
||||||
|
Logger,
|
||||||
|
ModalCloseButton,
|
||||||
|
Modals,
|
||||||
|
ModalSize,
|
||||||
|
openModal,
|
||||||
|
useAwaiter,
|
||||||
|
useForceUpdater
|
||||||
|
} from "@vencord/types/utils";
|
||||||
import { onceReady } from "@vencord/types/webpack";
|
import { onceReady } from "@vencord/types/webpack";
|
||||||
import { Button, Card, FluxDispatcher, Forms, Select, Text, UserStore, useState } from "@vencord/types/webpack/common";
|
import { FluxDispatcher, Select, UserStore, useState } from "@vencord/types/webpack/common";
|
||||||
import { Node } from "@vencord/venmic";
|
import { Node } from "@vencord/venmic";
|
||||||
import type { Dispatch, SetStateAction } from "react";
|
import type { Dispatch, SetStateAction } from "react";
|
||||||
import { MediaEngineStore } from "renderer/common";
|
import { MediaEngineStore } from "renderer/common";
|
||||||
@@ -18,6 +39,8 @@ import { addPatch } from "renderer/patches/shared";
|
|||||||
import { State, useSettings, useVesktopState } from "renderer/settings";
|
import { State, useSettings, useVesktopState } from "renderer/settings";
|
||||||
import { isLinux, isWindows } from "renderer/utils";
|
import { isLinux, isWindows } from "renderer/utils";
|
||||||
|
|
||||||
|
import { SimpleErrorBoundary } from "./SimpleErrorBoundary";
|
||||||
|
|
||||||
const StreamResolutions = ["480", "720", "1080", "1440", "2160"] as const;
|
const StreamResolutions = ["480", "720", "1080", "1440", "2160"] as const;
|
||||||
const StreamFps = ["15", "30", "60"] as const;
|
const StreamFps = ["15", "30", "60"] as const;
|
||||||
|
|
||||||
@@ -145,6 +168,9 @@ export function openScreenSharePicker(screens: Source[], skipPicker: boolean) {
|
|||||||
onCloseRequest() {
|
onCloseRequest() {
|
||||||
closeModal(key);
|
closeModal(key);
|
||||||
reject("Aborted");
|
reject("Aborted");
|
||||||
|
},
|
||||||
|
onCloseCallback() {
|
||||||
|
reject("Aborted");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -165,9 +191,7 @@ function ScreenPicker({ screens, chooseScreen }: { screens: Source[]; chooseScre
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<img src={url} alt="" />
|
<img src={url} alt="" />
|
||||||
<Text className={cl("screen-name")} variant="text-sm/normal">
|
<Paragraph className={cl("screen-name")}>{name}</Paragraph>
|
||||||
{name}
|
|
||||||
</Text>
|
|
||||||
</label>
|
</label>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -188,19 +212,16 @@ function AudioSettingsModal({
|
|||||||
return (
|
return (
|
||||||
<Modals.ModalRoot {...modalProps} size={ModalSize.MEDIUM}>
|
<Modals.ModalRoot {...modalProps} size={ModalSize.MEDIUM}>
|
||||||
<Modals.ModalHeader className={cl("header")}>
|
<Modals.ModalHeader className={cl("header")}>
|
||||||
<Forms.FormTitle tag="h2">Venmic Settings</Forms.FormTitle>
|
<BaseText size="lg" weight="semibold" tag="h3" style={{ flexGrow: 1 }}>
|
||||||
<Modals.ModalCloseButton onClick={close} className={cl("header-close-button")} />
|
Audio Settings
|
||||||
|
</BaseText>
|
||||||
|
<ModalCloseButton onClick={close} />
|
||||||
</Modals.ModalHeader>
|
</Modals.ModalHeader>
|
||||||
|
|
||||||
<Modals.ModalContent className={cl("modal", "venmic-settings")}>
|
<Modals.ModalContent className={cl("modal", "venmic-settings")}>
|
||||||
<FormSwitch
|
<FormSwitch
|
||||||
title="Microphone Workaround"
|
title="Microphone Workaround"
|
||||||
description={
|
description="Work around an issue that causes the microphone to be shared instead of the correct audio. Only enable if you're experiencing this issue."
|
||||||
<>
|
|
||||||
Work around an issue that causes the microphone to be shared instead of the correct audio.
|
|
||||||
Only enable if you're experiencing this issue.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
hideBorder
|
hideBorder
|
||||||
onChange={v => (Settings.audio = { ...Settings.audio, workaround: v })}
|
onChange={v => (Settings.audio = { ...Settings.audio, workaround: v })}
|
||||||
value={Settings.audio?.workaround ?? false}
|
value={Settings.audio?.workaround ?? false}
|
||||||
@@ -208,10 +229,7 @@ function AudioSettingsModal({
|
|||||||
<FormSwitch
|
<FormSwitch
|
||||||
title="Only Speakers"
|
title="Only Speakers"
|
||||||
description={
|
description={
|
||||||
<>
|
'When sharing entire desktop audio, only share apps that play to a speaker. You may want to disable this when using "mix bussing".'
|
||||||
When sharing entire desktop audio, only share apps that play to a speaker. You may want to
|
|
||||||
disable this when using "mix bussing".
|
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
hideBorder
|
hideBorder
|
||||||
onChange={v => (Settings.audio = { ...Settings.audio, onlySpeakers: v })}
|
onChange={v => (Settings.audio = { ...Settings.audio, onlySpeakers: v })}
|
||||||
@@ -231,7 +249,7 @@ function AudioSettingsModal({
|
|||||||
/>
|
/>
|
||||||
<FormSwitch
|
<FormSwitch
|
||||||
title="Ignore Inputs"
|
title="Ignore Inputs"
|
||||||
description={<>Exclude nodes that are intended to capture audio.</>}
|
description="Exclude nodes that are intended to capture audio."
|
||||||
hideBorder
|
hideBorder
|
||||||
onChange={v => (Settings.audio = { ...Settings.audio, ignoreInputMedia: v })}
|
onChange={v => (Settings.audio = { ...Settings.audio, ignoreInputMedia: v })}
|
||||||
value={Settings.audio?.ignoreInputMedia ?? true}
|
value={Settings.audio?.ignoreInputMedia ?? true}
|
||||||
@@ -239,10 +257,7 @@ function AudioSettingsModal({
|
|||||||
<FormSwitch
|
<FormSwitch
|
||||||
title="Ignore Virtual"
|
title="Ignore Virtual"
|
||||||
description={
|
description={
|
||||||
<>
|
'Exclude virtual nodes, such as nodes belonging to loopbacks. This might be useful when using "mix bussing".'
|
||||||
Exclude virtual nodes, such as nodes belonging to loopbacks. This might be useful when using
|
|
||||||
"mix bussing".
|
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
hideBorder
|
hideBorder
|
||||||
onChange={v => (Settings.audio = { ...Settings.audio, ignoreVirtual: v })}
|
onChange={v => (Settings.audio = { ...Settings.audio, ignoreVirtual: v })}
|
||||||
@@ -250,7 +265,7 @@ function AudioSettingsModal({
|
|||||||
/>
|
/>
|
||||||
<FormSwitch
|
<FormSwitch
|
||||||
title="Ignore Devices"
|
title="Ignore Devices"
|
||||||
description={<>Exclude device nodes, such as nodes belonging to microphones or speakers.</>}
|
description="Exclude device nodes, such as nodes belonging to microphones or speakers."
|
||||||
hideBorder
|
hideBorder
|
||||||
onChange={v =>
|
onChange={v =>
|
||||||
(Settings.audio = {
|
(Settings.audio = {
|
||||||
@@ -263,7 +278,7 @@ function AudioSettingsModal({
|
|||||||
/>
|
/>
|
||||||
<FormSwitch
|
<FormSwitch
|
||||||
title="Granular Selection"
|
title="Granular Selection"
|
||||||
description={<>Allow to select applications more granularly.</>}
|
description="Allow to select applications more granularly."
|
||||||
hideBorder
|
hideBorder
|
||||||
onChange={value => {
|
onChange={value => {
|
||||||
Settings.audio = { ...Settings.audio, granularSelect: value };
|
Settings.audio = { ...Settings.audio, granularSelect: value };
|
||||||
@@ -289,7 +304,7 @@ function AudioSettingsModal({
|
|||||||
/>
|
/>
|
||||||
</Modals.ModalContent>
|
</Modals.ModalContent>
|
||||||
<Modals.ModalFooter className={cl("footer")}>
|
<Modals.ModalFooter className={cl("footer")}>
|
||||||
<Button color={Button.Colors.TRANSPARENT} onClick={close}>
|
<Button variant="secondary" onClick={close}>
|
||||||
Back
|
Back
|
||||||
</Button>
|
</Button>
|
||||||
</Modals.ModalFooter>
|
</Modals.ModalFooter>
|
||||||
@@ -310,7 +325,7 @@ function OptionRadio<Settings extends object, Key extends keyof Settings>(props:
|
|||||||
<div className={cl("option-radios")}>
|
<div className={cl("option-radios")}>
|
||||||
{(options as string[]).map((option, idx) => (
|
{(options as string[]).map((option, idx) => (
|
||||||
<label className={cl("option-radio")} data-checked={settings[settingsKey] === option} key={option}>
|
<label className={cl("option-radio")} data-checked={settings[settingsKey] === option} key={option}>
|
||||||
<Text variant="text-sm/bold">{labels?.[idx] ?? option}</Text>
|
<Span weight="bold">{labels?.[idx] ?? option}</Span>
|
||||||
<input
|
<input
|
||||||
className={cl("option-input")}
|
className={cl("option-input")}
|
||||||
type="radio"
|
type="radio"
|
||||||
@@ -361,18 +376,18 @@ function StreamSettingsUi({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Forms.FormTitle>What you're streaming</Forms.FormTitle>
|
<HeadingTertiary className={Margins.bottom8}>What you're streaming</HeadingTertiary>
|
||||||
<Card className={cl("card", "preview")}>
|
<Card className={cl("card", "preview")}>
|
||||||
<img src={thumb} alt="" className={cl(isLinux ? "preview-img-linux" : "preview-img")} />
|
<img src={thumb} alt="" className={cl(isLinux ? "preview-img-linux" : "preview-img")} />
|
||||||
<Text variant="text-sm/normal">{source.name}</Text>
|
<Paragraph>{source.name}</Paragraph>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Forms.FormTitle>Stream Settings</Forms.FormTitle>
|
<HeadingTertiary className={Margins.bottom8}>Stream Settings</HeadingTertiary>
|
||||||
|
|
||||||
<Card className={cl("card")}>
|
<Card className={cl("card")}>
|
||||||
<div className={cl("quality")}>
|
<div className={cl("quality")}>
|
||||||
<section className={cl("quality-section")}>
|
<section className={cl("quality-section")}>
|
||||||
<Forms.FormTitle>Resolution</Forms.FormTitle>
|
<Heading tag="h5">Resolution</Heading>
|
||||||
<OptionRadio
|
<OptionRadio
|
||||||
options={StreamResolutions}
|
options={StreamResolutions}
|
||||||
settings={qualitySettings}
|
settings={qualitySettings}
|
||||||
@@ -382,7 +397,7 @@ function StreamSettingsUi({
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className={cl("quality-section")}>
|
<section className={cl("quality-section")}>
|
||||||
<Forms.FormTitle>Frame Rate</Forms.FormTitle>
|
<Heading tag="h5">Frame Rate</Heading>
|
||||||
<OptionRadio
|
<OptionRadio
|
||||||
options={StreamFps}
|
options={StreamFps}
|
||||||
settings={qualitySettings}
|
settings={qualitySettings}
|
||||||
@@ -393,7 +408,7 @@ function StreamSettingsUi({
|
|||||||
</div>
|
</div>
|
||||||
<div className={cl("quality")}>
|
<div className={cl("quality")}>
|
||||||
<section className={cl("quality-section")}>
|
<section className={cl("quality-section")}>
|
||||||
<Forms.FormTitle>Content Type</Forms.FormTitle>
|
<Heading tag="h5">Content Type</Heading>
|
||||||
<div>
|
<div>
|
||||||
<OptionRadio
|
<OptionRadio
|
||||||
options={["motion", "detail"]}
|
options={["motion", "detail"]}
|
||||||
@@ -402,12 +417,11 @@ function StreamSettingsUi({
|
|||||||
settingsKey="contentHint"
|
settingsKey="contentHint"
|
||||||
onChange={option => setSettings(s => ({ ...s, contentHint: option }))}
|
onChange={option => setSettings(s => ({ ...s, contentHint: option }))}
|
||||||
/>
|
/>
|
||||||
<div className={cl("hint-description")}>
|
|
||||||
<p>
|
<Paragraph className={Margins.top8}>
|
||||||
Choosing "Prefer Clarity" will result in a significantly lower framerate in exchange
|
Choosing "Prefer Clarity" will result in a significantly lower framerate in exchange for
|
||||||
for a much sharper and clearer image.
|
a much sharper and clearer image.
|
||||||
</p>
|
</Paragraph>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{isWindows && (
|
{isWindows && (
|
||||||
<FormSwitch
|
<FormSwitch
|
||||||
@@ -578,7 +592,7 @@ function AudioSourcePickerLinux({
|
|||||||
|
|
||||||
if (!sources.ok && sources.isGlibCxxOutdated) {
|
if (!sources.ok && sources.isGlibCxxOutdated) {
|
||||||
return (
|
return (
|
||||||
<Forms.FormText>
|
<Paragraph>
|
||||||
Failed to retrieve Audio Sources because your C++ library is too old to run
|
Failed to retrieve Audio Sources because your C++ library is too old to run
|
||||||
<a href="https://github.com/Vencord/venmic" target="_blank" rel="noreferrer">
|
<a href="https://github.com/Vencord/venmic" target="_blank" rel="noreferrer">
|
||||||
venmic
|
venmic
|
||||||
@@ -592,13 +606,13 @@ function AudioSourcePickerLinux({
|
|||||||
this guide
|
this guide
|
||||||
</a>{" "}
|
</a>{" "}
|
||||||
for possible solutions.
|
for possible solutions.
|
||||||
</Forms.FormText>
|
</Paragraph>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasPipewirePulse && !ignorePulseWarning) {
|
if (!hasPipewirePulse && !ignorePulseWarning) {
|
||||||
return (
|
return (
|
||||||
<Text variant="text-sm/normal">
|
<Paragraph>
|
||||||
Could not find pipewire-pulse. See{" "}
|
Could not find pipewire-pulse. See{" "}
|
||||||
<a
|
<a
|
||||||
href="https://gist.github.com/the-spyke/2de98b22ff4f978ebf0650c90e82027e#install"
|
href="https://gist.github.com/the-spyke/2de98b22ff4f978ebf0650c90e82027e#install"
|
||||||
@@ -611,7 +625,7 @@ function AudioSourcePickerLinux({
|
|||||||
You can still continue, however, please{" "}
|
You can still continue, however, please{" "}
|
||||||
<b>beware that you can only share audio of apps that are running under pipewire</b>.{" "}
|
<b>beware that you can only share audio of apps that are running under pipewire</b>.{" "}
|
||||||
<a onClick={() => setIgnorePulseWarning(true)}>I know what I'm doing!</a>
|
<a onClick={() => setIgnorePulseWarning(true)}>I know what I'm doing!</a>
|
||||||
</Text>
|
</Paragraph>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,50 +645,50 @@ function AudioSourcePickerLinux({
|
|||||||
<>
|
<>
|
||||||
<div className={cl("audio-sources")}>
|
<div className={cl("audio-sources")}>
|
||||||
<section>
|
<section>
|
||||||
<Forms.FormTitle>{loading ? "Loading Sources..." : "Audio Sources"}</Forms.FormTitle>
|
<Heading tag="h5">{loading ? "Loading Sources..." : "Audio Sources"}</Heading>
|
||||||
<Select
|
<SimpleErrorBoundary>
|
||||||
options={allSources.map(({ name, value }) => ({
|
|
||||||
label: name,
|
|
||||||
value: value,
|
|
||||||
default: name === "None"
|
|
||||||
}))}
|
|
||||||
isSelected={isItemSelected(includeSources)}
|
|
||||||
select={updateItems(setIncludeSources, includeSources)}
|
|
||||||
serialize={String}
|
|
||||||
popoutPosition="top"
|
|
||||||
closeOnSelect={false}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
{includeSources === "Entire System" && (
|
|
||||||
<section>
|
|
||||||
<Forms.FormTitle>Exclude Sources</Forms.FormTitle>
|
|
||||||
<Select
|
<Select
|
||||||
options={allSources
|
options={allSources.map(({ name, value }) => ({
|
||||||
.filter(x => x.name !== "Entire System")
|
label: name,
|
||||||
.map(({ name, value }) => ({
|
value: value,
|
||||||
label: name,
|
default: name === "None"
|
||||||
value: value,
|
}))}
|
||||||
default: name === "None"
|
isSelected={isItemSelected(includeSources)}
|
||||||
}))}
|
select={updateItems(setIncludeSources, includeSources)}
|
||||||
isSelected={isItemSelected(excludeSources)}
|
|
||||||
select={updateItems(setExcludeSources, excludeSources)}
|
|
||||||
serialize={String}
|
serialize={String}
|
||||||
popoutPosition="top"
|
popoutPosition="top"
|
||||||
closeOnSelect={false}
|
closeOnSelect={false}
|
||||||
/>
|
/>
|
||||||
|
</SimpleErrorBoundary>
|
||||||
|
</section>
|
||||||
|
{includeSources === "Entire System" && (
|
||||||
|
<section>
|
||||||
|
<Heading tag="h5">Exclude Sources</Heading>
|
||||||
|
<SimpleErrorBoundary>
|
||||||
|
<Select
|
||||||
|
options={allSources
|
||||||
|
.filter(x => x.name !== "Entire System")
|
||||||
|
.map(({ name, value }) => ({
|
||||||
|
label: name,
|
||||||
|
value: value,
|
||||||
|
default: name === "None"
|
||||||
|
}))}
|
||||||
|
isSelected={isItemSelected(excludeSources)}
|
||||||
|
select={updateItems(setExcludeSources, excludeSources)}
|
||||||
|
serialize={String}
|
||||||
|
popoutPosition="top"
|
||||||
|
closeOnSelect={false}
|
||||||
|
/>
|
||||||
|
</SimpleErrorBoundary>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={cl("settings-buttons")}>
|
<div className={cl("settings-buttons")}>
|
||||||
<Button
|
<Button variant="secondary" onClick={refreshAudioSources} className={cl("settings-button")}>
|
||||||
color={Button.Colors.TRANSPARENT}
|
|
||||||
onClick={refreshAudioSources}
|
|
||||||
className={cl("settings-button")}
|
|
||||||
>
|
|
||||||
<RestartIcon className={cl("settings-button-icon")} />
|
<RestartIcon className={cl("settings-button-icon")} />
|
||||||
Refresh Audio Sources
|
Refresh Audio Sources
|
||||||
</Button>
|
</Button>
|
||||||
<Button color={Button.Colors.TRANSPARENT} onClick={openSettings} className={cl("settings-button")}>
|
<Button variant="secondary" onClick={openSettings} className={cl("settings-button")}>
|
||||||
<CogWheel className={cl("settings-button-icon")} />
|
<CogWheel className={cl("settings-button-icon")} />
|
||||||
Open Audio Settings
|
Open Audio Settings
|
||||||
</Button>
|
</Button>
|
||||||
@@ -710,8 +724,10 @@ function ModalComponent({
|
|||||||
return (
|
return (
|
||||||
<Modals.ModalRoot {...modalProps} size={ModalSize.MEDIUM}>
|
<Modals.ModalRoot {...modalProps} size={ModalSize.MEDIUM}>
|
||||||
<Modals.ModalHeader className={cl("header")}>
|
<Modals.ModalHeader className={cl("header")}>
|
||||||
<Forms.FormTitle tag="h2">ScreenShare</Forms.FormTitle>
|
<BaseText size="lg" weight="semibold" tag="h3" style={{ flexGrow: 1 }}>
|
||||||
<Modals.ModalCloseButton onClick={close} />
|
Screen Share Picker
|
||||||
|
</BaseText>
|
||||||
|
<ModalCloseButton onClick={close} />
|
||||||
</Modals.ModalHeader>
|
</Modals.ModalHeader>
|
||||||
<Modals.ModalContent className={cl("modal")}>
|
<Modals.ModalContent className={cl("modal")}>
|
||||||
{!selected ? (
|
{!selected ? (
|
||||||
@@ -789,11 +805,11 @@ function ModalComponent({
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{selected && !skipPicker ? (
|
{selected && !skipPicker ? (
|
||||||
<Button color={Button.Colors.TRANSPARENT} onClick={() => setSelected(void 0)}>
|
<Button variant="secondary" onClick={() => setSelected(void 0)}>
|
||||||
Back
|
Back
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button color={Button.Colors.TRANSPARENT} onClick={close}>
|
<Button variant="secondary" onClick={close}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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 { Card, ErrorBoundary, HeadingTertiary, Paragraph, TextButton } from "@vencord/types/components";
|
||||||
|
import { FluxDispatcher, InviteActions } from "@vencord/types/webpack/common";
|
||||||
|
import type { PropsWithChildren } from "react";
|
||||||
|
|
||||||
|
async function openSupportChannel() {
|
||||||
|
const code = "YVbdG2ZRG4";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { invite } = await InviteActions.resolveInvite(code, "Desktop Modal");
|
||||||
|
|
||||||
|
if (!invite) throw 0;
|
||||||
|
|
||||||
|
await FluxDispatcher.dispatch({
|
||||||
|
type: "INVITE_MODAL_OPEN",
|
||||||
|
invite,
|
||||||
|
code,
|
||||||
|
context: "APP"
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
window.open(`https://discord.gg/${code}`, "_blank");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Fallback() {
|
||||||
|
return (
|
||||||
|
<Card variant="danger">
|
||||||
|
<HeadingTertiary>Something went wrong.</HeadingTertiary>
|
||||||
|
<Paragraph>
|
||||||
|
Please make sure Vencord and Vesktop are fully up to date. You can get help in our{" "}
|
||||||
|
<TextButton variant="link" onClick={openSupportChannel}>
|
||||||
|
Support Channel
|
||||||
|
</TextButton>
|
||||||
|
</Paragraph>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SimpleErrorBoundary({ children }: PropsWithChildren<{}>) {
|
||||||
|
return <ErrorBoundary fallback={Fallback}>{children}</ErrorBoundary>;
|
||||||
|
}
|
||||||
@@ -81,13 +81,13 @@
|
|||||||
/* Option Radios */
|
/* Option Radios */
|
||||||
|
|
||||||
.vcd-screen-picker-option-radios {
|
.vcd-screen-picker-option-radios {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vcd-screen-picker-option-radio {
|
.vcd-screen-picker-option-radio {
|
||||||
flex: 1 1 auto;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: var(--background-secondary);
|
background-color: var(--background-secondary);
|
||||||
border: 1px solid var(--primary-800);
|
border: 1px solid var(--primary-800);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { BaseText, Button, Heading, Paragraph, TextButton } from "@vencord/types/components";
|
||||||
import {
|
import {
|
||||||
Margins,
|
Margins,
|
||||||
ModalCloseButton,
|
ModalCloseButton,
|
||||||
@@ -14,7 +15,7 @@ import {
|
|||||||
openModal,
|
openModal,
|
||||||
useForceUpdater
|
useForceUpdater
|
||||||
} from "@vencord/types/utils";
|
} from "@vencord/types/utils";
|
||||||
import { Button, Forms, Text, Toasts } from "@vencord/types/webpack/common";
|
import { Toasts } from "@vencord/types/webpack/common";
|
||||||
import { Settings } from "shared/settings";
|
import { Settings } from "shared/settings";
|
||||||
|
|
||||||
import { cl, SettingsComponent } from "./Settings";
|
import { cl, SettingsComponent } from "./Settings";
|
||||||
@@ -27,20 +28,20 @@ function openDeveloperOptionsModal(settings: Settings) {
|
|||||||
openModal(props => (
|
openModal(props => (
|
||||||
<ModalRoot {...props} size={ModalSize.MEDIUM}>
|
<ModalRoot {...props} size={ModalSize.MEDIUM}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>
|
<BaseText size="lg" weight="semibold" tag="h3" style={{ flexGrow: 1 }}>
|
||||||
Vesktop Developer Options
|
Vesktop Developer Options
|
||||||
</Text>
|
</BaseText>
|
||||||
<ModalCloseButton onClick={props.onClose} />
|
<ModalCloseButton onClick={props.onClose} />
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
<div style={{ padding: "1em 0" }}>
|
<div style={{ padding: "1em 0" }}>
|
||||||
<Forms.FormTitle tag="h5">Vencord Location</Forms.FormTitle>
|
<Heading tag="h5">Vencord Location</Heading>
|
||||||
<VencordLocationPicker settings={settings} />
|
<VencordLocationPicker settings={settings} />
|
||||||
|
|
||||||
<Forms.FormTitle tag="h5" className={Margins.top16}>
|
<Heading tag="h5" className={Margins.top16}>
|
||||||
Debugging
|
Debugging
|
||||||
</Forms.FormTitle>
|
</Heading>
|
||||||
<div className={cl("button-grid")}>
|
<div className={cl("button-grid")}>
|
||||||
<Button onClick={() => VesktopNative.debug.launchGpu()}>Open chrome://gpu</Button>
|
<Button onClick={() => VesktopNative.debug.launchGpu()}>Open chrome://gpu</Button>
|
||||||
<Button onClick={() => VesktopNative.debug.launchWebrtcInternals()}>
|
<Button onClick={() => VesktopNative.debug.launchWebrtcInternals()}>
|
||||||
@@ -59,25 +60,24 @@ const VencordLocationPicker: SettingsComponent = ({ settings }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Forms.FormText>
|
<Paragraph>
|
||||||
Vencord files are loaded from{" "}
|
Vencord files are loaded from{" "}
|
||||||
{vencordDir ? (
|
{vencordDir ? (
|
||||||
<a
|
<TextButton
|
||||||
href="about:blank"
|
variant="link"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
VesktopNative.fileManager.showItemInFolder(vencordDir!);
|
VesktopNative.fileManager.showItemInFolder(vencordDir!);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{vencordDir}
|
{vencordDir}
|
||||||
</a>
|
</TextButton>
|
||||||
) : (
|
) : (
|
||||||
"the default location"
|
"the default location"
|
||||||
)}
|
)}
|
||||||
</Forms.FormText>
|
</Paragraph>
|
||||||
<div className={cl("button-grid")}>
|
<div className={cl("button-grid")}>
|
||||||
<Button
|
<Button
|
||||||
size={Button.Sizes.SMALL}
|
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const choice = await VesktopNative.fileManager.selectVencordDir();
|
const choice = await VesktopNative.fileManager.selectVencordDir();
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
@@ -105,8 +105,7 @@ const VencordLocationPicker: SettingsComponent = ({ settings }) => {
|
|||||||
Change
|
Change
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size={Button.Sizes.SMALL}
|
variant="dangerPrimary"
|
||||||
color={Button.Colors.RED}
|
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await VesktopNative.fileManager.selectVencordDir(null);
|
await VesktopNative.fileManager.selectVencordDir(null);
|
||||||
forceUpdate();
|
forceUpdate();
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ErrorBoundary } from "@vencord/types/components";
|
|
||||||
import { Select } from "@vencord/types/webpack/common";
|
import { Select } from "@vencord/types/webpack/common";
|
||||||
|
|
||||||
|
import { SimpleErrorBoundary } from "../SimpleErrorBoundary";
|
||||||
import { SettingsComponent } from "./Settings";
|
import { SettingsComponent } from "./Settings";
|
||||||
|
|
||||||
export const DiscordBranchPicker: SettingsComponent = ({ settings }) => {
|
export const DiscordBranchPicker: SettingsComponent = ({ settings }) => {
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary noop>
|
<SimpleErrorBoundary>
|
||||||
<Select
|
<Select
|
||||||
placeholder="Stable"
|
placeholder="Stable"
|
||||||
options={[
|
options={[
|
||||||
@@ -24,6 +24,6 @@ export const DiscordBranchPicker: SettingsComponent = ({ settings }) => {
|
|||||||
isSelected={v => v === settings.discordBranch}
|
isSelected={v => v === settings.discordBranch}
|
||||||
serialize={s => s}
|
serialize={s => s}
|
||||||
/>
|
/>
|
||||||
</ErrorBoundary>
|
</SimpleErrorBoundary>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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 { Button, Card, HeadingTertiary, Paragraph } from "@vencord/types/components";
|
||||||
|
import { useAwaiter } from "@vencord/types/utils";
|
||||||
|
|
||||||
|
import { cl } from "./Settings";
|
||||||
|
|
||||||
|
export function OutdatedVesktopWarning() {
|
||||||
|
const [isOutdated] = useAwaiter(VesktopNative.app.isOutdated);
|
||||||
|
|
||||||
|
if (!isOutdated) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card variant="warning" className={cl("updater-card")}>
|
||||||
|
<HeadingTertiary>Your Vesktop is outdated!</HeadingTertiary>
|
||||||
|
<Paragraph>Staying up to date is important for security and stability.</Paragraph>
|
||||||
|
|
||||||
|
<Button onClick={() => VesktopNative.app.openUpdater()} variant="secondary">
|
||||||
|
Open Updater
|
||||||
|
</Button>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,8 +7,7 @@
|
|||||||
import "./settings.css";
|
import "./settings.css";
|
||||||
|
|
||||||
import { classNameFactory } from "@vencord/types/api/Styles";
|
import { classNameFactory } from "@vencord/types/api/Styles";
|
||||||
import { ErrorBoundary } from "@vencord/types/components";
|
import { BaseText, Divider, ErrorBoundary } from "@vencord/types/components";
|
||||||
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";
|
||||||
@@ -17,7 +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 { Updater } from "./Updater";
|
import { OutdatedVesktopWarning } from "./OutdatedVesktopWarning";
|
||||||
import { UserAssetsButton } from "./UserAssets";
|
import { UserAssetsButton } from "./UserAssets";
|
||||||
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
|
import { VesktopSettingsSwitch } from "./VesktopSettingsSwitch";
|
||||||
import { WindowsTransparencyControls } from "./WindowsTransparencyControls";
|
import { WindowsTransparencyControls } from "./WindowsTransparencyControls";
|
||||||
@@ -149,9 +148,9 @@ function SettingsSections() {
|
|||||||
|
|
||||||
const sections = Object.entries(SettingsOptions).map(([title, settings], i, arr) => (
|
const sections = Object.entries(SettingsOptions).map(([title, settings], i, arr) => (
|
||||||
<div key={title} className={cl("category")}>
|
<div key={title} className={cl("category")}>
|
||||||
<Text variant="heading-lg/semibold" color="header-primary" className={cl("category-title")}>
|
<BaseText size="lg" weight="semibold" tag="h3" className={cl("category-title")}>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</BaseText>
|
||||||
|
|
||||||
<div className={cl("category-content")}>
|
<div className={cl("category-content")}>
|
||||||
{settings.map((Setting, i) => {
|
{settings.map((Setting, i) => {
|
||||||
@@ -173,7 +172,7 @@ function SettingsSections() {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{i < arr.length - 1 && <Forms.FormDivider className={cl("category-divider")} />}
|
{i < arr.length - 1 && <Divider className={cl("category-divider")} />}
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -184,10 +183,7 @@ export default ErrorBoundary.wrap(
|
|||||||
function SettingsUI() {
|
function SettingsUI() {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<Text variant="heading-xl/semibold" color="header-primary" className={cl("title")}>
|
<OutdatedVesktopWarning />
|
||||||
Vesktop Settings
|
|
||||||
</Text>
|
|
||||||
<Updater />
|
|
||||||
<SettingsSections />
|
<SettingsSections />
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { useAwaiter } from "@vencord/types/utils";
|
|
||||||
import { Button, Text } from "@vencord/types/webpack/common";
|
|
||||||
|
|
||||||
import { cl } from "./Settings";
|
|
||||||
|
|
||||||
export function Updater() {
|
|
||||||
const [isOutdated] = useAwaiter(VesktopNative.app.isOutdated);
|
|
||||||
|
|
||||||
if (!isOutdated) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={cl("updater-card")}>
|
|
||||||
<Text variant="text-md/semibold">Your Vesktop is outdated!</Text>
|
|
||||||
<Text variant="text-sm/normal">Staying up to date is important for security and stability.</Text>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
onClick={() => VesktopNative.app.openUpdater()}
|
|
||||||
size={Button.Sizes.SMALL}
|
|
||||||
color={Button.Colors.TRANSPARENT}
|
|
||||||
>
|
|
||||||
Open Updater
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
import "./UserAssets.css";
|
import "./UserAssets.css";
|
||||||
|
|
||||||
import { FormSwitch } from "@vencord/types/components";
|
import { BaseText, Button, FormSwitch } from "@vencord/types/components";
|
||||||
import {
|
import {
|
||||||
Margins,
|
Margins,
|
||||||
ModalCloseButton,
|
ModalCloseButton,
|
||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
wordsFromCamel,
|
wordsFromCamel,
|
||||||
wordsToTitle
|
wordsToTitle
|
||||||
} from "@vencord/types/utils";
|
} from "@vencord/types/utils";
|
||||||
import { Button, showToast, Text, useState } from "@vencord/types/webpack/common";
|
import { showToast, useState } from "@vencord/types/webpack/common";
|
||||||
import { UserAssetType } from "main/userAssets";
|
import { UserAssetType } from "main/userAssets";
|
||||||
import { useSettings } from "renderer/settings";
|
import { useSettings } from "renderer/settings";
|
||||||
|
|
||||||
@@ -34,9 +34,9 @@ function openAssetsModal() {
|
|||||||
openModal(props => (
|
openModal(props => (
|
||||||
<ModalRoot {...props} size={ModalSize.MEDIUM}>
|
<ModalRoot {...props} size={ModalSize.MEDIUM}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>
|
<BaseText size="lg" weight="semibold" tag="h3" style={{ flexGrow: 1 }}>
|
||||||
User Assets
|
User Assets
|
||||||
</Text>
|
</BaseText>
|
||||||
<ModalCloseButton onClick={props.onClose} />
|
<ModalCloseButton onClick={props.onClose} />
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
||||||
@@ -73,9 +73,9 @@ function Asset({ asset }: { asset: UserAssetType }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<Text tag="h3" variant="text-md/semibold">
|
<BaseText size="md" weight="medium" tag="h3">
|
||||||
{wordsToTitle(wordsFromCamel(asset))}
|
{wordsToTitle(wordsFromCamel(asset))}
|
||||||
</Text>
|
</BaseText>
|
||||||
<div className="vcd-user-assets-asset">
|
<div className="vcd-user-assets-asset">
|
||||||
<img
|
<img
|
||||||
className="vcd-user-assets-image"
|
className="vcd-user-assets-image"
|
||||||
@@ -86,7 +86,7 @@ function Asset({ asset }: { asset: UserAssetType }) {
|
|||||||
<div className="vcd-user-assets-actions">
|
<div className="vcd-user-assets-actions">
|
||||||
<div className="vcd-user-assets-buttons">
|
<div className="vcd-user-assets-buttons">
|
||||||
<Button onClick={onChooseAsset()}>Customize</Button>
|
<Button onClick={onChooseAsset()}>Customize</Button>
|
||||||
<Button color={Button.Colors.PRIMARY} onClick={onChooseAsset(null)}>
|
<Button variant="secondary" onClick={onChooseAsset(null)}>
|
||||||
Reset to default
|
Reset to default
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { FormSwitch } from "@vencord/types/components";
|
import { FormSwitch } from "@vencord/types/components";
|
||||||
import { ComponentProps } from "react";
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
import { cl } from "./Settings";
|
import { cl } from "./Settings";
|
||||||
|
|
||||||
|
|||||||
@@ -4,23 +4,24 @@
|
|||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ErrorBoundary } from "@vencord/types/components";
|
import { Heading, Paragraph } from "@vencord/types/components";
|
||||||
import { Margins } from "@vencord/types/utils";
|
import { Margins } from "@vencord/types/utils";
|
||||||
import { Forms, Select } from "@vencord/types/webpack/common";
|
import { Select } from "@vencord/types/webpack/common";
|
||||||
|
|
||||||
|
import { SimpleErrorBoundary } from "../SimpleErrorBoundary";
|
||||||
import { SettingsComponent } from "./Settings";
|
import { SettingsComponent } from "./Settings";
|
||||||
|
|
||||||
export const WindowsTransparencyControls: SettingsComponent = ({ settings }) => {
|
export const WindowsTransparencyControls: SettingsComponent = ({ settings }) => {
|
||||||
if (!VesktopNative.app.supportsWindowsTransparency()) return null;
|
if (!VesktopNative.app.supportsWindowsTransparency()) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary noop>
|
<div>
|
||||||
<div>
|
<Heading tag="h5">Transparency Options</Heading>
|
||||||
<Forms.FormTitle className={Margins.bottom8}>Transparency Options</Forms.FormTitle>
|
<Paragraph 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.
|
</Paragraph>
|
||||||
</Forms.FormText>
|
|
||||||
|
|
||||||
|
<SimpleErrorBoundary>
|
||||||
<Select
|
<Select
|
||||||
placeholder="None"
|
placeholder="None"
|
||||||
options={[
|
options={[
|
||||||
@@ -44,7 +45,7 @@ export const WindowsTransparencyControls: SettingsComponent = ({ settings }) =>
|
|||||||
isSelected={v => v === settings.transparencyOption}
|
isSelected={v => v === settings.transparencyOption}
|
||||||
serialize={s => s}
|
serialize={s => s}
|
||||||
/>
|
/>
|
||||||
</div>
|
</SimpleErrorBoundary>
|
||||||
</ErrorBoundary>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,10 +38,4 @@
|
|||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: var(--bg-secondary);
|
|
||||||
background: var(--background-feedback-warning);
|
|
||||||
border: 1px solid var(--info-warning-foreground);
|
|
||||||
color: var(--text-feedback-warning);
|
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,7 @@ import type SettingsPlugin from "@vencord/types/plugins/_core/settings";
|
|||||||
VesktopLogger.log("read if cute :3");
|
VesktopLogger.log("read if cute :3");
|
||||||
VesktopLogger.log("Vesktop v" + VesktopNative.app.getVersion());
|
VesktopLogger.log("Vesktop v" + VesktopNative.app.getVersion());
|
||||||
|
|
||||||
|
// TODO
|
||||||
const customSettingsSections = (Vencord.Plugins.plugins.Settings as any as typeof SettingsPlugin).customSections;
|
const customSettingsSections = (Vencord.Plugins.plugins.Settings as any as typeof SettingsPlugin).customSections;
|
||||||
|
|
||||||
customSettingsSections.push(() => ({
|
customSettingsSections.push(() => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user