add plugin favourites
This commit is contained in:
parent
83b74e2305
commit
67ed651e28
9 changed files with 134 additions and 59 deletions
|
|
@ -68,6 +68,7 @@ export interface Settings {
|
|||
plugins: {
|
||||
[plugin: string]: {
|
||||
enabled: boolean;
|
||||
isFavorite?: boolean;
|
||||
[setting: string]: any;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -639,3 +639,31 @@ export function RightArrow(props: IconProps) {
|
|||
</Icon>
|
||||
);
|
||||
}
|
||||
|
||||
export function StarFilled(props: IconProps) {
|
||||
return (
|
||||
<Icon
|
||||
{...props}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill={props.fill || "currentColor"}
|
||||
d="M10.81 2.86c.38-1.15 2-1.15 2.38 0l1.89 5.83h6.12c1.2 0 1.71 1.54.73 2.25l-4.95 3.6 1.9 5.82a1.25 1.25 0 0 1-1.93 1.4L12 18.16l-4.95 3.6c-.98.7-2.3-.25-1.92-1.4l1.89-5.82-4.95-3.6a1.25 1.25 0 0 1 .73-2.25h6.12l1.9-5.83Z"
|
||||
/>
|
||||
</Icon>
|
||||
);
|
||||
}
|
||||
|
||||
export function StarOutlined(props: IconProps) {
|
||||
return (
|
||||
<Icon
|
||||
{...props}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill={props.fill || "currentColor"}
|
||||
fillRule="evenodd"
|
||||
d="M2.07 10.94a1.25 1.25 0 0 1 .73-2.25h6.12l1.9-5.83c.37-1.15 2-1.15 2.37 0l1.89 5.83h6.12c1.2 0 1.71 1.54.73 2.25l-4.95 3.6 1.9 5.82a1.25 1.25 0 0 1-1.93 1.4L12 18.16l-4.95 3.6c-.98.7-2.3-.25-1.92-1.4l1.89-5.82-4.95-3.6Zm11.55-.25h5.26l-4.25 3.09 1.62 5-4.25-3.1-4.25 3.1 1.62-5-4.25-3.1h5.26l1.62-5 1.62 5Z" />
|
||||
</Icon>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ import { classNameFactory } from "@utils/css";
|
|||
import { fetchUserProfile } from "@utils/discord";
|
||||
import { classes, pluralise } from "@utils/misc";
|
||||
import { RenderModalProps, User } from "@vencord/discord-types";
|
||||
import { Forms, Modal,openModal, showToast, useEffect, useMemo, UserProfileStore, useStateFromStores } from "@webpack/common";
|
||||
import { Forms, Modal, openModal, showToast, useEffect, useMemo, UserProfileStore, useStateFromStores } from "@webpack/common";
|
||||
|
||||
import Plugins from "~plugins";
|
||||
|
||||
import { GithubButton, WebsiteButton } from "./LinkIconButton";
|
||||
import { PluginCard } from "./PluginCard";
|
||||
import { GithubButton, WebsiteButton } from "./PluginModalButtons";
|
||||
|
||||
const cl = classNameFactory("vc-author-modal-");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
.vc-settings-modal-link-icon {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
border-radius: 50%;
|
||||
border: 4px solid var(--background-base-lowest);
|
||||
box-sizing: border-box
|
||||
}
|
||||
|
||||
.vc-settings-modal-links {
|
||||
display: flex;
|
||||
gap: 0.2em;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import "./LinkIconButton.css";
|
||||
|
||||
import { GithubIcon, WebsiteIcon } from "@components/Icons";
|
||||
import { getTheme, Theme } from "@utils/discord";
|
||||
import { MaskedLink, Tooltip } from "@webpack/common";
|
||||
|
||||
export function GithubLinkIcon() {
|
||||
const theme = getTheme() === Theme.Light ? "#000000" : "#FFFFFF";
|
||||
return <GithubIcon aria-hidden fill={theme} className={"vc-settings-modal-link-icon"} />;
|
||||
}
|
||||
|
||||
export function WebsiteLinkIcon() {
|
||||
const theme = getTheme() === Theme.Light ? "#000000" : "#FFFFFF";
|
||||
return <WebsiteIcon aria-hidden fill={theme} className={"vc-settings-modal-link-icon"} />;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
function LinkIcon({ text, href, Icon }: Props & { Icon: React.ComponentType; }) {
|
||||
return (
|
||||
<Tooltip text={text}>
|
||||
{props => (
|
||||
<MaskedLink {...props} href={href}>
|
||||
<Icon />
|
||||
</MaskedLink>
|
||||
)}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
export const WebsiteButton = (props: Props) => <LinkIcon {...props} Icon={WebsiteLinkIcon} />;
|
||||
export const GithubButton = (props: Props) => <LinkIcon {...props} Icon={GithubLinkIcon} />;
|
||||
|
|
@ -32,14 +32,14 @@ import { classes } from "@utils/misc";
|
|||
import { OptionType, Plugin, PluginTag } from "@utils/types";
|
||||
import { RenderModalProps, User } from "@vencord/discord-types";
|
||||
import { findCssClassesLazy } from "@webpack";
|
||||
import { Clickable, FluxDispatcher, Forms, Modal,openModal, React, Text, Tooltip, useEffect, useMemo, UserStore, UserSummaryItem, UserUtils, useState } from "@webpack/common";
|
||||
import { Clickable, FluxDispatcher, Forms, Modal, openModal, React, Text, Tooltip, useEffect, useMemo, UserStore, UserSummaryItem, UserUtils, useState } from "@webpack/common";
|
||||
import { Constructor } from "type-fest";
|
||||
|
||||
import { PluginMeta } from "~plugins";
|
||||
|
||||
import { OptionComponentMap } from "./components";
|
||||
import { openContributorModal } from "./ContributorModal";
|
||||
import { GithubButton, WebsiteButton } from "./LinkIconButton";
|
||||
import { FavoriteButton, GithubButton, WebsiteButton } from "./PluginModalButtons";
|
||||
|
||||
const cl = classNameFactory("vc-plugin-modal-");
|
||||
|
||||
|
|
@ -176,6 +176,10 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
|
|||
<BaseText tag="h1" weight="semibold" size="lg">{plugin.name}</BaseText>
|
||||
{!pluginMeta.userPlugin && (
|
||||
<div className="vc-settings-modal-links">
|
||||
<FavoriteButton
|
||||
isFavorite={pluginSettings.isFavorite ?? false}
|
||||
onClick={() => pluginSettings.isFavorite = !pluginSettings.isFavorite}
|
||||
/>
|
||||
<WebsiteButton
|
||||
text="View more info"
|
||||
href={`https://vencord.dev/plugins/${plugin.name}`}
|
||||
|
|
|
|||
37
src/components/settings/tabs/plugins/PluginModalButtons.css
Normal file
37
src/components/settings/tabs/plugins/PluginModalButtons.css
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
.vc-settings-modal-light {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.vc-settings-modal-dark {
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.vc-settings-modal-favorite-button {
|
||||
cursor: pointer;
|
||||
transition: color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.vc-settings-modal-favorite-button-active,
|
||||
.vc-settings-modal-favorite-button:hover {
|
||||
color: var(--yellow-300);
|
||||
}
|
||||
|
||||
.vc-settings-modal-link-icon {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
border-radius: 50%;
|
||||
border: 4px solid var(--background-base-lowest);
|
||||
box-sizing: border-box
|
||||
}
|
||||
|
||||
.vc-settings-modal-favorite-icon {
|
||||
background: var(--background-base-lowest);
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.vc-settings-modal-links {
|
||||
display: flex;
|
||||
gap: 0.2em;
|
||||
margin-left: auto;
|
||||
}
|
||||
53
src/components/settings/tabs/plugins/PluginModalButtons.tsx
Normal file
53
src/components/settings/tabs/plugins/PluginModalButtons.tsx
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import "./PluginModalButtons.css";
|
||||
|
||||
import { GithubIcon, StarFilled, StarOutlined, WebsiteIcon } from "@components/Icons";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { getTheme, Theme } from "@utils/discord";
|
||||
import { Clickable, MaskedLink, Tooltip } from "@webpack/common";
|
||||
|
||||
const cl = classNameFactory("vc-settings-modal-");
|
||||
|
||||
const getThemeClass = () => getTheme() !== Theme.Light ? "dark" : "light";
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
function LinkIcon({ text, href, Icon }: Props & { Icon: React.ComponentType; }) {
|
||||
return (
|
||||
<Tooltip text={text}>
|
||||
{props =>
|
||||
<MaskedLink {...props} href={href} className={cl("link-button", getThemeClass())}>
|
||||
<Icon />
|
||||
</MaskedLink>
|
||||
}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
const GithubLinkIcon = () => <GithubIcon aria-hidden className={cl("link-icon")} />;
|
||||
const WebsiteLinkIcon = () => <WebsiteIcon aria-hidden className={cl("link-icon")} />;
|
||||
|
||||
export const GithubButton = (props: Props) => <LinkIcon {...props} Icon={GithubLinkIcon} />;
|
||||
export const WebsiteButton = (props: Props) => <LinkIcon {...props} Icon={WebsiteLinkIcon} />;
|
||||
|
||||
export function FavoriteButton({ isFavorite, onClick }: { isFavorite: boolean; onClick: () => void; }) {
|
||||
const Icon = isFavorite ? StarFilled : StarOutlined;
|
||||
|
||||
return (
|
||||
<Tooltip text={isFavorite ? "Unfavorite plugin" : "Favorite plugin - pins it to the top of the plugin list"}>
|
||||
{props =>
|
||||
<Clickable {...props} onClick={onClick} className={cl("favorite-button", isFavorite && "favorite-button-active", getThemeClass())}>
|
||||
<Icon aria-hidden className={cl("link-icon", "favorite-icon")} />
|
||||
</Clickable>
|
||||
}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
|
@ -74,6 +74,7 @@ function ReloadRequiredCard({ required }: { required: boolean; }) {
|
|||
|
||||
const enum SearchStatus {
|
||||
ALL,
|
||||
FAVORITES,
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
NEW,
|
||||
|
|
@ -160,7 +161,8 @@ function PluginSettings() {
|
|||
const sortedPlugins = useMemo(() =>
|
||||
Object.values(Plugins).sort((a, b) => a.name.localeCompare(b.name)),
|
||||
[]
|
||||
);
|
||||
)
|
||||
.toSorted((a, b) => Number(settings.plugins[b.name]?.isFavorite ?? false) - Number(settings.plugins[a.name]?.isFavorite ?? false));
|
||||
|
||||
const hasUserPlugins = useMemo(() => !IS_STANDALONE && Object.values(PluginMeta).some(m => m.userPlugin), []);
|
||||
|
||||
|
|
@ -173,6 +175,9 @@ function PluginSettings() {
|
|||
const { status, tags } = searchValue;
|
||||
|
||||
switch (status) {
|
||||
case SearchStatus.FAVORITES:
|
||||
if (!settings.plugins[plugin.name]?.isFavorite) return false;
|
||||
break;
|
||||
case SearchStatus.DISABLED:
|
||||
if (isPluginEnabled(plugin.name)) return false;
|
||||
break;
|
||||
|
|
@ -288,6 +293,7 @@ function PluginSettings() {
|
|||
<Select
|
||||
options={[
|
||||
{ label: "Show All", value: SearchStatus.ALL, default: true },
|
||||
{ label: "Show Favorites", value: SearchStatus.FAVORITES },
|
||||
{ label: "Show Enabled", value: SearchStatus.ENABLED },
|
||||
{ label: "Show Disabled", value: SearchStatus.DISABLED },
|
||||
{ label: "Show New", value: SearchStatus.NEW },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue