Skip to content

Commit

Permalink
improve settings ui (again)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vendicated authored and Nuckyz committed Jul 3, 2024
1 parent 7749206 commit 99b41db
Show file tree
Hide file tree
Showing 11 changed files with 308 additions and 186 deletions.
8 changes: 7 additions & 1 deletion .stylelintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
{
"extends": "stylelint-config-standard",
"rules": {
"indentation": 4
"indentation": 4,
"selector-class-pattern": [
"^[a-z][a-zA-Z0-9]*(-[a-z0-9][a-zA-Z0-9]*)*$",
{
"message": "Expected class selector to be kebab-case with camelCase segments"
}
]
}
}
15 changes: 15 additions & 0 deletions src/components/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,21 @@ export function PaintbrushIcon(props: IconProps) {
);
}

export function PencilIcon(props: IconProps) {
return (
<Icon
{...props}
className={classes(props.className, "vc-pencil-icon")}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="m13.96 5.46 4.58 4.58a1 1 0 0 0 1.42 0l1.38-1.38a2 2 0 0 0 0-2.82l-3.18-3.18a2 2 0 0 0-2.82 0l-1.38 1.38a1 1 0 0 0 0 1.42ZM2.11 20.16l.73-4.22a3 3 0 0 1 .83-1.61l7.87-7.87a1 1 0 0 1 1.42 0l4.58 4.58a1 1 0 0 1 0 1.42l-7.87 7.87a3 3 0 0 1-1.6.83l-4.23.73a1.5 1.5 0 0 1-1.73-1.73Z"
/>
</Icon>
);
}

