Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
thororen1234 2025-10-09 18:39:40 -04:00
commit 3104664cc8
No known key found for this signature in database
15 changed files with 161 additions and 135 deletions

View file

@ -25,7 +25,7 @@ import type { ComponentType, PropsWithChildren } from "react";
export function SettingsTab({ title, children }: PropsWithChildren<{ title: string; }>) {
return (
<Forms.FormSection>
<section>
<Text
variant="heading-lg/semibold"
tag="h2"
@ -35,7 +35,7 @@ export function SettingsTab({ title, children }: PropsWithChildren<{ title: stri
</Text>
{children}
</Forms.FormSection>
</section>
);
}

View file

@ -109,14 +109,15 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
const Component = OptionComponentMap[setting.type];
return (
<Component
id={key}
key={key}
option={setting}
onChange={debounce(onChange)}
pluginSettings={pluginSettings}
definedSettings={plugin.settings}
/>
<ErrorBoundary noop key={key}>
<Component
id={key}
option={setting}
onChange={debounce(onChange)}
pluginSettings={pluginSettings}
definedSettings={plugin.settings}
/>
</ErrorBoundary>
);
});
@ -156,7 +157,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
</ModalHeader>
<ModalContent className={Margins.bottom16}>
<Forms.FormSection>
<section>
<Flex className={cl("info")}>
<Forms.FormText className={cl("description")}>{plugin.description}</Forms.FormText>
{!pluginMeta.userPlugin && (
@ -195,22 +196,22 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
)}
/>
</div>
</Forms.FormSection>
</section>
{!!plugin.settingsAboutComponent && (
<div className={Margins.top16}>
<Forms.FormSection>
<section>
<ErrorBoundary message="An error occurred while rendering this plugin's custom Info Component">
<plugin.settingsAboutComponent />
</ErrorBoundary>
</Forms.FormSection>
</section>
</div>
)}
<Forms.FormSection>
<section>
<Text variant="heading-lg/semibold" className={classes(Margins.top16, Margins.bottom8)}>Settings</Text>
{renderSettings()}
</Forms.FormSection>
</section>
</ModalContent>
{
hasSettings && <ModalFooter>

View file

@ -21,6 +21,7 @@ import "./styles.css";
import * as DataStore from "@api/DataStore";
import { useSettings } from "@api/Settings";
import { classNameFactory } from "@api/Styles";
import ErrorBoundary from "@components/ErrorBoundary";
import { SettingsTab } from "@components/settings";
import { debounce } from "@shared/debounce";
import { ChangeList } from "@utils/ChangeList";
@ -362,23 +363,27 @@ export default function PluginSettings() {
</Forms.FormTitle>
<div className={classes(Margins.bottom20, cl("filter-controls"))}>
<TextInput autoFocus value={searchValue.value} placeholder="Search for a plugin..." onChange={onSearch} />
<ErrorBoundary noop>
<TextInput autoFocus value={searchValue.value} placeholder="Search for a plugin..." onChange={onSearch} />
</ErrorBoundary>
<div className={InputStyles.inputWrapper}>
<Select
options={[
{ label: "Show All", value: SearchStatus.ALL, default: true },
{ label: "Show Enabled", value: SearchStatus.ENABLED },
{ label: "Show Disabled", value: SearchStatus.DISABLED },
{ label: "Show Equicord", value: SearchStatus.EQUICORD },
{ label: "Show Vencord", value: SearchStatus.VENCORD },
...(totalUserPlugins > 0 ? [{ label: "Show Custom", value: SearchStatus.CUSTOM }] : []),
{ label: "Show New", value: SearchStatus.NEW },
]}
serialize={String}
select={onStatusChange}
isSelected={v => v === searchValue.status}
closeOnSelect={true}
/>
<ErrorBoundary noop>
<Select
options={[
{ label: "Show All", value: SearchStatus.ALL, default: true },
{ label: "Show Enabled", value: SearchStatus.ENABLED },
{ label: "Show Disabled", value: SearchStatus.DISABLED },
{ label: "Show Equicord", value: SearchStatus.EQUICORD },
{ label: "Show Vencord", value: SearchStatus.VENCORD },
...(totalUserPlugins > 0 ? [{ label: "Show Custom", value: SearchStatus.CUSTOM }] : []),
{ label: "Show New", value: SearchStatus.NEW },
]}
serialize={String}
select={onStatusChange}
isSelected={v => v === searchValue.status}
closeOnSelect={true}
/>
</ErrorBoundary>
</div>
</div>

View file

@ -68,7 +68,9 @@ function SettingsSyncSection() {
const sectionEnabled = cloud.authenticated && cloud.settingsSync;
return (
<Forms.FormSection title="Settings Sync" className={Margins.top16}>
<section className={Margins.top16}>
<Forms.FormTitle tag="h5">Settings Sync</Forms.FormTitle>
<Forms.FormText variant="text-md/normal" className={Margins.bottom20}>
Synchronize your settings to the cloud. This allows easy synchronization across multiple devices with
minimal effort.
@ -111,7 +113,7 @@ function SettingsSyncSection() {
Delete Cloud Settings
</Button>
</div>
</Forms.FormSection>
</section>
);
}
@ -131,7 +133,9 @@ function CloudTab() {
return (
<SettingsTab title="Equicord Cloud">
<Forms.FormSection title="Cloud Settings" className={Margins.top16}>
<section className={Margins.top16}>
<Forms.FormTitle tag="h5">Cloud Settings</Forms.FormTitle>
<Forms.FormText variant="text-md/normal" className={Margins.bottom20}>
Equicord comes with a cloud integration allowing settings to be synced across apps and devices.
<br />
@ -206,7 +210,7 @@ function CloudTab() {
</Grid>
<Forms.FormDivider className={Margins.top16} />
</Forms.FormSection >
</section >
<SettingsSyncSection />
</SettingsTab>
);

View file

@ -5,6 +5,7 @@
*/
import { useSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Margins } from "@utils/margins";
import { identity } from "@utils/misc";
import { Forms, Select } from "@webpack/common";
@ -15,66 +16,69 @@ export function VibrancySettings() {
return (
<>
<Forms.FormTitle tag="h5">Window vibrancy style (requires restart)</Forms.FormTitle>
<Select
className={Margins.bottom20}
placeholder="Window vibrancy style"
options={[
// Sorted from most opaque to most transparent
{
label: "No vibrancy", value: undefined
},
{
label: "Under Page (window tinting)",
value: "under-page"
},
{
label: "Content",
value: "content"
},
{
label: "Window",
value: "window"
},
{
label: "Selection",
value: "selection"
},
{
label: "Titlebar",
value: "titlebar"
},
{
label: "Header",
value: "header"
},
{
label: "Sidebar",
value: "sidebar"
},
{
label: "Tooltip",
value: "tooltip"
},
{
label: "Menu",
value: "menu"
},
{
label: "Popover",
value: "popover"
},
{
label: "Fullscreen UI (transparent but slightly muted)",
value: "fullscreen-ui"
},
{
label: "HUD (Most transparent)",
value: "hud"
},
]}
select={v => settings.macosVibrancyStyle = v}
isSelected={v => settings.macosVibrancyStyle === v}
serialize={identity} />
<ErrorBoundary noop>
<Select
className={Margins.bottom20}
placeholder="Window vibrancy style"
options={[
// Sorted from most opaque to most transparent
{
label: "No vibrancy", value: undefined
},
{
label: "Under Page (window tinting)",
value: "under-page"
},
{
label: "Content",
value: "content"
},
{
label: "Window",
value: "window"
},
{
label: "Selection",
value: "selection"
},
{
label: "Titlebar",
value: "titlebar"
},
{
label: "Header",
value: "header"
},
{
label: "Sidebar",
value: "sidebar"
},
{
label: "Tooltip",
value: "tooltip"
},
{
label: "Menu",
value: "menu"
},
{
label: "Popover",
value: "popover"
},
{
label: "Fullscreen UI (transparent but slightly muted)",
value: "fullscreen-ui"
},
{
label: "HUD (Most transparent)",
value: "hud"
},
]}
select={v => settings.macosVibrancyStyle = v}
isSelected={v => settings.macosVibrancyStyle === v}
serialize={identity}
/>
</ErrorBoundary>
</>
);
}

View file

@ -16,7 +16,8 @@ import { Button, Forms, Select, Slider, Text } from "@webpack/common";
export function NotificationSection() {
return (
<Forms.FormSection className={Margins.top16} title="Vencord Notifications" tag="h5">
<section className={Margins.top16}>
<Forms.FormTitle tag="h5">Vencord Notifications</Forms.FormTitle>
<Flex>
<Button onClick={openNotificationSettingsModal}>
Notification Settings
@ -25,7 +26,7 @@ export function NotificationSection() {
View Notification Log
</Button>
</Flex>
</Forms.FormSection>
</section>
);
}

View file

@ -152,7 +152,10 @@ function EquicordSettings() {
buttonOnClick={() => openContributorModal(user)}
/>
)}
<Forms.FormSection title="Quick Actions">
<section>
<Forms.FormTitle tag="h5">Quick Actions</Forms.FormTitle>
<QuickActionCard>
<QuickAction
Icon={LogIcon}
@ -188,15 +191,13 @@ function EquicordSettings() {
}
/>
</QuickActionCard>
</Forms.FormSection>
</section>
<Forms.FormDivider />
<Forms.FormSection className={Margins.top16} title="Settings" tag="h5">
<Forms.FormText
className={Margins.bottom20}
style={{ color: "var(--text-muted)" }}
>
<section className={Margins.top16}>
<Forms.FormTitle tag="h5">Settings</Forms.FormTitle>
<Forms.FormText className={Margins.bottom20} style={{ color: "var(--text-muted)" }}>
Hint: You can change the position of this settings section in the{" "}
<Button
look={Button.Looks.BLANK}
@ -231,7 +232,7 @@ function EquicordSettings() {
/>
),
)}
</Forms.FormSection>
</section>
{needsVibrancySettings && (
<>
@ -303,10 +304,9 @@ function EquicordSettings() {
</>
)}
<Forms.FormSection
<section
className={Margins.top16}
title="Equicord Notifications"
tag="h5"
>
<Flex>
<Button onClick={openNotificationSettingsModal}>
@ -316,7 +316,7 @@ function EquicordSettings() {
View Notification Log
</Button>
</Flex>
</Forms.FormSection>
</section>
</SettingsTab>
);
}

View file

@ -89,7 +89,8 @@ function CreateDecorationModal(props: ModalProps) {
<div className={cl("create-decoration-modal-form-preview-container")}>
<div className={cl("create-decoration-modal-form")}>
{error !== null && <Text color="text-danger" variant="text-xs/normal">{error.message}</Text>}
<Forms.FormSection title="File">
<section>
<Forms.FormTitle tag="h5">File</Forms.FormTitle>
<FileUpload
filename={file?.name}
placeholder="Choose a file"
@ -100,8 +101,9 @@ function CreateDecorationModal(props: ModalProps) {
<Forms.FormText className={Margins.top8}>
File should be APNG or PNG.
</Forms.FormText>
</Forms.FormSection>
<Forms.FormSection title="Name">
</section>
<section>
<Forms.FormTitle tag="h5">Name</Forms.FormTitle>
<TextInput
placeholder="Companion Cube"
value={name}
@ -110,7 +112,7 @@ function CreateDecorationModal(props: ModalProps) {
<Forms.FormText className={Margins.top8}>
This name will be used when referring to this decoration.
</Forms.FormText>
</Forms.FormSection>
</section>
</div>
<div>
<AvatarDecorationModalPreview

View file

@ -113,7 +113,7 @@ function SettingsAboutComponent() {
const [color2, setColor2] = useState(existingColors[1]);
return (
<Forms.FormSection>
<section>
<Forms.FormTitle tag="h3">Usage</Forms.FormTitle>
<Forms.FormText>
After enabling this plugin, you will see custom colors in
@ -191,7 +191,7 @@ function SettingsAboutComponent() {
/>
</div>
</Forms.FormText>
</Forms.FormSection>);
</section>);
}
export default definePlugin({

View file

@ -131,7 +131,7 @@ function IdsListComponent(props: { setValue: (value: string) => void; }) {
}
return (
<Forms.FormSection>
<section>
<Forms.FormTitle tag="h3">Filter List</Forms.FormTitle>
<Forms.FormText className={Margins.bottom8}>Comma separated list of activity IDs to filter (Useful for filtering specific RPC activities and CustomRPC</Forms.FormText>
<TextInput
@ -140,7 +140,7 @@ function IdsListComponent(props: { setValue: (value: string) => void; }) {
onChange={handleChange}
placeholder="235834946571337729, 343383572805058560"
/>
</Forms.FormSection>
</section>
);
}

View file

@ -81,15 +81,15 @@ export function NewCategoryModal({ categoryId, modalProps, initialChannelId }: P
{/* form is here so when you press enter while in the text input it submits */}
<form onSubmit={onSave}>
<ModalContent className={cl("content")}>
<Forms.FormSection>
<section>
<Forms.FormTitle>Name</Forms.FormTitle>
<TextInput
value={name}
onChange={e => setName(e)}
/>
</Forms.FormSection>
</section>
<Forms.FormDivider />
<Forms.FormSection>
<section>
<Forms.FormTitle>Color</Forms.FormTitle>
<ColorPickerWithSwatches
key={category.id}
@ -107,7 +107,7 @@ export function NewCategoryModal({ categoryId, modalProps, initialChannelId }: P
/>
)}
/>
</Forms.FormSection>
</section>
</ModalContent>
<ModalFooter>
<Button type="submit" onClick={onSave} disabled={!name}>{categoryId ? "Save" : "Create"}</Button>

View file

@ -88,7 +88,8 @@ function TimingSection({ title, logs, traceEnd }: TimingSectionProps) {
});
return (
<Forms.FormSection title={title} tag="h1">
<section>
<Forms.FormTitle tag="h2">{title}</Forms.FormTitle>
<code>
{traceEnd && (
<div style={{ color: "var(--header-primary)", marginBottom: 5, userSelect: "text" }}>
@ -105,7 +106,7 @@ function TimingSection({ title, logs, traceEnd }: TimingSectionProps) {
))}
</div>
</code>
</Forms.FormSection>
</section>
);
}
@ -117,7 +118,8 @@ function ServerTrace({ trace }: ServerTraceProps) {
const lines = trace.split("\n");
return (
<Forms.FormSection title="Server Trace" tag="h2">
<section>
<Forms.FormTitle tag="h3">Server Trace</Forms.FormTitle>
<code>
<Flex flexDirection="column" style={{ color: "var(--header-primary)", gap: 5, userSelect: "text" }}>
{lines.map((line, idx) => (
@ -125,7 +127,7 @@ function ServerTrace({ trace }: ServerTraceProps) {
))}
</Flex>
</code>
</Forms.FormSection>
</section>
);
}

View file

@ -117,9 +117,9 @@ function VoiceSetting() {
export function VoiceSettingSection() {
return (
<Forms.FormSection>
<section>
<Forms.FormTitle>Voice</Forms.FormTitle>
<VoiceSetting />
</Forms.FormSection>
</section>
);
}

View file

@ -227,7 +227,7 @@ export default definePlugin({
}
return (
<Forms.FormSection>
<section>
<Forms.FormText>
You can customise the spoken messages below. You can disable specific messages by setting them to nothing
</Forms.FormText>
@ -255,7 +255,7 @@ export default definePlugin({
</>
)}
{errorComponent}
</Forms.FormSection>
</section>
);
}
});

View file

@ -19,20 +19,19 @@
import { FormSwitchCompat } from "@components/FormSwitch";
import { LazyComponent } from "@utils/lazyReact";
import * as t from "@vencord/discord-types";
import { filters, mapMangledModuleLazy, waitFor } from "@webpack";
import { filters, find, LazyComponentWebpack, mapMangledModuleLazy, waitFor } from "@webpack";
import { FormText } from "./FormText";
import { waitForComponent } from "./internal";
const FormTitle = waitForComponent<t.FormTitle>("FormTitle", filters.componentByCode('["defaultMargin".concat', '="h5"'));
const FormSection = waitForComponent<t.FormSection>("FormSection", filters.componentByCode(".titleId)"));
const FormDivider = waitForComponent<t.FormDivider>("FormDivider", filters.componentByCode(".divider,", ",style:", '"div"', /\.divider,\i\),style:/));
export const Forms = {
FormTitle,
FormText,
FormSection,
/** @deprecated don't use this */
FormSection: "section" as never, // Backwards compat since Vesktop uses this
FormDivider
};
@ -57,8 +56,16 @@ export const TextInput = waitForComponent<t.TextInput>("TextInput", filters.comp
export const TextArea = waitForComponent<t.TextArea>("TextArea", filters.componentByCode("this.getPaddingRight()},id:"));
export const Text = waitForComponent<t.Text>("Text", filters.componentByCode('case"always-white"'));
export const Heading = waitForComponent<t.Heading>("Heading", filters.componentByCode(">6?{", "variant:"));
export const Select = waitForComponent<t.Select>("Select", filters.componentByCode('="bottom",', ".select,", '"Escape"==='));
export const SearchableSelect = waitForComponent<t.SearchableSelect>("SearchableSelect", filters.componentByCode(".setSelectionRange(", ".multi]:"));
export const Select: t.Select = LazyComponentWebpack(() => {
const oldFilter = filters.componentByCode('="bottom",', ".select,", '"Escape"===');
const newFilter = filters.componentByCode('"Select"', ".newOptionLabel");
const res = find(oldFilter) ?? find(newFilter);
if (res) return res;
throw new Error("Vencord failed to find the Select component");
});
export const SearchableSelect = waitForComponent<t.SearchableSelect>("SearchableSelect", filters.componentByCode('"SearchableSelect"'));
export const Slider = waitForComponent<t.Slider>("Slider", filters.componentByCode('"markDash".concat('));
export const Popout = waitForComponent<t.Popout>("Popout", filters.componentByCode("ref:this.ref,", "renderPopout:this.renderPopout,"));
export const Dialog = waitForComponent<t.Dialog>("Dialog", filters.componentByCode('role:"dialog",tabIndex:-1'));