const WebsiteIconDark = "/assets/e1e96d89e192de1997f73730db26e94f.svg";
const WebsiteIconLight = "/assets/730f58bcfd5a57a5e22460c445a0c6cf.svg";
const GithubIconLight = "/assets/3ff98ad75ac94fa883af5ed62d17c459.svg";
Expand Down
88 changes: 40 additions & 48 deletions src/components/VencordSettings/ThemesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@
import { useSettings } from "@api/Settings";
import { classNameFactory } from "@api/Styles";
import { Flex } from "@components/Flex";
import { DeleteIcon } from "@components/Icons";
import { DeleteIcon, FolderIcon, PaintbrushIcon, PencilIcon, PlusIcon, RestartIcon } from "@components/Icons";
import { Link } from "@components/Link";
import PluginModal from "@components/PluginSettings/PluginModal";
import { openPluginModal } from "@components/PluginSettings/PluginModal";
import type { UserThemeHeader } from "@main/themes";
import { openInviteModal } from "@utils/discord";
import { Margins } from "@utils/margins";
import { classes } from "@utils/misc";
import { openModal } from "@utils/modal";
import { showItemInFolder } from "@utils/native";
import { useAwaiter } from "@utils/react";
import { findByPropsLazy, findLazy } from "@webpack";
import { Button, Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common";
import { Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common";
import type { ComponentType, Ref, SyntheticEvent } from "react";

import { AddonCard } from "./AddonCard";
import { QuickAction, QuickActionCard } from "./quickActions";
import { SettingsTab, wrapTab } from "./shared";

type FileInput = ComponentType<{
Expand Down Expand Up @@ -213,60 +213,52 @@ function ThemesTab() {
</Card>

<Forms.FormSection title="Local Themes">
<Card className="vc-settings-quick-actions-card">
<QuickActionCard>
<>
{IS_WEB ?
(
<Button
size={Button.Sizes.SMALL}
disabled={themeDirPending}
>
Upload Theme
<FileInput
ref={fileInputRef}
onChange={onFileUpload}
multiple={true}
filters={[{ extensions: ["css"] }]}
/>
</Button>
<QuickAction
text={
<span style={{ position: "relative" }}>
Upload Theme
<FileInput
ref={fileInputRef}
onChange={onFileUpload}
multiple={true}
filters={[{ extensions: ["css"] }]}
/>
</span>
}
Icon={PlusIcon}
/>
) : (
<Button
onClick={() => showItemInFolder(themeDir!)}
size={Button.Sizes.SMALL}
<QuickAction
text="Open Themes Folder"
action={() => showItemInFolder(themeDir!)}
disabled={themeDirPending}
>
Open Themes Folder
</Button>
Icon={FolderIcon}
/>
)}
<Button
onClick={refreshLocalThemes}
size={Button.Sizes.SMALL}
>
Load missing Themes
</Button>
<Button
onClick={() => VencordNative.quickCss.openEditor()}
size={Button.Sizes.SMALL}
>
Edit QuickCSS
</Button>
<QuickAction
text="Load missing Themes"
action={refreshLocalThemes}
Icon={RestartIcon}
/>
<QuickAction
text="Edit QuickCSS"
action={() => VencordNative.quickCss.openEditor()}
Icon={PaintbrushIcon}
/>

{Vencord.Settings.plugins.ClientTheme.enabled && (
<Button
onClick={() => openModal(modalProps => (
<PluginModal
{...modalProps}
plugin={Vencord.Plugins.plugins.ClientTheme}
onRestartNeeded={() => { }}
/>
))}
size={Button.Sizes.SMALL}
>
Edit ClientTheme
</Button>
<QuickAction
text="Edit ClientTheme"
action={() => openPluginModal(Vencord.Plugins.plugins.ClientTheme)}
Icon={PencilIcon}
/>
)}
</>
</Card>
</QuickActionCard>

<div className={cl("grid")}>
{userThemes?.map(theme => (
Expand Down
77 changes: 30 additions & 47 deletions src/components/VencordSettings/VencordTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ import { useSettings } from "@api/Settings";
import { classNameFactory } from "@api/Styles";
import DonateButton from "@components/DonateButton";
import { openPluginModal } from "@components/PluginSettings/PluginModal";
import { gitRemote } from "@shared/vencordUserAgent";
import { Margins } from "@utils/margins";
import { identity } from "@utils/misc";
import { relaunch, showItemInFolder } from "@utils/native";
import { useAwaiter } from "@utils/react";
import { Button, Card, Forms, React, Select, Switch, TooltipContainer } from "@webpack/common";
import { ComponentType } from "react";
import { Button, Card, Forms, React, Select, Switch } from "@webpack/common";

import { Flex, FolderIcon, GithubIcon, LogIcon, PaintbrushIcon, RestartIcon } from "..";
import { openNotificationSettingsModal } from "./NotificationSettings";
import { QuickAction, QuickActionCard } from "./quickActions";
import { SettingsTab, wrapTab } from "./shared";

const cl = classNameFactory("vc-settings-");
Expand All @@ -41,17 +42,6 @@ type KeysOfType<Object, Type> = {
[K in keyof Object]: Object[K] extends Type ? K : never;
}[keyof Object];

const iconWithTooltip = (Icon: ComponentType<{ className?: string; }>, tooltip: string) => () => (
<TooltipContainer text={tooltip}>
<Icon className={cl("quick-actions-img")} />
</TooltipContainer>
);

const NotificationLogIcon = iconWithTooltip(LogIcon, "Open Notification Log");
const QuickCssIcon = iconWithTooltip(PaintbrushIcon, "Edit QuickCSS");
const RelaunchIcon = iconWithTooltip(RestartIcon, "Relaunch Discord");
const OpenSettingsDirIcon = iconWithTooltip(FolderIcon, "Open Settings Directory");
const OpenGithubIcon = iconWithTooltip(GithubIcon, "View Vencord's GitHub Repository");

function VencordSettings() {
const [settingsDir, , settingsDirPending] = useAwaiter(VencordNative.settings.getSettingsDir, {
Expand Down Expand Up @@ -111,44 +101,37 @@ function VencordSettings() {
<SettingsTab title="Vencord Settings">
<DonateCard image={donateImage} />
<Forms.FormSection title="Quick Actions">
<Card className={cl("quick-actions-card")}>
<Button
onClick={openNotificationLogModal}
look={Button.Looks.BLANK}
>
<NotificationLogIcon />
</Button>
<Button
onClick={() => VencordNative.quickCss.openEditor()}
look={Button.Looks.BLANK}
>
<QuickCssIcon />
</Button>
<QuickActionCard>
<QuickAction
Icon={LogIcon}
text="Notification Log"
action={openNotificationLogModal}
/>
<QuickAction
Icon={PaintbrushIcon}
text="Edit QuickCSS"
action={() => VencordNative.quickCss.openEditor()}
/>
{!IS_WEB && (
<Button
onClick={relaunch}
look={Button.Looks.BLANK}
>
<RelaunchIcon />
</Button>
<QuickAction
Icon={RestartIcon}
text="Relaunch Discord"
action={relaunch}
/>
)}
{!IS_WEB && (
<Button
onClick={() => showItemInFolder(settingsDir)}
look={Button.Looks.BLANK}
disabled={settingsDirPending}
>
<OpenSettingsDirIcon />
</Button>
<QuickAction
Icon={FolderIcon}
text="Open Settings Folder"
action={() => showItemInFolder(settingsDir)}
/>
)}
<Button
onClick={() => VencordNative.native.openExternal("https://github.com/Vendicated/Vencord")}
look={Button.Looks.BLANK}
disabled={settingsDirPending}
>
<OpenGithubIcon />
</Button>
</Card>
<QuickAction
Icon={GithubIcon}
text="View Source Code"
action={() => VencordNative.native.openExternal("https://github.com/" + gitRemote)}
/>
</QuickActionCard>
</Forms.FormSection>

<Forms.FormDivider />
Expand Down
33 changes: 33 additions & 0 deletions src/components/VencordSettings/quickActions.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.vc-settings-quickActions-card {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, max-content));
gap: 0.5em;
justify-content: center;
padding: 0.5em 0;
margin-bottom: 1em;
}

.vc-settings-quickActions-pill {
all: unset;
background: var(--background-secondary);
color: var(--header-secondary);
display: flex;
align-items: center;
gap: 0.5em;
padding: 8px 12px;
border-radius: 9999px;
}

.vc-settings-quickActions-pill:hover {
background: var(--background-secondary-alt);
}

.vc-settings-quickActions-pill:focus-visible {
outline: 2px solid var(--focus-primary);
outline-offset: 2px;
}

.vc-settings-quickActions-img {
width: 24px;
height: 24px;
}
39 changes: 39 additions & 0 deletions src/components/VencordSettings/quickActions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/

import "./quickActions.css";

import { classNameFactory } from "@api/Styles";
import { Card } from "@webpack/common";
import type { ComponentType, PropsWithChildren, ReactNode } from "react";

const cl = classNameFactory("vc-settings-quickActions-");

export interface QuickActionProps {
Icon: ComponentType<{ className?: string; }>;
text: ReactNode;
action?: () => void;
disabled?: boolean;
}

export function QuickAction(props: QuickActionProps) {
const { Icon, action, text, disabled } = props;

return (
<button className={cl("pill")} onClick={action} disabled={disabled}>
<Icon className={cl("img")} />
{text}
</button>
);
}

export function QuickActionCard(props: PropsWithChildren) {
return (
<Card className={cl("card")}>
{props.children}
</Card>
);
}
20 changes: 0 additions & 20 deletions src/components/VencordSettings/settingsStyles.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,6 @@
margin-bottom: -2px;
}

.vc-settings-quick-actions-card {
color: var(--text-normal);
padding: 1em;
display: flex;
justify-content: space-evenly;
gap: 1em;
flex-wrap: wrap;
align-items: center;
margin-bottom: 1em;
}

.vc-settings-quick-actions-card button {
min-width: unset;
}

.vc-settings-quick-actions-img {
width: 30px;
height: 30px;
}

.vc-settings-donate {
display: flex;
flex-direction: row;
Expand Down
2 changes: 1 addition & 1 deletion src/utils/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { DevsById } from "./constants";
* Calls .join(" ") on the arguments
* classes("one", "two") => "one two"
*/
export function classes(...classes: Array<string | null | undefined>) {
export function classes(...classes: Array<string | null | undefined | false>) {
return classes.filter(Boolean).join(" ");
}

Expand Down
Loading

0 comments on commit 99b41db

Please sign in to comment.