added QuickReactFrequents and DiscordColorways
This commit is contained in:
parent
fa99ee4093
commit
523dae7fa6
21 changed files with 5759 additions and 0 deletions
220
src/userplugins/DiscordColorways/components/ColorPicker.tsx
Normal file
220
src/userplugins/DiscordColorways/components/ColorPicker.tsx
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Flex } from "@components/Flex";
|
||||||
|
import { CopyIcon } from "@components/Icons";
|
||||||
|
import {
|
||||||
|
ModalProps,
|
||||||
|
ModalRoot,
|
||||||
|
} from "@utils/modal";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Clipboard,
|
||||||
|
ScrollerThin,
|
||||||
|
TextInput,
|
||||||
|
Toasts,
|
||||||
|
useState,
|
||||||
|
} from "@webpack/common";
|
||||||
|
|
||||||
|
import { colorVariables } from "../css";
|
||||||
|
|
||||||
|
interface ToolboxItem {
|
||||||
|
title: string;
|
||||||
|
onClick: () => void;
|
||||||
|
id?: string;
|
||||||
|
iconClassName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ColorVarItems: ToolboxItem[] = colorVariables.map((colorVariable: string) => {
|
||||||
|
return {
|
||||||
|
title: "Copy " + colorVariable,
|
||||||
|
onClick: () => {
|
||||||
|
function getHex(str: string): string { return Object.assign(document.createElement("canvas").getContext("2d") as {}, { fillStyle: str }).fillStyle; }
|
||||||
|
Clipboard.copy(getHex(getComputedStyle(document.body).getPropertyValue("--" + colorVariable)));
|
||||||
|
Toasts.show({ message: "Color " + colorVariable + " copied to clipboard", id: "toolbox-color-var-copied", type: 1 });
|
||||||
|
},
|
||||||
|
id: colorVariable
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const ToolboxItems: ToolboxItem[] = [
|
||||||
|
{
|
||||||
|
title: "Copy Accent Color",
|
||||||
|
onClick: () => {
|
||||||
|
function getHex(str: string): string {
|
||||||
|
return Object.assign(
|
||||||
|
document.createElement("canvas").getContext("2d") as {},
|
||||||
|
{ fillStyle: str }
|
||||||
|
).fillStyle;
|
||||||
|
}
|
||||||
|
Clipboard.copy(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(document.body).getPropertyValue(
|
||||||
|
"--brand-experiment"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Toasts.show({
|
||||||
|
message: "Accent color copied to clipboard",
|
||||||
|
id: "toolbox-accent-color-copied",
|
||||||
|
type: 1,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
id: "colorways-toolbox_copy-accent",
|
||||||
|
iconClassName: "copy",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Copy Primary Color",
|
||||||
|
onClick: () => {
|
||||||
|
function getHex(str: string): string {
|
||||||
|
return Object.assign(
|
||||||
|
document.createElement("canvas").getContext("2d") as {},
|
||||||
|
{ fillStyle: str }
|
||||||
|
).fillStyle;
|
||||||
|
}
|
||||||
|
Clipboard.copy(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(document.body).getPropertyValue(
|
||||||
|
"--background-primary"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Toasts.show({
|
||||||
|
message: "Primary color copied to clipboard",
|
||||||
|
id: "toolbox-primary-color-copied",
|
||||||
|
type: 1,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
id: "colorways-toolbox_copy-primary",
|
||||||
|
iconClassName: "copy",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Copy Secondary Color",
|
||||||
|
onClick: () => {
|
||||||
|
function getHex(str: string): string {
|
||||||
|
return Object.assign(
|
||||||
|
document.createElement("canvas").getContext("2d") as {},
|
||||||
|
{ fillStyle: str }
|
||||||
|
).fillStyle;
|
||||||
|
}
|
||||||
|
Clipboard.copy(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(document.body).getPropertyValue(
|
||||||
|
"--background-secondary"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Toasts.show({
|
||||||
|
message: "Secondary color copied to clipboard",
|
||||||
|
id: "toolbox-secondary-color-copied",
|
||||||
|
type: 1,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
id: "colorways-toolbox_copy-secondary",
|
||||||
|
iconClassName: "copy",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Copy Tertiary Color",
|
||||||
|
onClick: () => {
|
||||||
|
function getHex(str: string): string {
|
||||||
|
return Object.assign(
|
||||||
|
document.createElement("canvas").getContext("2d") as {},
|
||||||
|
{ fillStyle: str }
|
||||||
|
).fillStyle;
|
||||||
|
}
|
||||||
|
Clipboard.copy(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(document.body).getPropertyValue(
|
||||||
|
"--background-tertiary"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Toasts.show({
|
||||||
|
message: "Tertiary color copied to clipboard",
|
||||||
|
id: "toolbox-tertiary-color-copied",
|
||||||
|
type: 1,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
id: "colorways-toolbox_copy-tertiary",
|
||||||
|
iconClassName: "copy",
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function ({ modalProps }: { modalProps: ModalProps; }) {
|
||||||
|
const [colorVarItems, setColorVarItems] = useState<ToolboxItem[]>(ColorVarItems);
|
||||||
|
const [collapsedSettings, setCollapsedSettings] = useState<boolean>(true);
|
||||||
|
let results: ToolboxItem[];
|
||||||
|
function searchToolboxItems(e: string) {
|
||||||
|
results = [];
|
||||||
|
ColorVarItems.find((ToolboxItem: ToolboxItem) => {
|
||||||
|
if (ToolboxItem.title.toLowerCase().includes(e.toLowerCase())) {
|
||||||
|
results.push(ToolboxItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setColorVarItems(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalRoot {...modalProps} className="colorwayColorpicker">
|
||||||
|
<Flex style={{ gap: "8px", marginBottom: "8px" }}>
|
||||||
|
<TextInput
|
||||||
|
className="colorwaysColorpicker-search"
|
||||||
|
placeholder="Search for a color:"
|
||||||
|
onChange={e => {
|
||||||
|
searchToolboxItems(e);
|
||||||
|
if (e) {
|
||||||
|
setCollapsedSettings(false);
|
||||||
|
} else {
|
||||||
|
setCollapsedSettings(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.TRANSPARENT}
|
||||||
|
onClick={() => setCollapsedSettings(!collapsedSettings)}
|
||||||
|
>
|
||||||
|
<svg width="32" height="24" viewBox="0 0 24 24" aria-hidden="true" role="img">
|
||||||
|
<path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10" aria-hidden="true" />
|
||||||
|
</svg>
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
<ScrollerThin style={{ color: "var(--text-normal)" }} orientation="vertical" className={collapsedSettings ? " colorwaysColorpicker-collapsed" : ""} paddingFix>
|
||||||
|
{colorVarItems.map((toolboxItem: ToolboxItem) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id={
|
||||||
|
"colorways-colorstealer-item_" +
|
||||||
|
toolboxItem.id
|
||||||
|
}
|
||||||
|
className="colorwaysCreator-settingItm colorwaysCreator-toolboxItm"
|
||||||
|
onClick={toolboxItem.onClick}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--brand-experiment":
|
||||||
|
"var(--" + toolboxItem.id + ")",
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{toolboxItem.title}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ScrollerThin>
|
||||||
|
<Flex style={{ justifyContent: "space-between", marginTop: "8px" }} wrap="wrap" className={collapsedSettings ? "" : " colorwaysColorpicker-collapsed"}>
|
||||||
|
{ToolboxItems.map((toolboxItem: ToolboxItem, i: number) => <div
|
||||||
|
id={toolboxItem.id || `colorways-toolbox_item-${i}`}
|
||||||
|
className="colorwayToolbox-listItem"
|
||||||
|
>
|
||||||
|
<CopyIcon onClick={toolboxItem.onClick} width={20} height={20} className="colorwayToolbox-listItemSVG" />
|
||||||
|
<span className="colorwaysToolbox-label">{toolboxItem.title}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</ModalRoot>
|
||||||
|
);
|
||||||
|
}
|
108
src/userplugins/DiscordColorways/components/ColorwaysButton.tsx
Normal file
108
src/userplugins/DiscordColorways/components/ColorwaysButton.tsx
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import { openModal } from "@utils/modal";
|
||||||
|
import { FluxDispatcher, Text, Tooltip, useCallback, useEffect, useState } from "@webpack/common";
|
||||||
|
import { FluxEvents } from "@webpack/types";
|
||||||
|
|
||||||
|
import { PalleteIcon } from "./Icons";
|
||||||
|
import SelectorModal from "./SelectorModal";
|
||||||
|
|
||||||
|
export default function ({
|
||||||
|
listItemClass = "ColorwaySelectorBtnContainer",
|
||||||
|
listItemWrapperClass = "",
|
||||||
|
listItemTooltipClass = "colorwaysBtn-tooltipContent"
|
||||||
|
}: {
|
||||||
|
listItemClass?: string;
|
||||||
|
listItemWrapperClass?: string;
|
||||||
|
listItemTooltipClass?: string;
|
||||||
|
}) {
|
||||||
|
const [activeColorway, setActiveColorway] = useState<string>("None");
|
||||||
|
const [visibility, setVisibility] = useState<boolean>(true);
|
||||||
|
const [isThin, setIsThin] = useState<boolean>(false);
|
||||||
|
async function setButtonVisibility() {
|
||||||
|
const [showColorwaysButton, useThinMenuButton] = await DataStore.getMany([
|
||||||
|
"showColorwaysButton",
|
||||||
|
"useThinMenuButton"
|
||||||
|
]);
|
||||||
|
|
||||||
|
setVisibility(showColorwaysButton);
|
||||||
|
setIsThin(useThinMenuButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cached_setButtonVisibility = useCallback(setButtonVisibility, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
cached_setButtonVisibility();
|
||||||
|
});
|
||||||
|
|
||||||
|
FluxDispatcher.subscribe("COLORWAYS_UPDATE_BUTTON_HEIGHT" as FluxEvents, ({ isTall }) => {
|
||||||
|
setIsThin(isTall);
|
||||||
|
});
|
||||||
|
|
||||||
|
FluxDispatcher.subscribe("COLORWAYS_UPDATE_BUTTON_VISIBILITY" as FluxEvents, ({ isVisible }) => {
|
||||||
|
setVisibility(isVisible);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isThin) {
|
||||||
|
return (<Tooltip text={<>
|
||||||
|
<span>Colorways</span>
|
||||||
|
<Text variant="text-xs/normal" style={{ color: "var(--text-muted)", fontWeight: 500 }}>{"Active Colorway: " + activeColorway}</Text>
|
||||||
|
</>} position="right" tooltipContentClassName={listItemTooltipClass}
|
||||||
|
>
|
||||||
|
{({ onMouseEnter, onMouseLeave, onClick }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{visibility && <div className={listItemClass}>
|
||||||
|
<div
|
||||||
|
className={listItemWrapperClass + " ColorwaySelectorBtn"}
|
||||||
|
onMouseEnter={async () => {
|
||||||
|
onMouseEnter();
|
||||||
|
setActiveColorway(await DataStore.get("actveColorwayID") || "None");
|
||||||
|
}}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
onClick={() => {
|
||||||
|
onClick();
|
||||||
|
openModal(props => <SelectorModal modalProps={props} />);
|
||||||
|
}}
|
||||||
|
><PalleteIcon /></div>
|
||||||
|
</div>}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (<Tooltip text={<>
|
||||||
|
<span>Colorways</span>
|
||||||
|
<Text variant="text-xs/normal" style={{ color: "var(--text-muted)", fontWeight: 500 }}>{"Active Colorway: " + activeColorway}</Text>
|
||||||
|
</>} position="right" tooltipContentClassName={listItemTooltipClass}
|
||||||
|
>
|
||||||
|
{({ onMouseEnter, onMouseLeave, onClick }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{visibility && <div className={listItemClass}>
|
||||||
|
<div
|
||||||
|
className={listItemWrapperClass + " ColorwaySelectorBtn ColorwaySelectorBtn_thin"}
|
||||||
|
onMouseEnter={async () => {
|
||||||
|
onMouseEnter();
|
||||||
|
setActiveColorway(await DataStore.get("actveColorwayID") || "None");
|
||||||
|
}}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
onClick={() => {
|
||||||
|
onClick();
|
||||||
|
openModal(props => <SelectorModal modalProps={props} />);
|
||||||
|
}}
|
||||||
|
><Text variant="text-xs/normal" style={{ color: "var(--header-primary)", fontWeight: 700, fontSize: 9 }}>Colorways</Text></div>
|
||||||
|
</div>}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,318 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot } from "@utils/modal";
|
||||||
|
import { Button, Forms, ScrollerThin, Text, useState } from "@webpack/common";
|
||||||
|
|
||||||
|
import { knownThemeVars } from "../constants";
|
||||||
|
import { getFontOnBg, getHex } from "../utils";
|
||||||
|
|
||||||
|
export default function ({
|
||||||
|
modalProps,
|
||||||
|
onFinished
|
||||||
|
}: {
|
||||||
|
modalProps: ModalProps;
|
||||||
|
onFinished: ({ accent, primary, secondary, tertiary }: { accent: string, primary: string, secondary: string, tertiary: string; }) => void;
|
||||||
|
}) {
|
||||||
|
const [accentColor, setAccentColor] = useState<string>(getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--brand-experiment")
|
||||||
|
));
|
||||||
|
const [primaryColor, setPrimaryColor] = useState<string>(getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-primary")
|
||||||
|
));
|
||||||
|
const [secondaryColor, setSecondaryColor] = useState<string>(getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-secondary")
|
||||||
|
));
|
||||||
|
const [tertiaryColor, setTertiaryColor] = useState<string>(getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-tertiary")
|
||||||
|
));
|
||||||
|
return <ModalRoot {...modalProps} className="colorwayCreator-modal">
|
||||||
|
<ModalHeader>
|
||||||
|
<Text variant="heading-lg/semibold" tag="h1">
|
||||||
|
Conflicting Colors Found
|
||||||
|
</Text>
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalContent className="colorwayCreator-menuWrapper">
|
||||||
|
<Text className="colorwaysConflictingColors-warning">Multiple known themes have been found, select the colors you want to copy from below:</Text>
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>Colors to copy:</Forms.FormTitle>
|
||||||
|
<div className="colorwayCreator-colorPreviews">
|
||||||
|
<div className="colorwayCreator-colorPreview" style={{ backgroundColor: primaryColor, color: getFontOnBg(primaryColor) }} >Primary</div>
|
||||||
|
<div className="colorwayCreator-colorPreview" style={{ backgroundColor: secondaryColor, color: getFontOnBg(secondaryColor) }} >Secondary</div>
|
||||||
|
<div className="colorwayCreator-colorPreview" style={{ backgroundColor: tertiaryColor, color: getFontOnBg(tertiaryColor) }} >Tertiary</div>
|
||||||
|
<div className="colorwayCreator-colorPreview" style={{ backgroundColor: accentColor, color: getFontOnBg(accentColor) }} >Accent</div>
|
||||||
|
</div>
|
||||||
|
<div className="colorwaysCreator-settingCat">
|
||||||
|
<ScrollerThin orientation="vertical" className="colorwaysCreator-settingsList" paddingFix>
|
||||||
|
<div
|
||||||
|
id="colorways-colorstealer-item_Default"
|
||||||
|
className="colorwaysCreator-settingItm colorwaysCreator-colorPreviewItm"
|
||||||
|
>
|
||||||
|
<Forms.FormTitle>Discord</Forms.FormTitle>
|
||||||
|
<div className="colorwayCreator-colorPreviews">
|
||||||
|
<div
|
||||||
|
className="colorwayCreator-colorPreview" style={{
|
||||||
|
backgroundColor: getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-primary")
|
||||||
|
),
|
||||||
|
color: getFontOnBg(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-primary")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
onClick={() => setPrimaryColor(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-primary")
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
>Primary</div>
|
||||||
|
<div
|
||||||
|
className="colorwayCreator-colorPreview" style={{
|
||||||
|
backgroundColor: getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-secondary")
|
||||||
|
),
|
||||||
|
color: getFontOnBg(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-secondary")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
onClick={() => setSecondaryColor(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-secondary")
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
>Secondary</div>
|
||||||
|
<div
|
||||||
|
className="colorwayCreator-colorPreview" style={{
|
||||||
|
backgroundColor: getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-tertiary")
|
||||||
|
),
|
||||||
|
color: getFontOnBg(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-tertiary")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
onClick={() => setTertiaryColor(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-tertiary")
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
>Tertiary</div>
|
||||||
|
<div
|
||||||
|
className="colorwayCreator-colorPreview" style={{
|
||||||
|
backgroundColor: getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--brand-experiment")
|
||||||
|
),
|
||||||
|
color: getFontOnBg(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--brand-experiment")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
onClick={() => setAccentColor(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--brand-experiment")
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
>Accent</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{Object.values(knownThemeVars).map((theme: any, i) => {
|
||||||
|
if (getComputedStyle(document.body).getPropertyValue(theme.variable)) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id={
|
||||||
|
"colorways-colorstealer-item_" +
|
||||||
|
Object.keys(knownThemeVars)[i]
|
||||||
|
}
|
||||||
|
className="colorwaysCreator-settingItm colorwaysCreator-colorPreviewItm"
|
||||||
|
>
|
||||||
|
<Forms.FormTitle>{Object.keys(knownThemeVars)[i] + (theme.alt ? " (Main)" : "")}</Forms.FormTitle>
|
||||||
|
<div className="colorwayCreator-colorPreviews">
|
||||||
|
{theme.primary && getComputedStyle(document.body).getPropertyValue(theme.primary).match(/^\d.*%$/)
|
||||||
|
? <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_primary"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.primary)})`),
|
||||||
|
color: getFontOnBg(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.primary)})`))
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setPrimaryColor(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.primary)})`));
|
||||||
|
}}
|
||||||
|
>Primary</div>
|
||||||
|
: (
|
||||||
|
theme.primary
|
||||||
|
? <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_primary"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getHex(getComputedStyle(document.body).getPropertyValue(theme.primary)),
|
||||||
|
color: getFontOnBg(getHex(getComputedStyle(document.body).getPropertyValue(theme.primary)))
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setPrimaryColor(getHex(getComputedStyle(document.body).getPropertyValue(theme.primary)));
|
||||||
|
}}
|
||||||
|
>Primary</div>
|
||||||
|
: (theme.primaryVariables
|
||||||
|
&& <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_primary"
|
||||||
|
style={{ backgroundColor: `hsl(${getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l)})`, color: getFontOnBg(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l)})`)) }}
|
||||||
|
onClick={() => {
|
||||||
|
setPrimaryColor(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.primaryVariables.l)})`));
|
||||||
|
}}
|
||||||
|
>Primary</div>))
|
||||||
|
}
|
||||||
|
{theme.secondary && getComputedStyle(document.body).getPropertyValue(theme.secondary).match(/^\d.*%$/)
|
||||||
|
? <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_secondary"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.secondary)})`),
|
||||||
|
color: getFontOnBg(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.secondary)})`))
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setSecondaryColor(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.secondary)})`));
|
||||||
|
}}
|
||||||
|
>Secondary</div>
|
||||||
|
: (theme.secondary
|
||||||
|
? <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_secondary"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getHex(getComputedStyle(document.body).getPropertyValue(theme.secondary)),
|
||||||
|
color: getFontOnBg(getHex(getComputedStyle(document.body).getPropertyValue(theme.secondary)))
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setSecondaryColor(getHex(getComputedStyle(document.body).getPropertyValue(theme.secondary)));
|
||||||
|
}}
|
||||||
|
>Secondary</div>
|
||||||
|
: (theme.secondaryVariables
|
||||||
|
&& <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_secondary"
|
||||||
|
style={{ backgroundColor: `hsl(${getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l)})`, color: getFontOnBg(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l)})`)) }}
|
||||||
|
onClick={() => {
|
||||||
|
setSecondaryColor(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.secondaryVariables.l)})`));
|
||||||
|
}}
|
||||||
|
>Secondary</div>))
|
||||||
|
}
|
||||||
|
{theme.tertiary && getComputedStyle(document.body).getPropertyValue(theme.tertiary).match(/^\d.*%$/)
|
||||||
|
? <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_tertiary"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.tertiary)})`),
|
||||||
|
color: getFontOnBg(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.tertiary)})`))
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setTertiaryColor(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.tertiary)})`));
|
||||||
|
}}
|
||||||
|
>Tertiary</div>
|
||||||
|
: (theme.tertiary
|
||||||
|
? <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_tertiary"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getHex(getComputedStyle(document.body).getPropertyValue(theme.tertiary)),
|
||||||
|
color: getFontOnBg(getHex(getComputedStyle(document.body).getPropertyValue(theme.tertiary)))
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setTertiaryColor(getHex(getComputedStyle(document.body).getPropertyValue(theme.tertiary)));
|
||||||
|
}}
|
||||||
|
>Tertiary</div>
|
||||||
|
: (theme.tertiaryVariables
|
||||||
|
&& <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_tertiary"
|
||||||
|
style={{ backgroundColor: `hsl(${getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l)})`, color: getFontOnBg(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l)})`)) }}
|
||||||
|
onClick={() => {
|
||||||
|
setTertiaryColor(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.tertiaryVariables.l)})`));
|
||||||
|
}}
|
||||||
|
>Tertiary</div>))}
|
||||||
|
{theme.accent && getComputedStyle(document.body).getPropertyValue(theme.accent).match(/^\d.*%$/)
|
||||||
|
? <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_accent"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.accent)})`),
|
||||||
|
color: getFontOnBg(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.accent)})`))
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setAccentColor(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.accent)})`));
|
||||||
|
}}
|
||||||
|
>Accent</div>
|
||||||
|
: (theme.accent
|
||||||
|
? <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_accent"
|
||||||
|
style={{
|
||||||
|
backgroundColor: getHex(getComputedStyle(document.body).getPropertyValue(theme.accent)),
|
||||||
|
color: getFontOnBg(getHex(getComputedStyle(document.body).getPropertyValue(theme.accent)))
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setAccentColor(getHex(getComputedStyle(document.body).getPropertyValue(theme.accent)));
|
||||||
|
}}
|
||||||
|
>Accent</div>
|
||||||
|
: (theme.accentVariables
|
||||||
|
&& <div
|
||||||
|
className="colorwayCreator-colorPreview colorwayCreator-colorPreview_accent"
|
||||||
|
style={{ backgroundColor: `hsl(${getComputedStyle(document.body).getPropertyValue(theme.accentVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l)})`, color: getFontOnBg(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.accentVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l)})`)) }}
|
||||||
|
onClick={() => {
|
||||||
|
setAccentColor(getHex(`hsl(${getComputedStyle(document.body).getPropertyValue(theme.accentVariables.h)} ${!getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s) + "%") : getComputedStyle(document.body).getPropertyValue(theme.accentVariables.s)} ${!getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l).includes("%") ? (getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l) + "%") : getComputedStyle(document.body).getPropertyValue(theme.accentVariables.l)})`));
|
||||||
|
}}
|
||||||
|
>Accent</div>))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</ScrollerThin>
|
||||||
|
</div>
|
||||||
|
</ModalContent>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.BRAND}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
onFinished({
|
||||||
|
accent: accentColor,
|
||||||
|
primary: primaryColor,
|
||||||
|
secondary: secondaryColor,
|
||||||
|
tertiary: tertiaryColor
|
||||||
|
});
|
||||||
|
modalProps.onClose();
|
||||||
|
}}
|
||||||
|
>Finish</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalRoot >;
|
||||||
|
}
|
413
src/userplugins/DiscordColorways/components/CreatorModal.tsx
Normal file
413
src/userplugins/DiscordColorways/components/CreatorModal.tsx
Normal file
|
@ -0,0 +1,413 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import {
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalProps,
|
||||||
|
ModalRoot,
|
||||||
|
openModal,
|
||||||
|
} from "@utils/modal";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Forms,
|
||||||
|
ScrollerThin,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
useEffect,
|
||||||
|
UserStore,
|
||||||
|
useState,
|
||||||
|
} from "@webpack/common";
|
||||||
|
|
||||||
|
import { ColorPicker } from "..";
|
||||||
|
import { knownThemeVars } from "../constants";
|
||||||
|
import { generateCss, getPreset } from "../css";
|
||||||
|
import { Colorway } from "../types";
|
||||||
|
import { getHex, hexToString, hslToHex, rgbToHex } from "../utils";
|
||||||
|
import ConflictingColorsModal from "./ConflictingColorsModal";
|
||||||
|
import ThemePreviewCategory from "./ThemePreview";
|
||||||
|
export default function ({
|
||||||
|
modalProps,
|
||||||
|
loadUIProps,
|
||||||
|
colorwayID
|
||||||
|
}: {
|
||||||
|
modalProps: ModalProps;
|
||||||
|
loadUIProps?: () => Promise<void>;
|
||||||
|
colorwayID?: string;
|
||||||
|
}) {
|
||||||
|
const [accentColor, setAccentColor] = useState<string>("5865f2");
|
||||||
|
const [primaryColor, setPrimaryColor] = useState<string>("313338");
|
||||||
|
const [secondaryColor, setSecondaryColor] = useState<string>("2b2d31");
|
||||||
|
const [tertiaryColor, setTertiaryColor] = useState<string>("1e1f22");
|
||||||
|
const [colorwayName, setColorwayName] = useState<string>("");
|
||||||
|
const [tintedText, setTintedText] = useState<boolean>(true);
|
||||||
|
const [discordSaturation, setDiscordSaturation] = useState<boolean>(true);
|
||||||
|
const [collapsedSettings, setCollapsedSettings] = useState<boolean>(true);
|
||||||
|
const [collapsedPresets, setCollapsedPresets] = useState<boolean>(true);
|
||||||
|
const [preset, setPreset] = useState<string>("default");
|
||||||
|
const [presetColorArray, setPresetColorArray] = useState<string[]>(["accent", "primary", "secondary", "tertiary"]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const parsedID = colorwayID?.split("colorway:")[1];
|
||||||
|
if (parsedID) {
|
||||||
|
const allEqual = (arr: any[]) => arr.every(v => v === arr[0]);
|
||||||
|
if (!parsedID) {
|
||||||
|
throw new Error("Please enter a Colorway ID");
|
||||||
|
} else if (parsedID.length < 62) {
|
||||||
|
throw new Error("Invalid Colorway ID");
|
||||||
|
} else if (!hexToString(parsedID).includes(",")) {
|
||||||
|
throw new Error("Invalid Colorway ID");
|
||||||
|
} else if (!allEqual(hexToString(parsedID).split(",").map((e: string) => e.match("#")!.length)) && hexToString(parsedID).split(",").map((e: string) => e.match("#")!.length)[0] !== 1) {
|
||||||
|
throw new Error("Invalid Colorway ID");
|
||||||
|
} else {
|
||||||
|
const colorArray: string[] = hexToString(parsedID).split(",");
|
||||||
|
setAccentColor(colorArray[0].split("#")[1]);
|
||||||
|
setPrimaryColor(colorArray[1].split("#")[1]);
|
||||||
|
setSecondaryColor(colorArray[2].split("#")[1]);
|
||||||
|
setTertiaryColor(colorArray[3].split("#")[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const colorPickerProps = {
|
||||||
|
suggestedColors: [
|
||||||
|
"#313338",
|
||||||
|
"#2b2d31",
|
||||||
|
"#1e1f22",
|
||||||
|
"#5865f2",
|
||||||
|
],
|
||||||
|
showEyeDropper: true
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalRoot {...modalProps} className="colorwayCreator-modal">
|
||||||
|
<ModalHeader>
|
||||||
|
<Text variant="heading-lg/semibold" tag="h1">
|
||||||
|
Create Colorway
|
||||||
|
</Text>
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalContent className="colorwayCreator-menuWrapper">
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||||
|
Name:
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<TextInput
|
||||||
|
placeholder="Give your Colorway a name"
|
||||||
|
value={colorwayName}
|
||||||
|
onChange={setColorwayName}
|
||||||
|
/>
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||||
|
Colors:
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<div className="colorwayCreator-colorPreviews">
|
||||||
|
{presetColorArray.includes("primary") &&
|
||||||
|
<ColorPicker
|
||||||
|
label={<Text className="colorwaysPicker-colorLabel">Primary</Text>}
|
||||||
|
color={parseInt(primaryColor, 16)}
|
||||||
|
onChange={(color: number) => {
|
||||||
|
let hexColor = color.toString(16);
|
||||||
|
while (hexColor.length < 6) {
|
||||||
|
hexColor = "0" + hexColor;
|
||||||
|
}
|
||||||
|
setPrimaryColor(hexColor);
|
||||||
|
}}
|
||||||
|
{...colorPickerProps}
|
||||||
|
/>}
|
||||||
|
{presetColorArray.includes("secondary") &&
|
||||||
|
<ColorPicker
|
||||||
|
label={<Text className="colorwaysPicker-colorLabel">Secondary</Text>}
|
||||||
|
color={parseInt(secondaryColor, 16)}
|
||||||
|
onChange={(color: number) => {
|
||||||
|
let hexColor = color.toString(16);
|
||||||
|
while (hexColor.length < 6) {
|
||||||
|
hexColor = "0" + hexColor;
|
||||||
|
}
|
||||||
|
setSecondaryColor(hexColor);
|
||||||
|
}}
|
||||||
|
{...colorPickerProps}
|
||||||
|
/>}
|
||||||
|
{presetColorArray.includes("tertiary") &&
|
||||||
|
<ColorPicker
|
||||||
|
label={<Text className="colorwaysPicker-colorLabel">Tertiary</Text>}
|
||||||
|
color={parseInt(tertiaryColor, 16)}
|
||||||
|
onChange={(color: number) => {
|
||||||
|
let hexColor = color.toString(16);
|
||||||
|
while (hexColor.length < 6) {
|
||||||
|
hexColor = "0" + hexColor;
|
||||||
|
}
|
||||||
|
setTertiaryColor(hexColor);
|
||||||
|
}}
|
||||||
|
{...colorPickerProps}
|
||||||
|
/>}
|
||||||
|
{presetColorArray.includes("accent") &&
|
||||||
|
<ColorPicker
|
||||||
|
label={<Text className="colorwaysPicker-colorLabel">Accent</Text>}
|
||||||
|
color={parseInt(accentColor, 16)}
|
||||||
|
onChange={(color: number) => {
|
||||||
|
let hexColor = color.toString(16);
|
||||||
|
while (hexColor.length < 6) {
|
||||||
|
hexColor = "0" + hexColor;
|
||||||
|
}
|
||||||
|
setAccentColor(hexColor);
|
||||||
|
}}
|
||||||
|
{...colorPickerProps}
|
||||||
|
/>}
|
||||||
|
</div>
|
||||||
|
<div className={`colorwaysCreator-settingCat${collapsedSettings ? " colorwaysCreator-settingCat-collapsed" : ""}`}>
|
||||||
|
<div
|
||||||
|
className="colorwaysCreator-settingItm colorwaysCreator-settingHeader"
|
||||||
|
onClick={() => setCollapsedSettings(!collapsedSettings)}>
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>Settings</Forms.FormTitle>
|
||||||
|
<svg className="expand-3Nh1P5 transition-30IQBn directionDown-2w0MZz" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" role="img">
|
||||||
|
<path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10" aria-hidden="true" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<ScrollerThin orientation="vertical" className="colorwaysCreator-settingsList" paddingFix>
|
||||||
|
<div className="colorwaysCreator-settingItm" onClick={() => setTintedText(!tintedText)}>
|
||||||
|
<Text variant="eyebrow" tag="h5">Use colored text</Text>
|
||||||
|
<Switch value={tintedText} onChange={setTintedText} hideBorder={true} style={{ marginBottom: 0 }} />
|
||||||
|
</div>
|
||||||
|
<div className="colorwaysCreator-settingItm" onClick={() => setDiscordSaturation(!discordSaturation)}>
|
||||||
|
<Text variant="eyebrow" tag="h5">Use Discord's saturation</Text>
|
||||||
|
<Switch value={discordSaturation} onChange={setDiscordSaturation} hideBorder={true} style={{ marginBottom: 0 }} />
|
||||||
|
</div>
|
||||||
|
</ScrollerThin>
|
||||||
|
</div>
|
||||||
|
<div className={`colorwaysCreator-settingCat${collapsedPresets ? " colorwaysCreator-settingCat-collapsed" : ""}`}>
|
||||||
|
<div
|
||||||
|
className="colorwaysCreator-settingItm colorwaysCreator-settingHeader"
|
||||||
|
onClick={() => setCollapsedPresets(!collapsedPresets)}>
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>Presets</Forms.FormTitle>
|
||||||
|
<svg className="expand-3Nh1P5 transition-30IQBn directionDown-2w0MZz" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" role="img">
|
||||||
|
<path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10" aria-hidden="true" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<ScrollerThin orientation="vertical" className="colorwaysCreator-settingsList">
|
||||||
|
<div className="colorwaysCreator-settingItm colorwaysCreator-preset" onClick={() => {
|
||||||
|
setPreset("default");
|
||||||
|
setPresetColorArray(["primary", "secondary", "tertiary", "accent"]);
|
||||||
|
}}>
|
||||||
|
<svg aria-hidden="true" role="img" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill="currentColor" />
|
||||||
|
{preset === "default" && <circle cx="12" cy="12" r="5" className="radioIconForeground-3wH3aU" fill="currentColor" />}
|
||||||
|
</svg>
|
||||||
|
<Text variant="eyebrow" tag="h5">Default</Text>
|
||||||
|
</div>
|
||||||
|
{Object.values(getPreset()).map(pre => {
|
||||||
|
return <div className="colorwaysCreator-settingItm colorwaysCreator-preset" onClick={() => {
|
||||||
|
setPreset(pre.id);
|
||||||
|
setPresetColorArray(pre.colors);
|
||||||
|
}}>
|
||||||
|
<svg aria-hidden="true" role="img" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill="currentColor" />
|
||||||
|
{preset === pre.id && <circle cx="12" cy="12" r="5" className="radioIconForeground-3wH3aU" fill="currentColor" />}
|
||||||
|
</svg>
|
||||||
|
<Text variant="eyebrow" tag="h5">{pre.name}</Text>
|
||||||
|
</div>;
|
||||||
|
})}
|
||||||
|
</ScrollerThin>
|
||||||
|
</div>
|
||||||
|
<ThemePreviewCategory isCollapsed={false} accent={"#" + accentColor} primary={"#" + primaryColor} secondary={"#" + secondaryColor} tertiary={"#" + tertiaryColor} />
|
||||||
|
</ModalContent>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.BRAND}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={e => {
|
||||||
|
var customColorwayCSS: string = "";
|
||||||
|
if (preset === "default") {
|
||||||
|
customColorwayCSS = generateCss(
|
||||||
|
primaryColor,
|
||||||
|
secondaryColor,
|
||||||
|
tertiaryColor,
|
||||||
|
accentColor,
|
||||||
|
tintedText,
|
||||||
|
discordSaturation
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
customColorwayCSS = getPreset(
|
||||||
|
primaryColor,
|
||||||
|
secondaryColor,
|
||||||
|
tertiaryColor,
|
||||||
|
accentColor
|
||||||
|
)[preset].preset(discordSaturation);
|
||||||
|
}
|
||||||
|
const customColorway: Colorway = {
|
||||||
|
name: (colorwayName || "Colorway") + (preset === "default" ? "" : ": Made for " + getPreset()[preset].name),
|
||||||
|
"dc-import": customColorwayCSS,
|
||||||
|
accent: "#" + accentColor,
|
||||||
|
primary: "#" + primaryColor,
|
||||||
|
secondary: "#" + secondaryColor,
|
||||||
|
tertiary: "#" + tertiaryColor,
|
||||||
|
colors: presetColorArray,
|
||||||
|
author: UserStore.getCurrentUser().username,
|
||||||
|
authorID: UserStore.getCurrentUser().id,
|
||||||
|
};
|
||||||
|
const customColorwaysArray: Colorway[] = [customColorway];
|
||||||
|
DataStore.get("customColorways").then(
|
||||||
|
customColorways => {
|
||||||
|
customColorways.forEach(
|
||||||
|
(color: Colorway, i: number) => {
|
||||||
|
if (color.name !== customColorway.name) {
|
||||||
|
customColorwaysArray.push(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
DataStore.set("customColorways", customColorwaysArray);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
modalProps.onClose();
|
||||||
|
loadUIProps!();
|
||||||
|
}}
|
||||||
|
>Finish</Button>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
function setAllColors({ accent, primary, secondary, tertiary }: { accent: string, primary: string, secondary: string, tertiary: string; }) {
|
||||||
|
setAccentColor(accent.split("#")[1]);
|
||||||
|
setPrimaryColor(primary.split("#")[1]);
|
||||||
|
setSecondaryColor(secondary.split("#")[1]);
|
||||||
|
setTertiaryColor(tertiary.split("#")[1]);
|
||||||
|
}
|
||||||
|
var copiedThemes = ["Discord"];
|
||||||
|
Object.values(knownThemeVars).map((theme: { variable: string; variableType?: string; }, i: number) => {
|
||||||
|
if (getComputedStyle(document.body).getPropertyValue(theme.variable)) {
|
||||||
|
copiedThemes.push(Object.keys(knownThemeVars)[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (copiedThemes.length > 1) {
|
||||||
|
openModal(props => <ConflictingColorsModal modalProps={props} onFinished={setAllColors} />);
|
||||||
|
} else {
|
||||||
|
setPrimaryColor(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-primary")
|
||||||
|
).split("#")[1]
|
||||||
|
);
|
||||||
|
setSecondaryColor(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-secondary")
|
||||||
|
).split("#")[1]
|
||||||
|
);
|
||||||
|
setTertiaryColor(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--background-tertiary")
|
||||||
|
).split("#")[1]
|
||||||
|
);
|
||||||
|
setAccentColor(
|
||||||
|
getHex(
|
||||||
|
getComputedStyle(
|
||||||
|
document.body
|
||||||
|
).getPropertyValue("--brand-experiment")
|
||||||
|
).split("#")[1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Copy Current Colors
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
let colorwayID: string;
|
||||||
|
function setColorwayID(e: string) {
|
||||||
|
colorwayID = e;
|
||||||
|
}
|
||||||
|
openModal(props => {
|
||||||
|
return (
|
||||||
|
<ModalRoot {...props} className="colorwaysCreator-noMinHeight">
|
||||||
|
<ModalContent className="colorwaysCreator-noHeader colorwaysCreator-noMinHeight">
|
||||||
|
<Forms.FormTitle>Colorway ID:</Forms.FormTitle>
|
||||||
|
<TextInput placeholder="Enter Colorway ID" onInput={e => setColorwayID(e.currentTarget.value)} />
|
||||||
|
</ModalContent>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.BRAND}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
if (!colorwayID) {
|
||||||
|
throw new Error("Please enter a Colorway ID");
|
||||||
|
} else if (!hexToString(colorwayID).includes(",")) {
|
||||||
|
throw new Error("Invalid Colorway ID");
|
||||||
|
} else {
|
||||||
|
const setColor = [
|
||||||
|
setAccentColor,
|
||||||
|
setPrimaryColor,
|
||||||
|
setSecondaryColor,
|
||||||
|
setTertiaryColor
|
||||||
|
];
|
||||||
|
hexToString(colorwayID).split(/,#/).forEach((color: string, i: number) => {
|
||||||
|
var colorType = "hex";
|
||||||
|
if (color.includes("hsl")) {
|
||||||
|
colorType = "hsl";
|
||||||
|
} else if (color.includes("rgb")) {
|
||||||
|
colorType = "rgb";
|
||||||
|
}
|
||||||
|
color = color.replaceAll(",", "").replace(/.+?\(/, "").replace(")", "").replaceAll(/[ \t]+\/[ \t]+/g, " ").replaceAll("%", "");
|
||||||
|
if (colorType === "hsl") {
|
||||||
|
color = hslToHex(Number(color.split(" ")[0]), Number(color.split(" ")[1]), Number(color.split(" ")[2]));
|
||||||
|
}
|
||||||
|
if (colorType === "rgb") {
|
||||||
|
color = rgbToHex(Number(color.split(" ")[0]), Number(color.split(" ")[1]), Number(color.split(" ")[2]));
|
||||||
|
}
|
||||||
|
setColor[i](color.replace("#", ""));
|
||||||
|
});
|
||||||
|
props.onClose();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Finish
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
props.onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalRoot>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Enter Colorway ID
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
modalProps.onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalRoot>
|
||||||
|
);
|
||||||
|
}
|
15
src/userplugins/DiscordColorways/components/Divider.tsx
Normal file
15
src/userplugins/DiscordColorways/components/Divider.tsx
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return <div style={{
|
||||||
|
width: "100%",
|
||||||
|
height: 1,
|
||||||
|
borderTop: "thin solid var(--background-modifier-accent)",
|
||||||
|
marginTop: "var(--custom-margin-margin-medium)",
|
||||||
|
marginBottom: 20
|
||||||
|
}} />;
|
||||||
|
};
|
62
src/userplugins/DiscordColorways/components/Icons.tsx
Normal file
62
src/userplugins/DiscordColorways/components/Icons.tsx
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { classes } from "@utils/misc";
|
||||||
|
import type { PropsWithChildren, SVGProps } from "react";
|
||||||
|
|
||||||
|
interface BaseIconProps extends IconProps {
|
||||||
|
viewBox: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IconProps extends SVGProps<SVGSVGElement> {
|
||||||
|
className?: string;
|
||||||
|
height?: string | number;
|
||||||
|
width?: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Icon({ height = 24, width = 24, className, children, viewBox, ...svgProps }: PropsWithChildren<BaseIconProps>) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
className={classes(className, "vc-icon")}
|
||||||
|
role="img"
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
{...svgProps}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PalleteIcon(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
{...props}
|
||||||
|
className={classes(props.className, "vc-pallete-icon")}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M 12 7.5 C 13.242188 7.5 14.25 6.492188 14.25 5.25 C 14.25 4.007812 13.242188 3 12 3 C 10.757812 3 9.75 4.007812 9.75 5.25 C 9.75 6.492188 10.757812 7.5 12 7.5 Z M 18 12 C 19.242188 12 20.25 10.992188 20.25 9.75 C 20.25 8.507812 19.242188 7.5 18 7.5 C 16.757812 7.5 15.75 8.507812 15.75 9.75 C 15.75 10.992188 16.757812 12 18 12 Z M 8.25 10.5 C 8.25 11.742188 7.242188 12.75 6 12.75 C 4.757812 12.75 3.75 11.742188 3.75 10.5 C 3.75 9.257812 4.757812 8.25 6 8.25 C 7.242188 8.25 8.25 9.257812 8.25 10.5 Z M 9 19.5 C 10.242188 19.5 11.25 18.492188 11.25 17.25 C 11.25 16.007812 10.242188 15 9 15 C 7.757812 15 6.75 16.007812 6.75 17.25 C 6.75 18.492188 7.757812 19.5 9 19.5 Z M 9 19.5 M 24 12 C 24 16.726562 21.199219 15.878906 18.648438 15.105469 C 17.128906 14.644531 15.699219 14.210938 15 15 C 14.09375 16.023438 14.289062 17.726562 14.472656 19.378906 C 14.738281 21.742188 14.992188 24 12 24 C 5.371094 24 0 18.628906 0 12 C 0 5.371094 5.371094 0 12 0 C 18.628906 0 24 5.371094 24 12 Z M 12 22.5 C 12.917969 22.5 12.980469 22.242188 12.984375 22.234375 C 13.097656 22.015625 13.167969 21.539062 13.085938 20.558594 C 13.066406 20.304688 13.03125 20.003906 12.996094 19.671875 C 12.917969 18.976562 12.828125 18.164062 12.820312 17.476562 C 12.804688 16.417969 12.945312 15.0625 13.875 14.007812 C 14.429688 13.382812 15.140625 13.140625 15.78125 13.078125 C 16.390625 13.023438 17 13.117188 17.523438 13.234375 C 18.039062 13.351562 18.574219 13.515625 19.058594 13.660156 L 19.101562 13.675781 C 19.621094 13.832031 20.089844 13.972656 20.53125 14.074219 C 21.511719 14.296875 21.886719 14.199219 22.019531 14.109375 C 22.074219 14.070312 22.5 13.742188 22.5 12 C 22.5 6.199219 17.800781 1.5 12 1.5 C 6.199219 1.5 1.5 6.199219 1.5 12 C 1.5 17.800781 6.199219 22.5 12 22.5 Z M 12 22.5"
|
||||||
|
/></Icon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CloseIcon(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
{...props}
|
||||||
|
className={classes(props.className, "vc-close-icon")}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M18.4 4L12 10.4L5.6 4L4 5.6L10.4 12L4 18.4L5.6 20L12 13.6L18.4 20L20 18.4L13.6 12L20 5.6L18.4 4Z"
|
||||||
|
/>
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
}
|
275
src/userplugins/DiscordColorways/components/InfoModal.tsx
Normal file
275
src/userplugins/DiscordColorways/components/InfoModal.tsx
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import { openUserProfile } from "@utils/discord";
|
||||||
|
import {
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalProps,
|
||||||
|
ModalRoot,
|
||||||
|
} from "@utils/modal";
|
||||||
|
import { Button, Clipboard, Forms, Text, Toasts } from "@webpack/common";
|
||||||
|
|
||||||
|
import { ColorwayCSS } from "..";
|
||||||
|
import { generateCss } from "../css";
|
||||||
|
import { Colorway } from "../types";
|
||||||
|
import ThemePreviewCategory from "./ThemePreview";
|
||||||
|
|
||||||
|
export default function ({
|
||||||
|
modalProps,
|
||||||
|
colorwayProps,
|
||||||
|
discrimProps = false,
|
||||||
|
loadUIProps
|
||||||
|
}: {
|
||||||
|
modalProps: ModalProps;
|
||||||
|
colorwayProps: Colorway;
|
||||||
|
discrimProps?: boolean;
|
||||||
|
loadUIProps: () => Promise<void>;
|
||||||
|
}) {
|
||||||
|
const colors: string[] = colorwayProps.colors || [
|
||||||
|
"accent",
|
||||||
|
"primary",
|
||||||
|
"secondary",
|
||||||
|
"tertiary",
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<ModalRoot {...modalProps} className="colorwayCreator-modal">
|
||||||
|
<ModalHeader>
|
||||||
|
<Text variant="heading-lg/semibold" tag="h1">
|
||||||
|
Colorway Details: {colorwayProps.name}
|
||||||
|
</Text>
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalContent>
|
||||||
|
<div className="colorwayInfo-wrapper">
|
||||||
|
<div className="colorwayInfo-colorSwatches">
|
||||||
|
{colors.map(color => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="colorwayInfo-colorSwatch"
|
||||||
|
style={{
|
||||||
|
backgroundColor: colorwayProps[color],
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
Clipboard.copy(colorwayProps[color]);
|
||||||
|
Toasts.show({
|
||||||
|
message:
|
||||||
|
"Copied color successfully",
|
||||||
|
type: 1,
|
||||||
|
id: "copy-colorway-color-notify",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="colorwayInfo-row colorwayInfo-author">
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||||
|
Author:
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<Button
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
openUserProfile(colorwayProps.authorID);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{colorwayProps.author}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="colorwayInfo-row colorwayInfo-css">
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||||
|
CSS:
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<Text
|
||||||
|
variant="code"
|
||||||
|
selectable={true}
|
||||||
|
className="colorwayInfo-cssCodeblock"
|
||||||
|
>
|
||||||
|
{colorwayProps["dc-import"]}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<ThemePreviewCategory
|
||||||
|
isCollapsed={true}
|
||||||
|
className="colorwayInfo-lastCat"
|
||||||
|
accent={colorwayProps.accent}
|
||||||
|
primary={colorwayProps.primary}
|
||||||
|
secondary={colorwayProps.secondary}
|
||||||
|
tertiary={colorwayProps.tertiary}
|
||||||
|
></ThemePreviewCategory>
|
||||||
|
</div>
|
||||||
|
</ModalContent>
|
||||||
|
<ModalFooter>
|
||||||
|
{discrimProps && <Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.RED}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={async () => {
|
||||||
|
const customColorways = await DataStore.get("customColorways");
|
||||||
|
const actveColorwayID = await DataStore.get("actveColorwayID");
|
||||||
|
const customColorwaysArray: Colorway[] = [];
|
||||||
|
customColorways.map((color: Colorway, i: number) => {
|
||||||
|
if (customColorways.length > 0) {
|
||||||
|
if (color.name !== colorwayProps.name) {
|
||||||
|
customColorwaysArray.push(color);
|
||||||
|
}
|
||||||
|
if (++i === customColorways.length) {
|
||||||
|
DataStore.set("customColorways", customColorwaysArray);
|
||||||
|
}
|
||||||
|
if (actveColorwayID === colorwayProps.name) {
|
||||||
|
DataStore.set("actveColorway", null);
|
||||||
|
DataStore.set("actveColorwayID", null);
|
||||||
|
ColorwayCSS.set("");
|
||||||
|
}
|
||||||
|
modalProps.onClose();
|
||||||
|
loadUIProps();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Delete...
|
||||||
|
</Button>}
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
const stringToHex = (str: string) => {
|
||||||
|
let hex = "";
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
const charCode = str.charCodeAt(i);
|
||||||
|
const hexValue = charCode.toString(16);
|
||||||
|
|
||||||
|
// Pad with zeros to ensure two-digit representation
|
||||||
|
hex += hexValue.padStart(2, "0");
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
};
|
||||||
|
const colorwayIDArray = `${colorwayProps.accent},${colorwayProps.primary},${colorwayProps.secondary},${colorwayProps.tertiary}`;
|
||||||
|
const colorwayID = stringToHex(colorwayIDArray);
|
||||||
|
Clipboard.copy(colorwayID);
|
||||||
|
Toasts.show({
|
||||||
|
message: "Copied Colorway ID Successfully",
|
||||||
|
type: 1,
|
||||||
|
id: "copy-colorway-id-notify",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Copy Colorway ID
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
Clipboard.copy(colorwayProps["dc-import"]);
|
||||||
|
Toasts.show({
|
||||||
|
message: "Copied CSS to Clipboard",
|
||||||
|
type: 1,
|
||||||
|
id: "copy-colorway-css-notify",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Copy CSS
|
||||||
|
</Button>
|
||||||
|
{discrimProps ? <Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={async () => {
|
||||||
|
const customColorways = await DataStore.get("customColorways");
|
||||||
|
const actveColorwayID = await DataStore.get("actveColorwayID");
|
||||||
|
const customColorwaysArray: Colorway[] = [];
|
||||||
|
customColorways.map((color: Colorway, i: number) => {
|
||||||
|
if (customColorways.length > 0) {
|
||||||
|
if (color.name === colorwayProps.name) {
|
||||||
|
color["dc-import"] = generateCss(color.primary.split("#")[1] || "313338", color.secondary.split("#")[1] || "2b2d31", color.tertiary.split("#")[1] || "1e1f22", color.accent.split("#")[1] || "5865f2", true, true);
|
||||||
|
customColorwaysArray.push(color);
|
||||||
|
} else {
|
||||||
|
customColorwaysArray.push(color);
|
||||||
|
}
|
||||||
|
if (++i === customColorways.length) {
|
||||||
|
DataStore.set("customColorways", customColorwaysArray);
|
||||||
|
}
|
||||||
|
if (actveColorwayID === colorwayProps.name) {
|
||||||
|
DataStore.set("actveColorway", color["dc-import"]);
|
||||||
|
DataStore.set("actveColorwayID", color.name);
|
||||||
|
ColorwayCSS.set(color["dc-import"]);
|
||||||
|
}
|
||||||
|
modalProps.onClose();
|
||||||
|
loadUIProps();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update CSS
|
||||||
|
</Button> : <Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={async () => {
|
||||||
|
const colorwaySourceFiles = await DataStore.get(
|
||||||
|
"colorwaySourceFiles"
|
||||||
|
);
|
||||||
|
const responses: Response[] = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const data = await Promise.all(
|
||||||
|
responses.map((res: Response) =>
|
||||||
|
res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; })
|
||||||
|
));
|
||||||
|
const colorways = data.flatMap(json => json.colorways);
|
||||||
|
|
||||||
|
const customColorways = await DataStore.get("customColorways");
|
||||||
|
const actveColorwayID = await DataStore.get("actveColorwayID");
|
||||||
|
const customColorwaysArray: Colorway[] = [];
|
||||||
|
colorways.map((color: Colorway, i: number) => {
|
||||||
|
if (colorways.length > 0) {
|
||||||
|
if (color.name === colorwayProps.name) {
|
||||||
|
color.name += " (Custom)";
|
||||||
|
color["dc-import"] = generateCss(color.primary.split("#")[1] || "313338", color.secondary.split("#")[1] || "2b2d31", color.tertiary.split("#")[1] || "1e1f22", color.accent.split("#")[1] || "5865f2", true, true);
|
||||||
|
customColorwaysArray.push(color);
|
||||||
|
}
|
||||||
|
if (++i === colorways.length) {
|
||||||
|
DataStore.set("customColorways", [...customColorways, ...customColorwaysArray]);
|
||||||
|
}
|
||||||
|
if (actveColorwayID === colorwayProps.name) {
|
||||||
|
DataStore.set("actveColorway", color["dc-import"]);
|
||||||
|
DataStore.set("actveColorwayID", color.name);
|
||||||
|
ColorwayCSS.set(color["dc-import"]);
|
||||||
|
}
|
||||||
|
modalProps.onClose();
|
||||||
|
loadUIProps();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update CSS (Local)
|
||||||
|
</Button>}
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => {
|
||||||
|
modalProps.onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalRoot>
|
||||||
|
);
|
||||||
|
}
|
460
src/userplugins/DiscordColorways/components/SelectorModal.tsx
Normal file
460
src/userplugins/DiscordColorways/components/SelectorModal.tsx
Normal file
|
@ -0,0 +1,460 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable arrow-parens */
|
||||||
|
|
||||||
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import { ModalContent, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Forms,
|
||||||
|
Menu,
|
||||||
|
Popout,
|
||||||
|
ScrollerThin,
|
||||||
|
Select,
|
||||||
|
SettingsRouter,
|
||||||
|
TextInput,
|
||||||
|
Tooltip,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from "@webpack/common";
|
||||||
|
|
||||||
|
import { ColorwayCSS } from "..";
|
||||||
|
import { defaultColorwaySource, fallbackColorways } from "../constants";
|
||||||
|
import { generateCss } from "../css";
|
||||||
|
import { Colorway } from "../types";
|
||||||
|
import { getHex } from "../utils";
|
||||||
|
import ColorPickerModal from "./ColorPicker";
|
||||||
|
import CreatorModal from "./CreatorModal";
|
||||||
|
import { CloseIcon } from "./Icons";
|
||||||
|
import ColorwayInfoModal from "./InfoModal";
|
||||||
|
|
||||||
|
export default function ({
|
||||||
|
modalProps,
|
||||||
|
}: {
|
||||||
|
modalProps: ModalProps;
|
||||||
|
}): JSX.Element | any {
|
||||||
|
const [currentColorway, setCurrentColorway] = useState<string>("");
|
||||||
|
const [colorways, setColorways] = useState<Colorway[]>([]);
|
||||||
|
const [thirdPartyColorways, setThirdPartyColorways] = useState<Colorway[]>([]);
|
||||||
|
const [customColorways, setCustomColorways] = useState<Colorway[]>([]);
|
||||||
|
const [searchString, setSearchString] = useState<string>("");
|
||||||
|
const [loaderHeight, setLoaderHeight] = useState<string>("2px");
|
||||||
|
const [visibility, setVisibility] = useState<string>("all");
|
||||||
|
const [showReloadMenu, setShowReloadMenu] = useState(false);
|
||||||
|
let visibleColorwayArray: Colorway[];
|
||||||
|
|
||||||
|
switch (visibility) {
|
||||||
|
case "all":
|
||||||
|
visibleColorwayArray = [...colorways, ...thirdPartyColorways, ...customColorways];
|
||||||
|
break;
|
||||||
|
case "official":
|
||||||
|
visibleColorwayArray = [...colorways];
|
||||||
|
break;
|
||||||
|
case "3rdparty":
|
||||||
|
visibleColorwayArray = [...thirdPartyColorways];
|
||||||
|
break;
|
||||||
|
case "custom":
|
||||||
|
visibleColorwayArray = [...customColorways];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
visibleColorwayArray = [...colorways, ...thirdPartyColorways, ...customColorways];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadUI() {
|
||||||
|
const colorwaySourceFiles = await DataStore.get(
|
||||||
|
"colorwaySourceFiles"
|
||||||
|
);
|
||||||
|
const responses: Response[] = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const data = await Promise.all(
|
||||||
|
responses.map((res: Response) =>
|
||||||
|
res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; })
|
||||||
|
));
|
||||||
|
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||||
|
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||||
|
const baseData = await DataStore.getMany([
|
||||||
|
"customColorways",
|
||||||
|
"actveColorwayID",
|
||||||
|
]);
|
||||||
|
setColorways(colorways || fallbackColorways);
|
||||||
|
setThirdPartyColorways(thirdPartyColorwaysArr);
|
||||||
|
setCustomColorways(baseData[0]);
|
||||||
|
setCurrentColorway(baseData[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cached_loadUI = useCallback(loadUI, [setColorways, setCustomColorways, setCurrentColorway]);
|
||||||
|
|
||||||
|
async function searchColorways(e: string) {
|
||||||
|
if (!e) {
|
||||||
|
cached_loadUI();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const colorwaySourceFiles = await DataStore.get("colorwaySourceFiles");
|
||||||
|
const data = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url).then((res) => res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||||
|
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||||
|
const baseData = await DataStore.get("customColorways");
|
||||||
|
var results: Colorway[] = [];
|
||||||
|
(colorways || fallbackColorways).find((Colorway: Colorway) => {
|
||||||
|
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||||
|
results.push(Colorway);
|
||||||
|
});
|
||||||
|
var thirdPartyResults: Colorway[] = [];
|
||||||
|
(thirdPartyColorwaysArr).find((Colorway: Colorway) => {
|
||||||
|
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||||
|
thirdPartyResults.push(Colorway);
|
||||||
|
});
|
||||||
|
var customResults: Colorway[] = [];
|
||||||
|
baseData.find((Colorway: Colorway) => {
|
||||||
|
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||||
|
customResults.push(Colorway);
|
||||||
|
});
|
||||||
|
setColorways(results);
|
||||||
|
setThirdPartyColorways(thirdPartyResults);
|
||||||
|
setCustomColorways(customResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!searchString) {
|
||||||
|
cached_loadUI();
|
||||||
|
}
|
||||||
|
setLoaderHeight("0px");
|
||||||
|
}, [searchString]);
|
||||||
|
|
||||||
|
function ReloadPopout(onClose: () => void) {
|
||||||
|
return (
|
||||||
|
<Menu.Menu
|
||||||
|
navId="dc-reload-menu"
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<Menu.MenuItem
|
||||||
|
id="dc-force-reload"
|
||||||
|
label="Force Reload"
|
||||||
|
action={async () => {
|
||||||
|
setLoaderHeight("2px");
|
||||||
|
const colorwaySourceFiles = await DataStore.get(
|
||||||
|
"colorwaySourceFiles"
|
||||||
|
);
|
||||||
|
const responses: Response[] = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url, { cache: "no-store" })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const data = await Promise.all(
|
||||||
|
responses.map((res: Response) => {
|
||||||
|
setLoaderHeight("0px");
|
||||||
|
return res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; });
|
||||||
|
}
|
||||||
|
));
|
||||||
|
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||||
|
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||||
|
const baseData = await DataStore.getMany([
|
||||||
|
"customColorways",
|
||||||
|
"actveColorwayID",
|
||||||
|
]);
|
||||||
|
setColorways(colorways || fallbackColorways);
|
||||||
|
setThirdPartyColorways(thirdPartyColorwaysArr);
|
||||||
|
setCustomColorways(baseData[0]);
|
||||||
|
setCurrentColorway(baseData[1]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Menu.Menu>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalRoot {...modalProps} className="colorwaySelectorModal">
|
||||||
|
<ModalHeader>
|
||||||
|
<Select className="colorwaySelector-pill colorwaySelector-pill_select" options={[{
|
||||||
|
value: "all",
|
||||||
|
label: "All"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "official",
|
||||||
|
label: "Official"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "3rdparty",
|
||||||
|
label: "3rd-Party"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "custom",
|
||||||
|
label: "Custom"
|
||||||
|
}]} select={value => {
|
||||||
|
setVisibility(value);
|
||||||
|
}} isSelected={value => visibility === value} serialize={String} />
|
||||||
|
<TextInput
|
||||||
|
inputClassName="colorwaySelector-searchInput"
|
||||||
|
className="colorwaySelector-search"
|
||||||
|
placeholder="Search for Colorways..."
|
||||||
|
value={searchString}
|
||||||
|
onChange={(e: string) => [searchColorways, setSearchString].forEach(t => t(e))}
|
||||||
|
/>
|
||||||
|
<Tooltip text="Refresh Colorways...">
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => {
|
||||||
|
return <Popout
|
||||||
|
position="bottom"
|
||||||
|
align="right"
|
||||||
|
animation={Popout.Animation.NONE}
|
||||||
|
shouldShow={showReloadMenu}
|
||||||
|
onRequestClose={() => setShowReloadMenu(false)}
|
||||||
|
renderPopout={() => ReloadPopout(() => setShowReloadMenu(false))}
|
||||||
|
>
|
||||||
|
{(_, { isShown }) => (
|
||||||
|
<Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
style={{ marginLeft: "8px" }}
|
||||||
|
id="colorway-refreshcolorway"
|
||||||
|
onMouseEnter={isShown ? () => { } : onMouseEnter}
|
||||||
|
onMouseLeave={isShown ? () => { } : onMouseLeave}
|
||||||
|
onClick={() => {
|
||||||
|
setLoaderHeight("2px");
|
||||||
|
cached_loadUI().then(() => setLoaderHeight("0px"));
|
||||||
|
}}
|
||||||
|
onContextMenu={() => { onMouseLeave(); setShowReloadMenu(v => !v); }}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
style={{ padding: "6px" }}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
y="0"
|
||||||
|
fill="none"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
/>
|
||||||
|
<path d="M6.351,6.351C7.824,4.871,9.828,4,12,4c4.411,0,8,3.589,8,8h2c0-5.515-4.486-10-10-10 C9.285,2,6.779,3.089,4.938,4.938L3,3v6h6L6.351,6.351z" />
|
||||||
|
<path d="M17.649,17.649C16.176,19.129,14.173,20,12,20c-4.411,0-8-3.589-8-8H2c0,5.515,4.486,10,10,10 c2.716,0,5.221-1.089,7.062-2.938L21,21v-6h-6L17.649,17.649z" />
|
||||||
|
</svg>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Popout>;
|
||||||
|
}}
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip text="Open Settings">
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
style={{ marginLeft: "8px" }}
|
||||||
|
id="colorway-opensettings"
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
onClick={() => {
|
||||||
|
SettingsRouter.open("ColorwaysSettings");
|
||||||
|
modalProps.onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
role="img"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
style={{ padding: "6px" }}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z" />
|
||||||
|
</svg>
|
||||||
|
</Button>}
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip text="Create Colorway...">
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
style={{ marginLeft: "8px" }}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
onClick={() => openModal((props) => <CreatorModal
|
||||||
|
modalProps={props}
|
||||||
|
loadUIProps={cached_loadUI}
|
||||||
|
/>)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-hidden="true"
|
||||||
|
role="img"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
style={{ padding: "6px" }}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M20 11.1111H12.8889V4H11.1111V11.1111H4V12.8889H11.1111V20H12.8889V12.8889H20V11.1111Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Button>}
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip text="Open Color Stealer">
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
style={{ marginLeft: "8px" }}
|
||||||
|
id="colorway-opencolorstealer"
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
onClick={() => openModal((props) => <ColorPickerModal modalProps={props} />)}
|
||||||
|
>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" style={{ padding: "6px" }} fill="currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M12.433 10.07C14.133 10.585 16 11.15 16 8a8 8 0 1 0-8 8c1.996 0 1.826-1.504 1.649-3.08-.124-1.101-.252-2.237.351-2.92.465-.527 1.42-.237 2.433.07zM8 5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM5 6.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm.5 6.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z" />
|
||||||
|
</svg>
|
||||||
|
</Button>}
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip text="Close">
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
id="colorwaySelector-pill_closeSelector"
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
onClick={() => modalProps.onClose()}
|
||||||
|
>
|
||||||
|
<CloseIcon style={{ padding: "6px" }} width={20} height={20} />
|
||||||
|
</Button>}
|
||||||
|
</Tooltip>
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalContent className="colorwaySelectorModalContent">
|
||||||
|
<div className="colorwaysLoader-barContainer"><div className="colorwaysLoader-bar" style={{ height: loaderHeight }} /></div>
|
||||||
|
<ScrollerThin style={{ maxHeight: "450px" }} className="ColorwaySelectorWrapper">
|
||||||
|
{visibleColorwayArray.length === 0 &&
|
||||||
|
<Forms.FormTitle
|
||||||
|
style={{
|
||||||
|
marginBottom: 0,
|
||||||
|
width: "100%",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
No colorways...
|
||||||
|
</Forms.FormTitle>
|
||||||
|
}
|
||||||
|
{["all", "official", "3rdparty", "custom"].includes(visibility) && (
|
||||||
|
visibleColorwayArray.map((color, ind) => {
|
||||||
|
var colors: Array<string> = color.colors || [
|
||||||
|
"accent",
|
||||||
|
"primary",
|
||||||
|
"secondary",
|
||||||
|
"tertiary",
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Tooltip text={color.name}>
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => <div
|
||||||
|
className={"discordColorway" + (currentColorway === color.name ? " active" : "")}
|
||||||
|
id={"colorway-" + color.name}
|
||||||
|
data-last-official={ind + 1 === colorways.length}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="colorwayInfoIconContainer"
|
||||||
|
onClick={() => openModal((props) => <ColorwayInfoModal
|
||||||
|
modalProps={props}
|
||||||
|
colorwayProps={color}
|
||||||
|
discrimProps={customColorways.includes(color)}
|
||||||
|
loadUIProps={cached_loadUI}
|
||||||
|
/>)}
|
||||||
|
>
|
||||||
|
<div className="colorwayInfoIcon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="colorwayCheckIconContainer">
|
||||||
|
<div className="colorwayCheckIcon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<circle r="8" cx="12" cy="12" fill="var(--white-500)" />
|
||||||
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<path fill="var(--brand-500)" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="discordColorwayPreviewColorContainer"
|
||||||
|
onClick={async () => {
|
||||||
|
const [
|
||||||
|
onDemandWays,
|
||||||
|
onDemandWaysTintedText,
|
||||||
|
onDemandWaysDiscordSaturation
|
||||||
|
] = await DataStore.getMany([
|
||||||
|
"onDemandWays",
|
||||||
|
"onDemandWaysTintedText",
|
||||||
|
"onDemandWaysDiscordSaturation"
|
||||||
|
]);
|
||||||
|
if (currentColorway === color.name) {
|
||||||
|
DataStore.set("actveColorwayID", null);
|
||||||
|
DataStore.set("actveColorway", null);
|
||||||
|
ColorwayCSS.remove();
|
||||||
|
} else {
|
||||||
|
DataStore.set("activeColorwayColors", color.colors);
|
||||||
|
DataStore.set("actveColorwayID", color.name);
|
||||||
|
if (onDemandWays) {
|
||||||
|
const demandedColorway = generateCss(
|
||||||
|
getHex(color.primary).split("#")[1],
|
||||||
|
getHex(color.secondary).split("#")[1],
|
||||||
|
getHex(color.tertiary).split("#")[1],
|
||||||
|
getHex(color.accent).split("#")[1],
|
||||||
|
onDemandWaysTintedText,
|
||||||
|
onDemandWaysDiscordSaturation
|
||||||
|
);
|
||||||
|
DataStore.set("actveColorway", demandedColorway);
|
||||||
|
ColorwayCSS.set(demandedColorway);
|
||||||
|
} else {
|
||||||
|
DataStore.set("actveColorway", color["dc-import"]);
|
||||||
|
ColorwayCSS.set(color["dc-import"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCurrentColorway(await DataStore.get("actveColorwayID") as string);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{colors.map((colorItm) => <div
|
||||||
|
className="discordColorwayPreviewColor"
|
||||||
|
style={{ backgroundColor: color[colorItm] }}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
</div>}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</ScrollerThin>
|
||||||
|
</ModalContent >
|
||||||
|
</ModalRoot >
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DataStore } from "@api/index";
|
||||||
|
import { Flex } from "@components/Flex";
|
||||||
|
import { SettingsTab } from "@components/VencordSettings/shared";
|
||||||
|
import { Logger } from "@utils/Logger";
|
||||||
|
import { Margins } from "@utils/margins";
|
||||||
|
import { classes } from "@utils/misc";
|
||||||
|
import { chooseFile, saveFile } from "@utils/web";
|
||||||
|
import { Button, Card, Forms, Text } from "@webpack/common";
|
||||||
|
|
||||||
|
import { defaultColorwaySource } from "../../constants";
|
||||||
|
import { generateCss } from "../../css";
|
||||||
|
import { Colorway } from "../../types";
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
return <SettingsTab title="Manage Colorways">
|
||||||
|
<Forms.FormSection title="Import/Export">
|
||||||
|
<Card className={classes("vc-settings-card", "vc-backup-restore-card")}>
|
||||||
|
<Flex flexDirection="column">
|
||||||
|
<strong>Warning</strong>
|
||||||
|
<span>Importing a colorways file will overwrite your current custom colorways.</span>
|
||||||
|
</Flex>
|
||||||
|
</Card>
|
||||||
|
<Text variant="text-md/normal" className={Margins.bottom8}>
|
||||||
|
You can import and export your custom colorways as a JSON file.
|
||||||
|
This allows you to easily transfer them to another device/installation.
|
||||||
|
</Text>
|
||||||
|
<Flex>
|
||||||
|
<Button
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
onClick={async () => {
|
||||||
|
if (IS_DISCORD_DESKTOP) {
|
||||||
|
const [file] = await DiscordNative.fileManager.openFiles({
|
||||||
|
filters: [
|
||||||
|
{ name: "Discord Colorways List", extensions: ["json"] },
|
||||||
|
{ name: "all", extensions: ["*"] }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
if (file) {
|
||||||
|
try {
|
||||||
|
await DataStore.set("customColorways", JSON.parse(new TextDecoder().decode(file.data)));
|
||||||
|
} catch (err) {
|
||||||
|
new Logger("DiscordColorways").error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const file = await chooseFile("application/json");
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = async () => {
|
||||||
|
try {
|
||||||
|
await DataStore.set("customColorways", JSON.parse(reader.result as string));
|
||||||
|
} catch (err) {
|
||||||
|
new Logger("DiscordColorways").error(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
Import Colorways
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
onClick={async () => {
|
||||||
|
if (IS_DISCORD_DESKTOP) {
|
||||||
|
DiscordNative.fileManager.saveWithDialog(JSON.stringify(await DataStore.get("customColorways") as string), "colorways.json");
|
||||||
|
} else {
|
||||||
|
saveFile(new File([JSON.stringify(await DataStore.get("customColorways") as string)], "colorways.json", { type: "application/json" }));
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
Export Colorways
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Forms.FormSection>
|
||||||
|
<Forms.FormDivider className={Margins.top8 + " " + Margins.bottom8} />
|
||||||
|
<Forms.FormSection title="Transfer 3rd Party Colorways to local index (3rd-Party > Custom):">
|
||||||
|
<Flex>
|
||||||
|
<Button
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
onClick={async () => {
|
||||||
|
const colorwaySourceFiles = await DataStore.get(
|
||||||
|
"colorwaySourceFiles"
|
||||||
|
);
|
||||||
|
const responses: Response[] = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const data = await Promise.all(
|
||||||
|
responses.map((res: Response) =>
|
||||||
|
res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; })
|
||||||
|
));
|
||||||
|
const thirdPartyColorwaysArr: Colorway[] = data.flatMap(json => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||||
|
const customColorways: Colorway[] = await DataStore.get("customColorways") as Colorway[];
|
||||||
|
DataStore.set("customColorways", [...customColorways, ...thirdPartyColorwaysArr.map(({ name: nameOld, ...rest }) => ({ name: (nameOld + " (Custom)"), ...rest }))]);
|
||||||
|
}}>
|
||||||
|
As-Is
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
onClick={async () => {
|
||||||
|
const colorwaySourceFiles = await DataStore.get(
|
||||||
|
"colorwaySourceFiles"
|
||||||
|
);
|
||||||
|
const responses: Response[] = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const data = await Promise.all(
|
||||||
|
responses.map((res: Response) =>
|
||||||
|
res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; })
|
||||||
|
));
|
||||||
|
const thirdPartyColorwaysArr: Colorway[] = data.flatMap(json => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||||
|
const customColorways: Colorway[] = await DataStore.get("customColorways") as Colorway[];
|
||||||
|
DataStore.set("customColorways", [...customColorways, ...thirdPartyColorwaysArr.map(({ name: nameOld, "dc-import": oldImport, ...rest }: Colorway) => ({ name: (nameOld + " (Custom)"), "dc-import": generateCss(rest.primary.split("#")[1] || "313338", rest.secondary.split("#")[1] || "2b2d31", rest.tertiary.split("#")[1] || "1e1f22", rest.accent.split("#")[1] || "5865f2", true, true), ...rest }))]);
|
||||||
|
}}>
|
||||||
|
With Updated CSS
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Forms.FormSection>
|
||||||
|
</SettingsTab>;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DataStore } from "@api/index";
|
||||||
|
import { SettingsTab } from "@components/VencordSettings/shared";
|
||||||
|
import { Switch, useCallback, useEffect, useState } from "@webpack/common";
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
const [onDemand, setOnDemand] = useState<boolean>(false);
|
||||||
|
const [onDemandTinted, setOnDemandTinted] = useState<boolean>(false);
|
||||||
|
const [onDemandDiscordSat, setOnDemandDiscordSat] = useState<boolean>(false);
|
||||||
|
async function loadUI() {
|
||||||
|
const [
|
||||||
|
onDemandWays,
|
||||||
|
onDemandWaysTintedText,
|
||||||
|
onDemandWaysDiscordSaturation
|
||||||
|
] = await DataStore.getMany([
|
||||||
|
"onDemandWays",
|
||||||
|
"onDemandWaysTintedText",
|
||||||
|
"onDemandWaysDiscordSaturation"
|
||||||
|
]);
|
||||||
|
setOnDemand(onDemandWays);
|
||||||
|
setOnDemandTinted(onDemandWaysTintedText);
|
||||||
|
setOnDemandDiscordSat(onDemandWaysDiscordSaturation);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cached_loadUI = useCallback(loadUI, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
cached_loadUI();
|
||||||
|
}, []);
|
||||||
|
return <SettingsTab title="On-Demand">
|
||||||
|
<Switch
|
||||||
|
value={onDemand}
|
||||||
|
onChange={(v: boolean) => {
|
||||||
|
setOnDemand(v);
|
||||||
|
DataStore.set("onDemandWays", v);
|
||||||
|
}}
|
||||||
|
note="Always utilise the latest of what DiscordColorways has to offer. CSS is being directly generated on the device and gets applied in the place of the normal import/CSS given by the colorway."
|
||||||
|
>
|
||||||
|
Enable Colorways On Demand
|
||||||
|
</Switch>
|
||||||
|
<Switch
|
||||||
|
value={onDemandTinted}
|
||||||
|
onChange={(v: boolean) => {
|
||||||
|
setOnDemandTinted(v);
|
||||||
|
DataStore.set("onDemandWaysTintedText", v);
|
||||||
|
}}
|
||||||
|
disabled={!onDemand}
|
||||||
|
>
|
||||||
|
Use tinted text
|
||||||
|
</Switch>
|
||||||
|
<Switch
|
||||||
|
hideBorder
|
||||||
|
value={onDemandDiscordSat}
|
||||||
|
onChange={(v: boolean) => {
|
||||||
|
setOnDemandDiscordSat(v);
|
||||||
|
DataStore.set("onDemandWaysDiscordSaturation", v);
|
||||||
|
}}
|
||||||
|
disabled={!onDemand}
|
||||||
|
>
|
||||||
|
Use Discord's saturation
|
||||||
|
</Switch>
|
||||||
|
</SettingsTab>;
|
||||||
|
}
|
|
@ -0,0 +1,442 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable arrow-parens */
|
||||||
|
|
||||||
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import { Flex } from "@components/Flex";
|
||||||
|
import { SettingsTab } from "@components/VencordSettings/shared";
|
||||||
|
import { openModal } from "@utils/modal";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Forms,
|
||||||
|
Menu,
|
||||||
|
Popout,
|
||||||
|
Select,
|
||||||
|
TextInput,
|
||||||
|
Tooltip,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from "@webpack/common";
|
||||||
|
|
||||||
|
import { ColorwayCSS } from "../..";
|
||||||
|
import { defaultColorwaySource, fallbackColorways } from "../../constants";
|
||||||
|
import { Colorway } from "../../types";
|
||||||
|
import ColorPickerModal from "../ColorPicker";
|
||||||
|
import CreatorModal from "../CreatorModal";
|
||||||
|
import ColorwayInfoModal from "../InfoModal";
|
||||||
|
|
||||||
|
export default function ({
|
||||||
|
visibleTabProps = "all",
|
||||||
|
}: {
|
||||||
|
visibleTabProps?: string;
|
||||||
|
}): JSX.Element | any {
|
||||||
|
const [currentColorway, setCurrentColorway] = useState<string>("");
|
||||||
|
const [colorways, setColorways] = useState<Colorway[]>([]);
|
||||||
|
const [thirdPartyColorways, setThirdPartyColorways] = useState<Colorway[]>([]);
|
||||||
|
const [customColorways, setCustomColorways] = useState<Colorway[]>([]);
|
||||||
|
const [searchString, setSearchString] = useState<string>("");
|
||||||
|
const [loaderHeight, setLoaderHeight] = useState<string>("2px");
|
||||||
|
const [visibility, setVisibility] = useState<string>(visibleTabProps);
|
||||||
|
const [showReloadMenu, setShowReloadMenu] = useState(false);
|
||||||
|
let visibleColorwayArray: Colorway[];
|
||||||
|
|
||||||
|
switch (visibility) {
|
||||||
|
case "all":
|
||||||
|
visibleColorwayArray = [...colorways, ...thirdPartyColorways, ...customColorways];
|
||||||
|
break;
|
||||||
|
case "official":
|
||||||
|
visibleColorwayArray = [...colorways];
|
||||||
|
break;
|
||||||
|
case "3rdparty":
|
||||||
|
visibleColorwayArray = [...thirdPartyColorways];
|
||||||
|
break;
|
||||||
|
case "custom":
|
||||||
|
visibleColorwayArray = [...customColorways];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
visibleColorwayArray = [...colorways, ...thirdPartyColorways, ...customColorways];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadUI() {
|
||||||
|
const colorwaySourceFiles = await DataStore.get(
|
||||||
|
"colorwaySourceFiles"
|
||||||
|
);
|
||||||
|
const responses: Response[] = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const data = await Promise.all(
|
||||||
|
responses.map((res: Response) =>
|
||||||
|
res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; })
|
||||||
|
));
|
||||||
|
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||||
|
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||||
|
const baseData = await DataStore.getMany([
|
||||||
|
"customColorways",
|
||||||
|
"actveColorwayID",
|
||||||
|
]);
|
||||||
|
setColorways(colorways || fallbackColorways);
|
||||||
|
setThirdPartyColorways(thirdPartyColorwaysArr);
|
||||||
|
setCustomColorways(baseData[0]);
|
||||||
|
setCurrentColorway(baseData[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cached_loadUI = useCallback(loadUI, [setColorways, setCustomColorways, setCurrentColorway]);
|
||||||
|
|
||||||
|
async function searchColorways(e: string) {
|
||||||
|
if (!e) {
|
||||||
|
cached_loadUI();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const colorwaySourceFiles = await DataStore.get("colorwaySourceFiles");
|
||||||
|
const data = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url).then((res) => res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||||
|
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||||
|
const baseData = await DataStore.get("customColorways");
|
||||||
|
var results: Colorway[] = [];
|
||||||
|
(colorways || fallbackColorways).find((Colorway: Colorway) => {
|
||||||
|
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||||
|
results.push(Colorway);
|
||||||
|
});
|
||||||
|
var thirdPartyResults: Colorway[] = [];
|
||||||
|
(thirdPartyColorwaysArr).find((Colorway: Colorway) => {
|
||||||
|
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||||
|
thirdPartyResults.push(Colorway);
|
||||||
|
});
|
||||||
|
var customResults: Colorway[] = [];
|
||||||
|
baseData.find((Colorway: Colorway) => {
|
||||||
|
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||||
|
customResults.push(Colorway);
|
||||||
|
});
|
||||||
|
setColorways(results);
|
||||||
|
setThirdPartyColorways(thirdPartyResults);
|
||||||
|
setCustomColorways(customResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!searchString) {
|
||||||
|
cached_loadUI();
|
||||||
|
}
|
||||||
|
setLoaderHeight("0px");
|
||||||
|
}, [searchString]);
|
||||||
|
|
||||||
|
function ReloadPopout(onClose: () => void) {
|
||||||
|
return (
|
||||||
|
<Menu.Menu
|
||||||
|
navId="dc-reload-menu"
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<Menu.MenuItem
|
||||||
|
id="dc-force-reload"
|
||||||
|
label="Force Reload"
|
||||||
|
action={async () => {
|
||||||
|
setLoaderHeight("2px");
|
||||||
|
const colorwaySourceFiles = await DataStore.get(
|
||||||
|
"colorwaySourceFiles"
|
||||||
|
);
|
||||||
|
const responses: Response[] = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url, { cache: "no-store" })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const data = await Promise.all(
|
||||||
|
responses.map((res: Response) => {
|
||||||
|
setLoaderHeight("0px");
|
||||||
|
return res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; });
|
||||||
|
}
|
||||||
|
));
|
||||||
|
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||||
|
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||||
|
const baseData = await DataStore.getMany([
|
||||||
|
"customColorways",
|
||||||
|
"actveColorwayID",
|
||||||
|
]);
|
||||||
|
setColorways(colorways || fallbackColorways);
|
||||||
|
setThirdPartyColorways(thirdPartyColorwaysArr);
|
||||||
|
setCustomColorways(baseData[0]);
|
||||||
|
setCurrentColorway(baseData[1]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Menu.Menu>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsTab title="Colors">
|
||||||
|
<div className="colorwaysSettingsSelector-wrapper">
|
||||||
|
<Flex style={{ gap: "0" }}>
|
||||||
|
<Select className="colorwaySelector-pill colorwaySelector-pill_select" options={[{
|
||||||
|
value: "all",
|
||||||
|
label: "All"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "official",
|
||||||
|
label: "Official"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "3rdparty",
|
||||||
|
label: "3rd-Party"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "custom",
|
||||||
|
label: "Custom"
|
||||||
|
}]} select={value => {
|
||||||
|
setVisibility(value);
|
||||||
|
}} isSelected={value => visibility === value} serialize={String} />
|
||||||
|
<TextInput
|
||||||
|
inputClassName="colorwaySelector-searchInput"
|
||||||
|
className="colorwaySelector-search"
|
||||||
|
placeholder="Search for Colorways..."
|
||||||
|
value={searchString}
|
||||||
|
onChange={(e: string) => [searchColorways, setSearchString].forEach(t => t(e))}
|
||||||
|
/>
|
||||||
|
<Tooltip text="Refresh Colorways...">
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => {
|
||||||
|
return <Popout
|
||||||
|
position="bottom"
|
||||||
|
align="right"
|
||||||
|
animation={Popout.Animation.NONE}
|
||||||
|
shouldShow={showReloadMenu}
|
||||||
|
onRequestClose={() => setShowReloadMenu(false)}
|
||||||
|
renderPopout={() => ReloadPopout(() => setShowReloadMenu(false))}
|
||||||
|
>
|
||||||
|
{(_, { isShown }) => (
|
||||||
|
<Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
style={{ marginLeft: "8px" }}
|
||||||
|
id="colorway-refreshcolorway"
|
||||||
|
onMouseEnter={isShown ? () => { } : onMouseEnter}
|
||||||
|
onMouseLeave={isShown ? () => { } : onMouseLeave}
|
||||||
|
onClick={() => {
|
||||||
|
setLoaderHeight("2px");
|
||||||
|
cached_loadUI().then(() => setLoaderHeight("0px"));
|
||||||
|
}}
|
||||||
|
onContextMenu={() => { onMouseLeave(); setShowReloadMenu(v => !v); }}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
style={{ padding: "6px", boxSizing: "content-box" }}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
y="0"
|
||||||
|
fill="none"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
/>
|
||||||
|
<path d="M6.351,6.351C7.824,4.871,9.828,4,12,4c4.411,0,8,3.589,8,8h2c0-5.515-4.486-10-10-10 C9.285,2,6.779,3.089,4.938,4.938L3,3v6h6L6.351,6.351z" />
|
||||||
|
<path d="M17.649,17.649C16.176,19.129,14.173,20,12,20c-4.411,0-8-3.589-8-8H2c0,5.515,4.486,10,10,10 c2.716,0,5.221-1.089,7.062-2.938L21,21v-6h-6L17.649,17.649z" />
|
||||||
|
</svg>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Popout>;
|
||||||
|
}}
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip text="Create Colorway...">
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
style={{ marginLeft: "8px" }}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
onClick={() => openModal((props) => <CreatorModal
|
||||||
|
modalProps={props}
|
||||||
|
loadUIProps={cached_loadUI}
|
||||||
|
/>)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-hidden="true"
|
||||||
|
role="img"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
style={{ padding: "6px", boxSizing: "content-box" }}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M20 11.1111H12.8889V4H11.1111V11.1111H4V12.8889H11.1111V20H12.8889V12.8889H20V11.1111Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</Button>}
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip text="Open Color Stealer">
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
style={{ marginLeft: "8px" }}
|
||||||
|
id="colorway-opencolorstealer"
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
onClick={() => openModal((props) => <ColorPickerModal modalProps={props} />)}
|
||||||
|
>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" style={{ padding: "6px", boxSizing: "content-box" }} fill="currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M12.433 10.07C14.133 10.585 16 11.15 16 8a8 8 0 1 0-8 8c1.996 0 1.826-1.504 1.649-3.08-.124-1.101-.252-2.237.351-2.92.465-.527 1.42-.237 2.433.07zM8 5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM5 6.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm.5 6.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z" />
|
||||||
|
</svg>
|
||||||
|
</Button>}
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
<div className="colorwaysLoader-barContainer"><div className="colorwaysLoader-bar" style={{ height: loaderHeight }} /></div>
|
||||||
|
<div className="ColorwaySelectorWrapper">
|
||||||
|
{visibleColorwayArray.length === 0 &&
|
||||||
|
<Forms.FormTitle
|
||||||
|
style={{
|
||||||
|
marginBottom: 0,
|
||||||
|
width: "100%",
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
No colorways...
|
||||||
|
</Forms.FormTitle>
|
||||||
|
}
|
||||||
|
{visibleColorwayArray.map((color, ind) => {
|
||||||
|
var colors: Array<string> = color.colors || [
|
||||||
|
"accent",
|
||||||
|
"primary",
|
||||||
|
"secondary",
|
||||||
|
"tertiary",
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Tooltip text={color.name}>
|
||||||
|
{({ onMouseEnter, onMouseLeave }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={"discordColorway" + (currentColorway === color.name ? " active" : "")}
|
||||||
|
id={"colorway-" + color.name}
|
||||||
|
data-last-official={
|
||||||
|
ind + 1 === colorways.length
|
||||||
|
}
|
||||||
|
onMouseEnter={onMouseEnter}
|
||||||
|
onMouseLeave={onMouseLeave}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="colorwayInfoIconContainer"
|
||||||
|
onClick={() => {
|
||||||
|
openModal((props) => (
|
||||||
|
<ColorwayInfoModal
|
||||||
|
modalProps={
|
||||||
|
props
|
||||||
|
}
|
||||||
|
colorwayProps={
|
||||||
|
color
|
||||||
|
}
|
||||||
|
discrimProps={customColorways.includes(
|
||||||
|
color
|
||||||
|
)}
|
||||||
|
loadUIProps={cached_loadUI}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="colorwayInfoIcon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="colorwayCheckIconContainer">
|
||||||
|
<div className="colorwayCheckIcon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<circle r="8" cx="12" cy="12" fill="var(--white-500)" />
|
||||||
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<path fill="var(--brand-500)" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="discordColorwayPreviewColorContainer"
|
||||||
|
onClick={() => {
|
||||||
|
if (
|
||||||
|
currentColorway ===
|
||||||
|
color.name
|
||||||
|
) {
|
||||||
|
DataStore.set(
|
||||||
|
"actveColorwayID",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
DataStore.set(
|
||||||
|
"actveColorway",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
ColorwayCSS.remove();
|
||||||
|
} else {
|
||||||
|
DataStore.set(
|
||||||
|
"actveColorwayID",
|
||||||
|
color.name
|
||||||
|
);
|
||||||
|
DataStore.set(
|
||||||
|
"actveColorway",
|
||||||
|
color["dc-import"]
|
||||||
|
);
|
||||||
|
ColorwayCSS.set(
|
||||||
|
color["dc-import"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DataStore.get(
|
||||||
|
"actveColorwayID"
|
||||||
|
).then(
|
||||||
|
(
|
||||||
|
actveColorwayID: string
|
||||||
|
) =>
|
||||||
|
setCurrentColorway(
|
||||||
|
actveColorwayID
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{colors.map((colorItm) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="discordColorwayPreviewColor"
|
||||||
|
style={{
|
||||||
|
// prettier-ignore
|
||||||
|
backgroundColor: color[colorItm],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SettingsTab>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,303 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DataStore } from "@api/index";
|
||||||
|
import { Flex } from "@components/Flex";
|
||||||
|
import { CopyIcon } from "@components/Icons";
|
||||||
|
import { Link } from "@components/Link";
|
||||||
|
import { SettingsTab } from "@components/VencordSettings/shared";
|
||||||
|
import { ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Clipboard,
|
||||||
|
FluxDispatcher,
|
||||||
|
Forms,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useState
|
||||||
|
} from "@webpack/common";
|
||||||
|
import { FluxEvents } from "@webpack/types";
|
||||||
|
import { versionData } from "userplugins/discordColorways";
|
||||||
|
|
||||||
|
import { defaultColorwaySource, fallbackColorways, knownColorwaySources } from "../../constants";
|
||||||
|
import { Colorway } from "../../types";
|
||||||
|
import Divider from "../Divider";
|
||||||
|
import { CloseIcon } from "../Icons";
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
const [colorways, setColorways] = useState<Colorway[]>([]);
|
||||||
|
const [customColorways, setCustomColorways] = useState<Colorway[]>([]);
|
||||||
|
const [colorwaySourceFiles, setColorwaySourceFiles] = useState<string[]>();
|
||||||
|
const [colorsButtonVisibility, setColorsButtonVisibility] = useState<boolean>(false);
|
||||||
|
const [isButtonThin, setIsButtonThin] = useState<boolean>(false);
|
||||||
|
|
||||||
|
async function loadUI() {
|
||||||
|
const colorwaySourceFiles = await DataStore.get(
|
||||||
|
"colorwaySourceFiles"
|
||||||
|
);
|
||||||
|
const responses: Response[] = await Promise.all(
|
||||||
|
colorwaySourceFiles.map((url: string) =>
|
||||||
|
fetch(url)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const data = await Promise.all(
|
||||||
|
responses.map((res: Response) =>
|
||||||
|
res.json().catch(() => { return { colorways: [] }; })
|
||||||
|
));
|
||||||
|
const colorways = data.flatMap(json => json.colorways);
|
||||||
|
const [
|
||||||
|
customColorways,
|
||||||
|
colorwaySourceFiless,
|
||||||
|
showColorwaysButton,
|
||||||
|
useThinMenuButton
|
||||||
|
] = await DataStore.getMany([
|
||||||
|
"customColorways",
|
||||||
|
"colorwaySourceFiles",
|
||||||
|
"showColorwaysButton",
|
||||||
|
"useThinMenuButton"
|
||||||
|
]);
|
||||||
|
setColorways(colorways || fallbackColorways);
|
||||||
|
setCustomColorways(customColorways);
|
||||||
|
setColorwaySourceFiles(colorwaySourceFiless);
|
||||||
|
setColorsButtonVisibility(showColorwaysButton);
|
||||||
|
setIsButtonThin(useThinMenuButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cached_loadUI = useCallback(loadUI, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
cached_loadUI();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <SettingsTab title="Settings">
|
||||||
|
<div className="colorwaysSettingsPage-wrapper">
|
||||||
|
<Flex style={{ gap: "0", marginBottom: "8px" }}>
|
||||||
|
<Forms.FormTitle tag="h5" style={{ width: "100%", marginBottom: "0", lineHeight: "32px" }}>Sources</Forms.FormTitle>
|
||||||
|
<Button
|
||||||
|
className="colorwaysSettings-colorwaySourceAction"
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
style={{ flexShrink: "0" }}
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
color={Button.Colors.TRANSPARENT}
|
||||||
|
onClick={() => {
|
||||||
|
openModal(props => {
|
||||||
|
var colorwaySource = "";
|
||||||
|
return <ModalRoot {...props}>
|
||||||
|
<ModalHeader>
|
||||||
|
<Text variant="heading-lg/semibold" tag="h1">
|
||||||
|
Add a source:
|
||||||
|
</Text>
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalContent>
|
||||||
|
<TextInput
|
||||||
|
placeholder="Enter a valid URL..."
|
||||||
|
onChange={e => colorwaySource = e}
|
||||||
|
/>
|
||||||
|
</ModalContent>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.BRAND}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={async () => {
|
||||||
|
var sourcesArr: string[] = [];
|
||||||
|
const colorwaySourceFilesArr = await DataStore.get("colorwaySourceFiles");
|
||||||
|
colorwaySourceFilesArr.map((source: string) => sourcesArr.push(source));
|
||||||
|
if (colorwaySource !== defaultColorwaySource) {
|
||||||
|
sourcesArr.push(colorwaySource);
|
||||||
|
}
|
||||||
|
DataStore.set("colorwaySourceFiles", sourcesArr);
|
||||||
|
setColorwaySourceFiles(sourcesArr);
|
||||||
|
props.onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Finish
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
color={Button.Colors.PRIMARY}
|
||||||
|
size={Button.Sizes.MEDIUM}
|
||||||
|
look={Button.Looks.FILLED}
|
||||||
|
onClick={() => props.onClose()}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalRoot>;
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-hidden="true"
|
||||||
|
role="img"
|
||||||
|
width="14"
|
||||||
|
height="14"
|
||||||
|
viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M20 11.1111H12.8889V4H11.1111V11.1111H4V12.8889H11.1111V20H12.8889V12.8889H20V11.1111Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Add a source...
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
<Flex flexDirection="column">
|
||||||
|
{colorwaySourceFiles?.map((colorwaySourceFile: string) => <div className="colorwaysSettings-colorwaySource">
|
||||||
|
{knownColorwaySources.find(o => o.url === colorwaySourceFile) ? <div className="hoverRoll">
|
||||||
|
<Text className="colorwaysSettings-colorwaySourceLabel hoverRoll_normal">
|
||||||
|
{knownColorwaySources.find(o => o.url === colorwaySourceFile)!.name} {colorwaySourceFile === defaultColorwaySource && <div className="colorways-badge">DEFAULT</div>}
|
||||||
|
</Text>
|
||||||
|
<Text className="colorwaysSettings-colorwaySourceLabel hoverRoll_hovered">
|
||||||
|
{colorwaySourceFile}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
: <Text className="colorwaysSettings-colorwaySourceLabel">
|
||||||
|
{colorwaySourceFile}
|
||||||
|
</Text>}
|
||||||
|
{colorwaySourceFile !== defaultColorwaySource
|
||||||
|
&& <Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.TRANSPARENT}
|
||||||
|
onClick={async () => {
|
||||||
|
var sourcesArr: string[] = [];
|
||||||
|
const colorwaySourceFilesArr = await DataStore.get("colorwaySourceFiles");
|
||||||
|
colorwaySourceFilesArr.map((source: string) => {
|
||||||
|
if (source !== colorwaySourceFile) {
|
||||||
|
sourcesArr.push(source);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
DataStore.set("colorwaySourceFiles", sourcesArr);
|
||||||
|
setColorwaySourceFiles(sourcesArr);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CloseIcon width={20} height={20} />
|
||||||
|
</Button>}
|
||||||
|
<Button
|
||||||
|
innerClassName="colorwaysSettings-iconButtonInner"
|
||||||
|
size={Button.Sizes.ICON}
|
||||||
|
color={Button.Colors.TRANSPARENT}
|
||||||
|
onClick={() => { Clipboard.copy(colorwaySourceFile); }}
|
||||||
|
>
|
||||||
|
<CopyIcon width={20} height={20} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
<Divider />
|
||||||
|
<Forms.FormTitle tag="h5">Quick Switch</Forms.FormTitle>
|
||||||
|
<Switch
|
||||||
|
value={colorsButtonVisibility}
|
||||||
|
onChange={(v: boolean) => {
|
||||||
|
setColorsButtonVisibility(v);
|
||||||
|
DataStore.set("showColorwaysButton", v);
|
||||||
|
FluxDispatcher.dispatch({
|
||||||
|
type: "COLORWAYS_UPDATE_BUTTON_VISIBILITY" as FluxEvents,
|
||||||
|
isVisible: v
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
note="Shows a button on the top of the servers list that opens a colorway selector modal."
|
||||||
|
>
|
||||||
|
Enable Quick Switch
|
||||||
|
</Switch>
|
||||||
|
<Switch
|
||||||
|
value={isButtonThin}
|
||||||
|
onChange={(v: boolean) => {
|
||||||
|
setIsButtonThin(v);
|
||||||
|
DataStore.set("useThinMenuButton", v);
|
||||||
|
FluxDispatcher.dispatch({
|
||||||
|
type: "COLORWAYS_UPDATE_BUTTON_HEIGHT" as FluxEvents,
|
||||||
|
isTall: v
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
note="Replaces the icon on the colorways launcher button with text, making it more compact."
|
||||||
|
>
|
||||||
|
Use thin Quick Switch button
|
||||||
|
</Switch>
|
||||||
|
<Flex flexDirection="column" style={{ gap: 0 }}>
|
||||||
|
<h1 style={{
|
||||||
|
fontFamily: "var(--font-headline)",
|
||||||
|
fontSize: "24px",
|
||||||
|
color: "var(--header-primary)",
|
||||||
|
lineHeight: "31px",
|
||||||
|
marginBottom: "0"
|
||||||
|
}}>
|
||||||
|
Discord <span style={{
|
||||||
|
fontFamily: "var(--font-display)",
|
||||||
|
fontSize: "24px",
|
||||||
|
backgroundColor: "var(--brand-500)",
|
||||||
|
padding: "0 4px",
|
||||||
|
borderRadius: "4px"
|
||||||
|
}}>Colorways</span>
|
||||||
|
</h1>
|
||||||
|
<Text
|
||||||
|
variant="text-xs/normal"
|
||||||
|
style={{
|
||||||
|
color: "var(--text-normal)",
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: "14px",
|
||||||
|
marginBottom: "12px"
|
||||||
|
}}
|
||||||
|
>by Project Colorway</Text>
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||||
|
Plugin Version:
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<Text
|
||||||
|
variant="text-xs/normal"
|
||||||
|
style={{
|
||||||
|
color: "var(--text-muted)",
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: "14px",
|
||||||
|
marginBottom: "8px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{versionData.pluginVersion}
|
||||||
|
</Text>
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||||
|
Creator Version:
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<Text
|
||||||
|
variant="text-xs/normal"
|
||||||
|
style={{
|
||||||
|
color: "var(--text-muted)",
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: "14px",
|
||||||
|
marginBottom: "8px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{versionData.creatorVersion}{" "}
|
||||||
|
(Stable)
|
||||||
|
</Text>
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||||
|
Loaded Colorways:
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<Text
|
||||||
|
variant="text-xs/normal"
|
||||||
|
style={{
|
||||||
|
color: "var(--text-muted)",
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: "14px",
|
||||||
|
marginBottom: "8px"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{[...colorways, ...customColorways].length}
|
||||||
|
</Text>
|
||||||
|
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||||
|
Project Repositories:
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<Forms.FormText style={{ marginBottom: "8px" }}>
|
||||||
|
<Link href="https://github.com/DaBluLite/DiscordColorways">DiscordColorways</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="https://github.com/DaBluLite/ProjectColorway">Project Colorway</Link>
|
||||||
|
</Forms.FormText>
|
||||||
|
</Flex>
|
||||||
|
</div>
|
||||||
|
</SettingsTab>;
|
||||||
|
}
|
17
src/userplugins/DiscordColorways/components/Spinner.tsx
Normal file
17
src/userplugins/DiscordColorways/components/Spinner.tsx
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function ({ className }: { className?: string; }) {
|
||||||
|
return <div className={"colorwaysBtn-spinner" + (className ? " " + className : "")} role="img" aria-label="Loading">
|
||||||
|
<div className="colorwaysBtn-spinnerInner">
|
||||||
|
<svg className="colorwaysBtn-spinnerCircular" viewBox="25 25 50 50" fill="currentColor">
|
||||||
|
<circle className="colorwaysBtn-spinnerBeam colorwaysBtn-spinnerBeam3" cx="50" cy="50" r="20" />
|
||||||
|
<circle className="colorwaysBtn-spinnerBeam colorwaysBtn-spinnerBeam2" cx="50" cy="50" r="20" />
|
||||||
|
<circle className="colorwaysBtn-spinnerBeam" cx="50" cy="50" r="20" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
222
src/userplugins/DiscordColorways/components/ThemePreview.tsx
Normal file
222
src/userplugins/DiscordColorways/components/ThemePreview.tsx
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Forms,
|
||||||
|
Text,
|
||||||
|
useState
|
||||||
|
} from "@webpack/common";
|
||||||
|
|
||||||
|
import { HexToHSL } from "../utils";
|
||||||
|
import { CloseIcon } from "./Icons";
|
||||||
|
|
||||||
|
export default function ({
|
||||||
|
accent,
|
||||||
|
primary,
|
||||||
|
secondary,
|
||||||
|
tertiary,
|
||||||
|
className,
|
||||||
|
isCollapsed,
|
||||||
|
previewCSS
|
||||||
|
}: {
|
||||||
|
accent: string,
|
||||||
|
primary: string,
|
||||||
|
secondary: string,
|
||||||
|
tertiary: string,
|
||||||
|
className?: string,
|
||||||
|
isCollapsed: boolean,
|
||||||
|
previewCSS?: string;
|
||||||
|
}) {
|
||||||
|
const [collapsed, setCollapsed] = useState<boolean>(isCollapsed);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
`${collapsed === true
|
||||||
|
? "colorwaysPreview colorwaysPreview-collapsed"
|
||||||
|
: "colorwaysPreview"
|
||||||
|
} ${className}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="colorwaysCreator-settingItm colorwaysCreator-settingHeader"
|
||||||
|
onClick={() => setCollapsed(!collapsed)}
|
||||||
|
>
|
||||||
|
<Forms.FormTitle
|
||||||
|
style={{ marginBottom: 0 }}
|
||||||
|
>
|
||||||
|
Preview
|
||||||
|
</Forms.FormTitle>
|
||||||
|
<svg
|
||||||
|
className="expand-3Nh1P5 transition-30IQBn directionDown-2w0MZz"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
aria-hidden="true"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M7 10L12 15 17 10"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
{previewCSS}
|
||||||
|
</style>
|
||||||
|
<ThemePreview
|
||||||
|
accent={accent}
|
||||||
|
primary={primary}
|
||||||
|
secondary={secondary}
|
||||||
|
tertiary={tertiary}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ThemePreview({
|
||||||
|
accent,
|
||||||
|
primary,
|
||||||
|
secondary,
|
||||||
|
tertiary,
|
||||||
|
previewCSS
|
||||||
|
}: {
|
||||||
|
accent: string,
|
||||||
|
primary: string,
|
||||||
|
secondary: string,
|
||||||
|
tertiary: string,
|
||||||
|
previewCSS?: string;
|
||||||
|
}) {
|
||||||
|
const [isFullscreen, setIsFullscreen] = useState<boolean>(false);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="colorwaysPreview-container"
|
||||||
|
>
|
||||||
|
<style>
|
||||||
|
{previewCSS}
|
||||||
|
</style>
|
||||||
|
<div
|
||||||
|
className="colorwaysPreview-wrapper"
|
||||||
|
style={{ backgroundColor: tertiary }}
|
||||||
|
>
|
||||||
|
<div className="colorwaysPreview-titlebar" />
|
||||||
|
<div className="colorwaysPreview-body">
|
||||||
|
<div className="colorwayPreview-guilds">
|
||||||
|
<div className="colorwayPreview-guild">
|
||||||
|
<div
|
||||||
|
className="colorwayPreview-guildItem"
|
||||||
|
style={{ backgroundColor: primary }}
|
||||||
|
onMouseEnter={e => e.currentTarget.style.backgroundColor = accent}
|
||||||
|
onMouseLeave={e => e.currentTarget.style.backgroundColor = primary}
|
||||||
|
onClick={e => {
|
||||||
|
if (!document.fullscreenElement) {
|
||||||
|
e.currentTarget
|
||||||
|
.parentElement
|
||||||
|
?.parentElement
|
||||||
|
?.parentElement
|
||||||
|
?.parentElement
|
||||||
|
?.requestFullscreen();
|
||||||
|
} else {
|
||||||
|
document.exitFullscreen();
|
||||||
|
}
|
||||||
|
setIsFullscreen(!isFullscreen);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isFullscreen ? <CloseIcon /> : <svg
|
||||||
|
aria-hidden="true"
|
||||||
|
role="img"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M19,3H14V5h5v5h2V5A2,2,0,0,0,19,3Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M19,19H14v2h5a2,2,0,0,0,2-2V14H19Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M3,5v5H5V5h5V3H5A2,2,0,0,0,3,5Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M5,14H3v5a2,2,0,0,0,2,2h5V19H5Z"
|
||||||
|
/>
|
||||||
|
</svg>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="colorwayPreview-guild">
|
||||||
|
<div className="colorwayPreview-guildSeparator" style={{ backgroundColor: primary }} />
|
||||||
|
</div>
|
||||||
|
<div className="colorwayPreview-guild">
|
||||||
|
<div
|
||||||
|
className="colorwayPreview-guildItem"
|
||||||
|
style={{ backgroundColor: primary }}
|
||||||
|
onMouseEnter={e => { e.currentTarget.style.backgroundColor = accent; }}
|
||||||
|
onMouseLeave={e => { e.currentTarget.style.backgroundColor = primary; }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="colorwayPreview-guild">
|
||||||
|
<div
|
||||||
|
className="colorwayPreview-guildItem"
|
||||||
|
style={{ backgroundColor: primary }}
|
||||||
|
onMouseEnter={e => { e.currentTarget.style.backgroundColor = accent; }}
|
||||||
|
onMouseLeave={e => { e.currentTarget.style.backgroundColor = primary; }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="colorwayPreview-channels" style={{ backgroundColor: secondary }}>
|
||||||
|
<div
|
||||||
|
className="colorwayPreview-userArea"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "hsl(" + HexToHSL(secondary)[0] + " " + HexToHSL(secondary)[1] + "% " + Math.max(HexToHSL(secondary)[2] - 3.6, 0) + "%)"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="colorwayPreview-filler" />
|
||||||
|
<div
|
||||||
|
className="colorwayPreview-topShadow"
|
||||||
|
style={{
|
||||||
|
"--primary-900-hsl": `${HexToHSL(tertiary)[0]} ${HexToHSL(tertiary)[1]}% ${Math.max(HexToHSL(tertiary)[2] - (3.6 * 6), 0)}%`,
|
||||||
|
"--primary-500-hsl": `${HexToHSL(primary)[0]} ${HexToHSL(primary)[1]}% ${Math.min(HexToHSL(primary)[2] + (3.6 * 3), 100)}%`
|
||||||
|
} as React.CSSProperties}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
tag="div"
|
||||||
|
variant="text-md/semibold"
|
||||||
|
lineClamp={1}
|
||||||
|
selectable={false}
|
||||||
|
>
|
||||||
|
Preview
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="colorwayPreview-chat" style={{ backgroundColor: primary }}>
|
||||||
|
<div
|
||||||
|
className="colorwayPreview-chatBox"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "hsl(" + HexToHSL(primary)[0] + " " + HexToHSL(primary)[1] + "% " + Math.min(HexToHSL(primary)[2] + 3.6, 100) + "%)"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="colorwayPreview-filler" />
|
||||||
|
<div
|
||||||
|
className="colorwayPreview-topShadow"
|
||||||
|
style={{
|
||||||
|
"--primary-900-hsl": `${HexToHSL(tertiary)[0]} ${HexToHSL(tertiary)[1]}% ${Math.max(HexToHSL(tertiary)[2] - (3.6 * 6), 0)}%`
|
||||||
|
} as React.CSSProperties}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
317
src/userplugins/DiscordColorways/constants.ts
Normal file
317
src/userplugins/DiscordColorways/constants.ts
Normal file
|
@ -0,0 +1,317 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const defaultColorwaySource = "https://raw.githubusercontent.com/DaBluLite/ProjectColorway/master/index.json";
|
||||||
|
|
||||||
|
export const knownColorwaySources = [
|
||||||
|
{
|
||||||
|
name: "Project Colorway",
|
||||||
|
url: "https://raw.githubusercontent.com/DaBluLite/ProjectColorway/master/index.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DaBluLite's Personal Colorways",
|
||||||
|
url: "https://raw.githubusercontent.com/DaBluLite/dablulite.github.io/master/colorways/index.json"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const fallbackColorways = [
|
||||||
|
{
|
||||||
|
name: "Keyboard Purple",
|
||||||
|
original: false,
|
||||||
|
accent: "hsl(235 85.6% 64.7%)",
|
||||||
|
primary: "#222456",
|
||||||
|
secondary: "#1c1f48",
|
||||||
|
tertiary: "#080d1d",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/KeyboardPurple/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Eclipse",
|
||||||
|
original: false,
|
||||||
|
accent: "hsl(87 85.6% 64.7%)",
|
||||||
|
primary: "#000000",
|
||||||
|
secondary: "#181818",
|
||||||
|
tertiary: "#0a0a0a",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Eclipse/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cyan",
|
||||||
|
original: false,
|
||||||
|
accent: "#009f88",
|
||||||
|
primary: "#202226",
|
||||||
|
secondary: "#1c1e21",
|
||||||
|
tertiary: "#141517",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Cyan/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Spotify",
|
||||||
|
original: false,
|
||||||
|
accent: "hsl(141 76% 48%)",
|
||||||
|
primary: "#121212",
|
||||||
|
secondary: "#090909",
|
||||||
|
tertiary: "#090909",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Spotify/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bright n' Blue",
|
||||||
|
original: true,
|
||||||
|
accent: "hsl(234, 68%, 33%)",
|
||||||
|
primary: "#394aae",
|
||||||
|
secondary: "#29379d",
|
||||||
|
tertiary: "#1b278d",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/BrightBlue/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Still Young",
|
||||||
|
original: true,
|
||||||
|
accent: "hsl(58 85.6% 89%)",
|
||||||
|
primary: "#443a31",
|
||||||
|
secondary: "#7c3d3e",
|
||||||
|
tertiary: "#207578",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/StillYoung/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Sea",
|
||||||
|
original: true,
|
||||||
|
accent: "hsl(184, 100%, 50%)",
|
||||||
|
primary: "#07353b",
|
||||||
|
secondary: "#0b5e60",
|
||||||
|
tertiary: "#08201d",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Sea/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Lava",
|
||||||
|
original: true,
|
||||||
|
accent: "hsl(4, 80.4%, 32%)",
|
||||||
|
primary: "#401b17",
|
||||||
|
secondary: "#351917",
|
||||||
|
tertiary: "#230b0b",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Lava/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Solid Pink",
|
||||||
|
original: true,
|
||||||
|
accent: "hsl(340, 55.2%, 56.3%)",
|
||||||
|
primary: "#1e151c",
|
||||||
|
secondary: "#21181f",
|
||||||
|
tertiary: "#291e27",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/SolidPink/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Sand",
|
||||||
|
original: true,
|
||||||
|
accent: "hsl(41, 31%, 45%)",
|
||||||
|
primary: "#7f6c43",
|
||||||
|
secondary: "#665b33",
|
||||||
|
tertiary: "#5c5733",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Sand/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "AMOLED",
|
||||||
|
original: true,
|
||||||
|
accent: "hsl(235 85.6% 64.7%)",
|
||||||
|
primary: "#000000",
|
||||||
|
secondary: "#000000",
|
||||||
|
tertiary: "#000000",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Amoled/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Zorin",
|
||||||
|
original: false,
|
||||||
|
accent: "hsl(200, 89%, 86%)",
|
||||||
|
primary: "#171d20",
|
||||||
|
secondary: "#171d20",
|
||||||
|
tertiary: "#1e2529",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Zorin/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Desaturated",
|
||||||
|
original: false,
|
||||||
|
accent: "hsl(227, 58%, 65%)",
|
||||||
|
primary: "#35383d",
|
||||||
|
secondary: "#2c2f34",
|
||||||
|
tertiary: "#1e1f24",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Desaturated/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Crimson",
|
||||||
|
original: false,
|
||||||
|
accent: "hsl(0, 100%, 50%)",
|
||||||
|
primary: "#050000",
|
||||||
|
secondary: "#0a0000",
|
||||||
|
tertiary: "#0f0000",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Crimson/import.css);",
|
||||||
|
author: "Riddim_GLiTCH",
|
||||||
|
authorID: "801089753038061669",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Jupiter",
|
||||||
|
original: true,
|
||||||
|
accent: "#ffd89b",
|
||||||
|
primary: "#ffd89b",
|
||||||
|
secondary: "#19547b",
|
||||||
|
tertiary: "#1e1f22",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Jupiter/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
isGradient: true,
|
||||||
|
colors: ["accent", "primary", "secondary"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Neon Candy",
|
||||||
|
original: true,
|
||||||
|
accent: "#FC00FF",
|
||||||
|
primary: "#00DBDE",
|
||||||
|
secondary: "#00DBDE",
|
||||||
|
tertiary: "#00DBDE",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/NeonCandy/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
isGradient: true,
|
||||||
|
colors: ["accent", "primary"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Wildberry",
|
||||||
|
original: false,
|
||||||
|
accent: "#f40172",
|
||||||
|
primary: "#180029",
|
||||||
|
secondary: "#340057",
|
||||||
|
tertiary: "#4b007a",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Wildberry/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Facebook",
|
||||||
|
original: false,
|
||||||
|
accent: "#2375e1",
|
||||||
|
primary: "#18191a",
|
||||||
|
secondary: "#242526",
|
||||||
|
tertiary: "#3a3b3c",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Facebook/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Material You",
|
||||||
|
original: false,
|
||||||
|
accent: "#004977",
|
||||||
|
primary: "#1f1f1f",
|
||||||
|
secondary: "#28292a",
|
||||||
|
tertiary: "#2d2f31",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/MaterialYou/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Discord Teal",
|
||||||
|
original: false,
|
||||||
|
accent: "#175f6d",
|
||||||
|
primary: "#313338",
|
||||||
|
secondary: "#2b2d31",
|
||||||
|
tertiary: "#1e1f22",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/css-snippets/DiscordTeal/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
colors: ["accent"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "黄昏の花 (Twilight Blossom)",
|
||||||
|
original: true,
|
||||||
|
accent: "#e100ff",
|
||||||
|
primary: "#04000a",
|
||||||
|
secondary: "#0b0024",
|
||||||
|
tertiary: "#210042",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/TwilightBlossom/import.css);",
|
||||||
|
author: "Riddim_GLiTCH",
|
||||||
|
authorID: "801089753038061669",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Chai",
|
||||||
|
original: true,
|
||||||
|
accent: "#59cd51",
|
||||||
|
primary: "#1c1e15",
|
||||||
|
secondary: "#1e2118",
|
||||||
|
tertiary: "#24291e",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/Chai/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "CS1.6",
|
||||||
|
original: false,
|
||||||
|
accent: "#929a8d",
|
||||||
|
primary: "#3f4738",
|
||||||
|
secondary: "#5b6c51",
|
||||||
|
tertiary: "#4d5945",
|
||||||
|
"dc-import": "@import url(//dablulite.github.io/DiscordColorways/CS16/import.css);",
|
||||||
|
author: "DaBluLite",
|
||||||
|
authorID: "582170007505731594",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
export const knownThemeVars = {
|
||||||
|
"Cyan": {
|
||||||
|
variable: "--cyan-accent-color",
|
||||||
|
accent: "--cyan-accent-color",
|
||||||
|
primary: "--cyan-background-primary",
|
||||||
|
secondary: "--cyan-background-secondary"
|
||||||
|
},
|
||||||
|
"Virtual Boy": {
|
||||||
|
variable: "--VBaccent",
|
||||||
|
tertiary: "--VBaccent-muted",
|
||||||
|
alt: {
|
||||||
|
tertiary: "--VBaccent-dimmest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Modular": {
|
||||||
|
variable: "--modular-hue",
|
||||||
|
accentVariables: {
|
||||||
|
h: "--modular-hue",
|
||||||
|
s: "--modular-saturation",
|
||||||
|
l: "--modular-lightness"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Solana": {
|
||||||
|
variable: "--accent-hue",
|
||||||
|
accentVariables: {
|
||||||
|
h: "--accent-hue",
|
||||||
|
s: "--accent-saturation",
|
||||||
|
l: "--accent-brightness"
|
||||||
|
},
|
||||||
|
primaryVariables: {
|
||||||
|
h: "--background-accent-hue",
|
||||||
|
s: "--background-accent-saturation",
|
||||||
|
l: "--background-accent-brightness"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
767
src/userplugins/DiscordColorways/css.ts
Normal file
767
src/userplugins/DiscordColorways/css.ts
Normal file
|
@ -0,0 +1,767 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Plugins } from "Vencord";
|
||||||
|
|
||||||
|
import { HexToHSL } from "./utils";
|
||||||
|
|
||||||
|
export const colorVariables: string[] = [
|
||||||
|
"brand-100",
|
||||||
|
"brand-130",
|
||||||
|
"brand-160",
|
||||||
|
"brand-200",
|
||||||
|
"brand-230",
|
||||||
|
"brand-260",
|
||||||
|
"brand-300",
|
||||||
|
"brand-330",
|
||||||
|
"brand-345",
|
||||||
|
"brand-360",
|
||||||
|
"brand-400",
|
||||||
|
"brand-430",
|
||||||
|
"brand-460",
|
||||||
|
"brand-500",
|
||||||
|
"brand-530",
|
||||||
|
"brand-560",
|
||||||
|
"brand-600",
|
||||||
|
"brand-630",
|
||||||
|
"brand-660",
|
||||||
|
"brand-700",
|
||||||
|
"brand-730",
|
||||||
|
"brand-760",
|
||||||
|
"brand-800",
|
||||||
|
"brand-830",
|
||||||
|
"brand-860",
|
||||||
|
"brand-900",
|
||||||
|
"primary-900",
|
||||||
|
"primary-860",
|
||||||
|
"primary-830",
|
||||||
|
"primary-800",
|
||||||
|
"primary-760",
|
||||||
|
"primary-730",
|
||||||
|
"primary-700",
|
||||||
|
"primary-660",
|
||||||
|
"primary-645",
|
||||||
|
"primary-630",
|
||||||
|
"primary-600",
|
||||||
|
"primary-560",
|
||||||
|
"primary-530",
|
||||||
|
"primary-500",
|
||||||
|
"primary-460",
|
||||||
|
"primary-430",
|
||||||
|
"primary-400",
|
||||||
|
"primary-360",
|
||||||
|
"primary-330",
|
||||||
|
"primary-300",
|
||||||
|
"primary-260",
|
||||||
|
"primary-230",
|
||||||
|
"primary-200",
|
||||||
|
"primary-160",
|
||||||
|
"primary-130",
|
||||||
|
"primary-100",
|
||||||
|
"white-900",
|
||||||
|
"white-860",
|
||||||
|
"white-830",
|
||||||
|
"white-800",
|
||||||
|
"white-760",
|
||||||
|
"white-730",
|
||||||
|
"white-700",
|
||||||
|
"white-660",
|
||||||
|
"white-630",
|
||||||
|
"white-600",
|
||||||
|
"white-560",
|
||||||
|
"white-530",
|
||||||
|
"white-500",
|
||||||
|
"white-460",
|
||||||
|
"white-430",
|
||||||
|
"white-400",
|
||||||
|
"white-360",
|
||||||
|
"white-330",
|
||||||
|
"white-300",
|
||||||
|
"white-260",
|
||||||
|
"white-230",
|
||||||
|
"white-200",
|
||||||
|
"white-160",
|
||||||
|
"white-130",
|
||||||
|
"white-100",
|
||||||
|
"teal-900",
|
||||||
|
"teal-860",
|
||||||
|
"teal-830",
|
||||||
|
"teal-800",
|
||||||
|
"teal-760",
|
||||||
|
"teal-730",
|
||||||
|
"teal-700",
|
||||||
|
"teal-660",
|
||||||
|
"teal-630",
|
||||||
|
"teal-600",
|
||||||
|
"teal-560",
|
||||||
|
"teal-530",
|
||||||
|
"teal-500",
|
||||||
|
"teal-460",
|
||||||
|
"teal-430",
|
||||||
|
"teal-400",
|
||||||
|
"teal-360",
|
||||||
|
"teal-330",
|
||||||
|
"teal-300",
|
||||||
|
"teal-260",
|
||||||
|
"teal-230",
|
||||||
|
"teal-200",
|
||||||
|
"teal-160",
|
||||||
|
"teal-130",
|
||||||
|
"teal-100",
|
||||||
|
"black-900",
|
||||||
|
"black-860",
|
||||||
|
"black-830",
|
||||||
|
"black-800",
|
||||||
|
"black-760",
|
||||||
|
"black-730",
|
||||||
|
"black-700",
|
||||||
|
"black-660",
|
||||||
|
"black-630",
|
||||||
|
"black-600",
|
||||||
|
"black-560",
|
||||||
|
"black-530",
|
||||||
|
"black-500",
|
||||||
|
"black-460",
|
||||||
|
"black-430",
|
||||||
|
"black-400",
|
||||||
|
"black-360",
|
||||||
|
"black-330",
|
||||||
|
"black-300",
|
||||||
|
"black-260",
|
||||||
|
"black-230",
|
||||||
|
"black-200",
|
||||||
|
"black-160",
|
||||||
|
"black-130",
|
||||||
|
"black-100",
|
||||||
|
"red-900",
|
||||||
|
"red-860",
|
||||||
|
"red-830",
|
||||||
|
"red-800",
|
||||||
|
"red-760",
|
||||||
|
"red-730",
|
||||||
|
"red-700",
|
||||||
|
"red-660",
|
||||||
|
"red-630",
|
||||||
|
"red-600",
|
||||||
|
"red-560",
|
||||||
|
"red-530",
|
||||||
|
"red-500",
|
||||||
|
"red-460",
|
||||||
|
"red-430",
|
||||||
|
"red-400",
|
||||||
|
"red-360",
|
||||||
|
"red-330",
|
||||||
|
"red-300",
|
||||||
|
"red-260",
|
||||||
|
"red-230",
|
||||||
|
"red-200",
|
||||||
|
"red-160",
|
||||||
|
"red-130",
|
||||||
|
"red-100",
|
||||||
|
"yellow-900",
|
||||||
|
"yellow-860",
|
||||||
|
"yellow-830",
|
||||||
|
"yellow-800",
|
||||||
|
"yellow-760",
|
||||||
|
"yellow-730",
|
||||||
|
"yellow-700",
|
||||||
|
"yellow-660",
|
||||||
|
"yellow-630",
|
||||||
|
"yellow-600",
|
||||||
|
"yellow-560",
|
||||||
|
"yellow-530",
|
||||||
|
"yellow-500",
|
||||||
|
"yellow-460",
|
||||||
|
"yellow-430",
|
||||||
|
"yellow-400",
|
||||||
|
"yellow-360",
|
||||||
|
"yellow-330",
|
||||||
|
"yellow-300",
|
||||||
|
"yellow-260",
|
||||||
|
"yellow-230",
|
||||||
|
"yellow-200",
|
||||||
|
"yellow-160",
|
||||||
|
"yellow-130",
|
||||||
|
"yellow-100",
|
||||||
|
"green-900",
|
||||||
|
"green-860",
|
||||||
|
"green-830",
|
||||||
|
"green-800",
|
||||||
|
"green-760",
|
||||||
|
"green-730",
|
||||||
|
"green-700",
|
||||||
|
"green-660",
|
||||||
|
"green-630",
|
||||||
|
"green-600",
|
||||||
|
"green-560",
|
||||||
|
"green-530",
|
||||||
|
"green-500",
|
||||||
|
"green-460",
|
||||||
|
"green-430",
|
||||||
|
"green-400",
|
||||||
|
"green-360",
|
||||||
|
"green-330",
|
||||||
|
"green-300",
|
||||||
|
"green-260",
|
||||||
|
"green-230",
|
||||||
|
"green-200",
|
||||||
|
"green-160",
|
||||||
|
"green-130",
|
||||||
|
"green-100",
|
||||||
|
];
|
||||||
|
|
||||||
|
const PrimarySatDiffs = {
|
||||||
|
130: 63.9594,
|
||||||
|
160: 49.4382,
|
||||||
|
200: 37.5758,
|
||||||
|
230: 30.3797,
|
||||||
|
260: 22.5166,
|
||||||
|
300: 32.5,
|
||||||
|
330: 27.0968,
|
||||||
|
345: 22.5166,
|
||||||
|
360: 18.9189,
|
||||||
|
400: -14.4,
|
||||||
|
430: -33.0435,
|
||||||
|
460: 25.2101,
|
||||||
|
500: -11.0236,
|
||||||
|
530: -3.0303,
|
||||||
|
645: 7.40741,
|
||||||
|
660: 3.0303,
|
||||||
|
730: 11.9403,
|
||||||
|
800: 25,
|
||||||
|
};
|
||||||
|
|
||||||
|
const BrandSatDiffs = {
|
||||||
|
100: -9.54712,
|
||||||
|
130: 2.19526,
|
||||||
|
160: -1.17509,
|
||||||
|
200: -2.72351,
|
||||||
|
230: 1.62225,
|
||||||
|
260: 0.698487,
|
||||||
|
300: 0.582411,
|
||||||
|
330: -0.585823,
|
||||||
|
345: -0.468384,
|
||||||
|
360: 0.582411,
|
||||||
|
400: 0.582411,
|
||||||
|
430: 0.116754,
|
||||||
|
460: -0.116891,
|
||||||
|
530: -24.8194,
|
||||||
|
560: -49.927,
|
||||||
|
600: -58.8057,
|
||||||
|
630: -58.8057,
|
||||||
|
660: -58.0256,
|
||||||
|
700: -58.2202,
|
||||||
|
730: -58.6103,
|
||||||
|
760: -58.4151,
|
||||||
|
800: -57.2502,
|
||||||
|
830: -57.4436,
|
||||||
|
860: -58.4151,
|
||||||
|
900: -52.5074
|
||||||
|
};
|
||||||
|
|
||||||
|
const BrandLightDiffs = {
|
||||||
|
100: 33.5,
|
||||||
|
130: 32.2,
|
||||||
|
160: 30.2,
|
||||||
|
200: 28.2,
|
||||||
|
230: 26.2999,
|
||||||
|
260: 23.8999,
|
||||||
|
300: 21.2,
|
||||||
|
330: 16.8999,
|
||||||
|
345: 14.0999,
|
||||||
|
360: 12.7999,
|
||||||
|
400: 7.0999,
|
||||||
|
430: 5.0999,
|
||||||
|
460: 2.7999,
|
||||||
|
530: -5.9,
|
||||||
|
560: -12.3,
|
||||||
|
600: -20.6,
|
||||||
|
630: -26.5,
|
||||||
|
660: -31.4,
|
||||||
|
700: -38.8,
|
||||||
|
730: -40.4,
|
||||||
|
760: -42.5,
|
||||||
|
800: -45.3,
|
||||||
|
830: -49.8,
|
||||||
|
860: -55.1,
|
||||||
|
900: -61.6
|
||||||
|
};
|
||||||
|
|
||||||
|
function gradientBase(accentColor?: string, discordSaturation = false) {
|
||||||
|
return `@import url(//dablulite.github.io/css-snippets/NoLightInDark/import.css);
|
||||||
|
@import url(//dablulite.github.io/css-snippets/NitroThemesFix/import.css);
|
||||||
|
.theme-dark {
|
||||||
|
--bg-overlay-color: 0 0 0;
|
||||||
|
--bg-overlay-color-inverse: 255 255 255;
|
||||||
|
--bg-overlay-opacity-1: 0.85;
|
||||||
|
--bg-overlay-opacity-2: 0.8;
|
||||||
|
--bg-overlay-opacity-3: 0.7;
|
||||||
|
--bg-overlay-opacity-4: 0.5;
|
||||||
|
--bg-overlay-opacity-5: 0.4;
|
||||||
|
--bg-overlay-opacity-6: 0.1;
|
||||||
|
--bg-overlay-opacity-hover: 0.5;
|
||||||
|
--bg-overlay-opacity-hover-inverse: 0.08;
|
||||||
|
--bg-overlay-opacity-active: 0.45;
|
||||||
|
--bg-overlay-opacity-active-inverse: 0.1;
|
||||||
|
--bg-overlay-opacity-selected: 0.4;
|
||||||
|
--bg-overlay-opacity-selected-inverse: 0.15;
|
||||||
|
--bg-overlay-opacity-chat: 0.8;
|
||||||
|
--bg-overlay-opacity-home: 0.85;
|
||||||
|
--bg-overlay-opacity-home-card: 0.8;
|
||||||
|
--bg-overlay-opacity-app-frame: var(--bg-overlay-opacity-4);
|
||||||
|
}
|
||||||
|
.theme-light {
|
||||||
|
--bg-overlay-color: 255 255 255;
|
||||||
|
--bg-overlay-color-inverse: 0 0 0;
|
||||||
|
--bg-overlay-opacity-1: 0.9;
|
||||||
|
--bg-overlay-opacity-2: 0.8;
|
||||||
|
--bg-overlay-opacity-3: 0.7;
|
||||||
|
--bg-overlay-opacity-4: 0.6;
|
||||||
|
--bg-overlay-opacity-5: 0.3;
|
||||||
|
--bg-overlay-opacity-6: 0.15;
|
||||||
|
--bg-overlay-opacity-hover: 0.7;
|
||||||
|
--bg-overlay-opacity-hover-inverse: 0.02;
|
||||||
|
--bg-overlay-opacity-active: 0.65;
|
||||||
|
--bg-overlay-opacity-active-inverse: 0.03;
|
||||||
|
--bg-overlay-opacity-selected: 0.6;
|
||||||
|
--bg-overlay-opacity-selected-inverse: 0.04;
|
||||||
|
--bg-overlay-opacity-chat: 0.9;
|
||||||
|
--bg-overlay-opacity-home: 0.7;
|
||||||
|
--bg-overlay-opacity-home-card: 0.9;
|
||||||
|
--bg-overlay-opacity-app-frame: var(--bg-overlay-opacity-5);
|
||||||
|
}
|
||||||
|
.children_cde9af:after, .form_d8a4a1:before {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
.scroller_de945b {
|
||||||
|
background: var(--bg-overlay-app-frame,var(--background-tertiary));
|
||||||
|
}
|
||||||
|
.expandedFolderBackground_b1385f {
|
||||||
|
background: rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-6));
|
||||||
|
}
|
||||||
|
.wrapper__8436d:not(:hover):not(.selected_ae80f7) .childWrapper_a6ce15 {
|
||||||
|
background: rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-6));
|
||||||
|
}
|
||||||
|
.folder__17546:has(.expandedFolderIconWrapper__324c1) {
|
||||||
|
background: var(--bg-overlay-6,var(--background-secondary));
|
||||||
|
}
|
||||||
|
.circleIconButton__05cf2:not(.selected_aded59) {
|
||||||
|
background: rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-6));
|
||||||
|
}
|
||||||
|
.auto_a3c0bd::-webkit-scrollbar-thumb,
|
||||||
|
.thin_b1c063::-webkit-scrollbar-thumb {
|
||||||
|
background-size: 200vh;
|
||||||
|
background-image: -webkit-gradient(linear,left top,left bottom,from(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-4))),to(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-4)))),var(--custom-theme-background);
|
||||||
|
background-image: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-4)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-4))),var(--custom-theme-background);
|
||||||
|
}
|
||||||
|
.auto_a3c0bd::-webkit-scrollbar-track {
|
||||||
|
background-size: 200vh;
|
||||||
|
background-image: -webkit-gradient(linear,left top,left bottom,from(rgb(var(--bg-overlay-color)/.4)),to(rgb(var(--bg-overlay-color)/.4))),var(--custom-theme-background);
|
||||||
|
background-image: linear-gradient(rgb(var(--bg-overlay-color)/.4),rgb(var(--bg-overlay-color)/.4)),var(--custom-theme-background);
|
||||||
|
}
|
||||||
|
:root:root {
|
||||||
|
--brand-100-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[100])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[100]) * 10) / 10, 0)};
|
||||||
|
--brand-130-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[130])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[130]) * 10) / 10, 0)}%;
|
||||||
|
--brand-160-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[160])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[160]) * 10) / 10, 0)}%;
|
||||||
|
--brand-200-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[200])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[200]) * 10) / 10, 0)}%;
|
||||||
|
--brand-230-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[230])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[230]) * 10) / 10, 0)}%;
|
||||||
|
--brand-260-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[260])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[260]) * 10) / 10, 0)}%;
|
||||||
|
--brand-300-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[300])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[300]) * 10) / 10, 0)}%;
|
||||||
|
--brand-330-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[330])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[330]) * 10) / 10, 0)}%;
|
||||||
|
--brand-345-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[345])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[345]) * 10) / 10, 0)}%;
|
||||||
|
--brand-360-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[360])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[360]) * 10) / 10, 0)}%;
|
||||||
|
--brand-400-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[400])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[400]) * 10) / 10, 0)}%;
|
||||||
|
--brand-430-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[430])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[430]) * 10) / 10, 0)}%;
|
||||||
|
--brand-460-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[460])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[460]) * 10) / 10, 0)}%;
|
||||||
|
--brand-500-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + accentColor)[1]}%) ${HexToHSL("#" + accentColor)[2]}%;
|
||||||
|
--brand-530-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[530])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[530]) * 10) / 10, 100)}%;
|
||||||
|
--brand-560-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[560])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[560]) * 10) / 10, 100)}%;
|
||||||
|
--brand-600-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[600])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[600]) * 10) / 10, 100)}%;
|
||||||
|
--brand-630-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[630])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[630]) * 10) / 10, 100)}%;
|
||||||
|
--brand-660-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[660])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[660]) * 10) / 10, 100)}%;
|
||||||
|
--brand-700-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[700])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[700]) * 10) / 10, 100)}%;
|
||||||
|
--brand-730-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[730])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[730]) * 10) / 10, 100)}%;
|
||||||
|
--brand-760-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[760])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[760]) * 10) / 10, 100)}%;
|
||||||
|
--brand-800-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[800])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[800]) * 10) / 10, 100)}%;
|
||||||
|
--brand-830-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[830])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[830]) * 10) / 10, 100)}%;
|
||||||
|
--brand-860-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[860])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[860]) * 10) / 10, 100)}%;
|
||||||
|
--brand-900-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[900])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[900]) * 10) / 10, 100)}%;
|
||||||
|
--bg-overlay-1: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-1)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-1))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-2: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-2)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-2))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-3: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-3)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-3))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-4: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-4)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-4))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-5: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-5)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-5))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-6: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-6)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-6))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-hover: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-hover-inverse)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-hover-inverse))) fixed 0 0/cover,linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-hover)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-hover))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-active: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-active-inverse)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-active-inverse))) fixed 0 0/cover,linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-active)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-active))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-selected: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-selected-inverse)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-selected-inverse))) fixed 0 0/cover,linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-selected)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-selected))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-chat: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-chat)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-chat))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-home: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-home-card: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home-card)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home-card))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||||
|
--bg-overlay-app-frame: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-app-frame)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-app-frame))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateCss(primaryColor: string, secondaryColor: string, tertiaryColor: string, accentColor: string, tintedText: boolean, discordSaturation: boolean) {
|
||||||
|
const colorwayCss = `/*Automatically Generated - Colorway Creator V${(Plugins.plugins.DiscordColorways as any).creatorVersion}*/
|
||||||
|
:root:root {
|
||||||
|
--brand-100-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[100])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[100]) * 10) / 10, 0)};
|
||||||
|
--brand-130-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[130])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[130]) * 10) / 10, 0)}%;
|
||||||
|
--brand-160-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[160])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[160]) * 10) / 10, 0)}%;
|
||||||
|
--brand-200-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[200])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[200]) * 10) / 10, 0)}%;
|
||||||
|
--brand-230-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[230])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[230]) * 10) / 10, 0)}%;
|
||||||
|
--brand-260-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[260])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[260]) * 10) / 10, 0)}%;
|
||||||
|
--brand-300-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[300])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[300]) * 10) / 10, 0)}%;
|
||||||
|
--brand-330-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[330])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[330]) * 10) / 10, 0)}%;
|
||||||
|
--brand-345-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[345])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[345]) * 10) / 10, 0)}%;
|
||||||
|
--brand-360-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[360])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[360]) * 10) / 10, 0)}%;
|
||||||
|
--brand-400-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[400])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[400]) * 10) / 10, 0)}%;
|
||||||
|
--brand-430-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[430])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[430]) * 10) / 10, 0)}%;
|
||||||
|
--brand-460-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[460])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[460]) * 10) / 10, 0)}%;
|
||||||
|
--brand-500-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + accentColor)[1]}%) ${HexToHSL("#" + accentColor)[2]}%;
|
||||||
|
--brand-530-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[530])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[530]) * 10) / 10, 100)}%;
|
||||||
|
--brand-560-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[560])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[560]) * 10) / 10, 100)}%;
|
||||||
|
--brand-600-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[600])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[600]) * 10) / 10, 100)}%;
|
||||||
|
--brand-630-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[630])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[630]) * 10) / 10, 100)}%;
|
||||||
|
--brand-660-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[660])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[660]) * 10) / 10, 100)}%;
|
||||||
|
--brand-700-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[700])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[700]) * 10) / 10, 100)}%;
|
||||||
|
--brand-730-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[730])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[730]) * 10) / 10, 100)}%;
|
||||||
|
--brand-760-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[760])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[760]) * 10) / 10, 100)}%;
|
||||||
|
--brand-800-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[800])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[800]) * 10) / 10, 100)}%;
|
||||||
|
--brand-830-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[830])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[830]) * 10) / 10, 100)}%;
|
||||||
|
--brand-860-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[860])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[860]) * 10) / 10, 100)}%;
|
||||||
|
--brand-900-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[900])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[900]) * 10) / 10, 100)}%;
|
||||||
|
--primary-800-hsl: ${HexToHSL("#" + tertiaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + tertiaryColor)[1] / 100) * (100 + PrimarySatDiffs[800])) * 10) / 10 : HexToHSL("#" + tertiaryColor)[1]}%) ${Math.max(HexToHSL("#" + tertiaryColor)[2] - (3.6 * 2), 0)}%;
|
||||||
|
--primary-730-hsl: ${HexToHSL("#" + tertiaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + tertiaryColor)[1] / 100) * (100 + PrimarySatDiffs[730])) * 10) / 10 : HexToHSL("#" + tertiaryColor)[1]}%) ${Math.max(HexToHSL("#" + tertiaryColor)[2] - 3.6, 0)}%;
|
||||||
|
--primary-700-hsl: ${HexToHSL("#" + tertiaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + tertiaryColor)[1]}%) ${HexToHSL("#" + tertiaryColor)[2]}%;
|
||||||
|
--primary-660-hsl: ${HexToHSL("#" + secondaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + secondaryColor)[1] / 100) * (100 + PrimarySatDiffs[660])) * 10) / 10 : HexToHSL("#" + secondaryColor)[1]}%) ${Math.max(HexToHSL("#" + secondaryColor)[2] - 3.6, 0)}%;
|
||||||
|
--primary-645-hsl: ${HexToHSL("#" + secondaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + secondaryColor)[1] / 100) * (100 + PrimarySatDiffs[645])) * 10) / 10 : HexToHSL("#" + secondaryColor)[1]}%) ${Math.max(HexToHSL("#" + secondaryColor)[2] - 1.1, 0)}%;
|
||||||
|
--primary-630-hsl: ${HexToHSL("#" + secondaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + secondaryColor)[1]}%) ${HexToHSL("#" + secondaryColor)[2]}%;
|
||||||
|
--primary-600-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + primaryColor)[1]}%) ${HexToHSL("#" + primaryColor)[2]}%;
|
||||||
|
--primary-560-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + primaryColor)[1]}%) ${Math.min(HexToHSL("#" + primaryColor)[2] + 3.6, 100)}%;
|
||||||
|
--primary-530-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[530])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%) ${Math.min(HexToHSL("#" + primaryColor)[2] + (3.6 * 2), 100)}%;
|
||||||
|
--primary-500-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[500])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%) ${Math.min(HexToHSL("#" + primaryColor)[2] + (3.6 * 3), 100)}%;${tintedText ? `\n --primary-460-hsl: 0 calc(var(--saturation-factor, 1)*0%) 50%;
|
||||||
|
--primary-430: ${HexToHSL("#" + secondaryColor)[0] === 0 ? "gray" : ((HexToHSL("#" + secondaryColor)[2] < 80) ? "hsl(" + HexToHSL("#" + secondaryColor)[0] + `, calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[430])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%), 90%)` : "hsl(" + HexToHSL("#" + secondaryColor)[0] + ", calc(var(--saturation-factor, 1)*100%), 20%)")};
|
||||||
|
--primary-400: ${HexToHSL("#" + secondaryColor)[0] === 0 ? "gray" : ((HexToHSL("#" + secondaryColor)[2] < 80) ? "hsl(" + HexToHSL("#" + secondaryColor)[0] + `, calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[400])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%), 90%)` : "hsl(" + HexToHSL("#" + secondaryColor)[0] + ", calc(var(--saturation-factor, 1)*100%), 20%)")};
|
||||||
|
--primary-360: ${HexToHSL("#" + secondaryColor)[0] === 0 ? "gray" : ((HexToHSL("#" + secondaryColor)[2] < 80) ? "hsl(" + HexToHSL("#" + secondaryColor)[0] + `, calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[360])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%), 90%)` : "hsl(" + HexToHSL("#" + secondaryColor)[0] + ", calc(var(--saturation-factor, 1)*100%), 20%)")};` : ""}
|
||||||
|
}
|
||||||
|
.emptyPage_feb902,
|
||||||
|
.scrollerContainer_dda72c,
|
||||||
|
.container__03ec9,
|
||||||
|
.header__71942 {
|
||||||
|
background-color: unset !important;
|
||||||
|
}${(Math.round(HexToHSL("#" + primaryColor)[2]) > 80) ? `\n\n/*Primary*/
|
||||||
|
.theme-dark .container_bd15da,
|
||||||
|
.theme-dark .body__616e6,
|
||||||
|
.theme-dark .toolbar__62fb5,
|
||||||
|
.theme-dark .container_e1387b,
|
||||||
|
.theme-dark .messageContent_abea64,
|
||||||
|
.theme-dark .attachButtonPlus_fd0021,
|
||||||
|
.theme-dark .username__0b0e7:not([style]),
|
||||||
|
.theme-dark .children_cde9af,
|
||||||
|
.theme-dark .buttonContainer__6de7e,
|
||||||
|
.theme-dark .listItem__48528,
|
||||||
|
.theme-dark .body__616e6 .caret__33d19,
|
||||||
|
.theme-dark .body__616e6 .titleWrapper_d6133e > h1,
|
||||||
|
.theme-dark .body__616e6 .icon_ae0b42 {
|
||||||
|
--white-500: black !important;
|
||||||
|
--interactive-normal: black !important;
|
||||||
|
--text-normal: black !important;
|
||||||
|
--text-muted: black !important;
|
||||||
|
--header-primary: black !important;
|
||||||
|
--header-secondary: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .contentRegionScroller__9ae20 :not(.mtk1,.mtk2,.mtk3,.mtk4,.mtk5,.mtk6,.mtk7,.mtk8,.mtk9,.monaco-editor .line-numbers) {
|
||||||
|
--white-500: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .container__6b2e5,
|
||||||
|
.theme-dark .container__03ec9,
|
||||||
|
.theme-dark .header__71942 {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .container__26baa {
|
||||||
|
--channel-icon: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .callContainer__1477d {
|
||||||
|
--white-500: ${(HexToHSL("#" + tertiaryColor)[2] > 80) ? "black" : "white"} !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .channelTextArea_c2094b {
|
||||||
|
--text-normal: ${(HexToHSL("#" + primaryColor)[2] + 3.6 > 80) ? "black" : "white"};
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .placeholder_dec8c7 {
|
||||||
|
--channel-text-area-placeholder: ${(HexToHSL("#" + primaryColor)[2] + 3.6 > 80) ? "black" : "white"};
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .colorwaySelectorIcon {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .root_a28985 > .header__5e5a6 > h1 {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
/*End Primary*/`: ""}${(HexToHSL("#" + secondaryColor)[2] > 80) ? `\n\n/*Secondary*/
|
||||||
|
.theme-dark .wrapper__3c6d5 *,
|
||||||
|
.theme-dark .sidebar_e031be *:not(.hasBanner__04337 *),
|
||||||
|
.theme-dark .members__573eb *:not([style]),
|
||||||
|
.theme-dark .sidebarRegionScroller__8113e *,
|
||||||
|
.theme-dark .header__8e271,
|
||||||
|
.theme-dark .lookFilled__950dd.colorPrimary_ebe632 {
|
||||||
|
--white-500: black !important;
|
||||||
|
--channels-default: black !important;
|
||||||
|
--channel-icon: black !important;
|
||||||
|
--interactive-normal: var(--white-500);
|
||||||
|
--interactive-hover: var(--white-500);
|
||||||
|
--interactive-active: var(--white-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .channelRow__538ef {
|
||||||
|
background-color: var(--background-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .channelRow__538ef * {
|
||||||
|
--channel-icon: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark #app-mount .activity_bafb94 {
|
||||||
|
--channels-default: var(--white-500) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .nameTag__77ab2 {
|
||||||
|
--header-primary: black !important;
|
||||||
|
--header-secondary: ${HexToHSL("#" + secondaryColor)[0] === 0 ? "gray" : ((HexToHSL("#" + secondaryColor)[2] < 80) ? "hsl(" + HexToHSL("#" + secondaryColor)[0] + ", calc(var(--saturation-factor, 1)*100%), 90%)" : "hsl(" + HexToHSL("#" + secondaryColor)[0] + ", calc(var(--saturation-factor, 1)*100%), 20%)")} !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .bannerVisible_ef30fe .headerContent__6fcc7 {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .embedFull__14919 {
|
||||||
|
--text-normal: black;
|
||||||
|
}
|
||||||
|
/*End Secondary*/`: ""}${HexToHSL("#" + tertiaryColor)[2] > 80 ? `\n\n/*Tertiary*/
|
||||||
|
.theme-dark .winButton_f17fb6,
|
||||||
|
.theme-dark .searchBar__310d8 *,
|
||||||
|
.theme-dark .wordmarkWindows_ffbc5e,
|
||||||
|
.theme-dark .searchBar__5a20a *,
|
||||||
|
.theme-dark .searchBarComponent__8f95f {
|
||||||
|
--white-500: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark [style="background-color: var(--background-secondary);"] {
|
||||||
|
color: ${HexToHSL("#" + secondaryColor)[2] > 80 ? "black" : "white"};
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .popout__24e32 > * {
|
||||||
|
--interactive-normal: black !important;
|
||||||
|
--header-secondary: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-dark .tooltip__7b090 {
|
||||||
|
--text-normal: black !important;
|
||||||
|
}
|
||||||
|
.theme-dark .children_cde9af .icon_ae0b42 {
|
||||||
|
color: var(--interactive-active) !important;
|
||||||
|
}
|
||||||
|
/*End Tertiary*/`: ""}${HexToHSL("#" + accentColor)[2] > 80 ? `\n\n/*Accent*/
|
||||||
|
.selected_aded59 *,
|
||||||
|
.selected_ae80f7 *,
|
||||||
|
#app-mount .lookFilled__950dd.colorBrand__27d57:not(.buttonColor__7bad9),
|
||||||
|
.colorDefault_e361cf.focused_dcafb9,
|
||||||
|
.row__9e25f:hover,
|
||||||
|
.colorwayInfoIcon,
|
||||||
|
.checkmarkCircle_b1b1cc > circle {
|
||||||
|
--white-500: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ColorwaySelectorBtn:hover .vc-pallete-icon {
|
||||||
|
color: #000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root:root {
|
||||||
|
--mention-foreground: black !important;
|
||||||
|
}
|
||||||
|
/*End Accent*/`: ""}`;
|
||||||
|
return colorwayCss;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPreset(primaryColor?: string, secondaryColor?: string, tertiaryColor?: string, accentColor?: string) {
|
||||||
|
function cyan(discordSaturation = false) {
|
||||||
|
return `:root:root {
|
||||||
|
--cyan-accent-color: ${"#" + accentColor};
|
||||||
|
--cyan-background-primary: hsl(${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + primaryColor)[1]}%) ${HexToHSL("#" + primaryColor)[2]}%/40%);
|
||||||
|
--cyan-background-secondary: hsl(${HexToHSL("#" + tertiaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + tertiaryColor)[1]}%) ${Math.min(HexToHSL("#" + tertiaryColor)[2] + (3.6 * 2), 100)}%);
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function virtualBoy(discordSaturation = false) {
|
||||||
|
return `:root:root {
|
||||||
|
--VBaccent: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + accentColor)[1]}%) ${HexToHSL("#" + accentColor)[2]}%;
|
||||||
|
--VBaccent-muted: ${HexToHSL("#" + tertiaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + tertiaryColor)[1]}%) ${Math.max(((HexToHSL("#" + tertiaryColor)[2]) - 10), 0)}%;
|
||||||
|
--VBaccent-dimmest: ${HexToHSL("#" + tertiaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + tertiaryColor)[1]}%) ${Math.min((HexToHSL("#" + tertiaryColor)[2] + (3.6 * 5) - 3), 100)}%;
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function modular(discordSaturation = false) {
|
||||||
|
return `:root:root {
|
||||||
|
--modular-hue: ${HexToHSL("#" + accentColor)[0]};
|
||||||
|
--modular-saturation: calc(var(--saturation-factor, 1)${HexToHSL("#" + accentColor)[1]}%);
|
||||||
|
--modular-lightness: ${HexToHSL("#" + accentColor)[2]}%;
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function solana(discordSaturation = false) {
|
||||||
|
return `:root:root {
|
||||||
|
--accent-hue: ${HexToHSL("#" + accentColor)[0]};
|
||||||
|
--accent-saturation: calc(var(--saturation-factor, 1)${HexToHSL("#" + accentColor)[1]}%);
|
||||||
|
--accent-brightness: ${HexToHSL("#" + accentColor)[2]}%;
|
||||||
|
--background-accent-hue: ${HexToHSL("#" + primaryColor)[0]};
|
||||||
|
--background-accent-saturation: calc(var(--saturation-factor, 1)${HexToHSL("#" + primaryColor)[1]}%);
|
||||||
|
--background-accent-brightness: ${HexToHSL("#" + primaryColor)[2]}%;
|
||||||
|
--background-overlay-opacity: 0%;
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gradientType1(discordSaturation = false) {
|
||||||
|
return `${gradientBase(accentColor, discordSaturation)}
|
||||||
|
--custom-theme-background: linear-gradient(239.16deg, #${primaryColor} 10.39%, #${secondaryColor} 26.87%, #${tertiaryColor} 48.31%, hsl(${HexToHSL("#" + secondaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + secondaryColor)[1]}%) ${Math.min(HexToHSL("#" + secondaryColor)[2] + 3.6, 100)}%) 64.98%, #${primaryColor} 92.5%);
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gradientType2(discordSaturation = false) {
|
||||||
|
return `${gradientBase(accentColor, discordSaturation)}
|
||||||
|
--custom-theme-background: linear-gradient(48.17deg, #${primaryColor} 11.21%, #${secondaryColor} 61.92%);
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hueRotation(discordSaturation = false) {
|
||||||
|
return `:root:root {
|
||||||
|
--brand-100-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[100])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[100]) * 10) / 10, 0)};
|
||||||
|
--brand-130-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[130])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[130]) * 10) / 10, 0)}%;
|
||||||
|
--brand-160-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[160])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[160]) * 10) / 10, 0)}%;
|
||||||
|
--brand-200-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[200])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[200]) * 10) / 10, 0)}%;
|
||||||
|
--brand-230-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[230])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[230]) * 10) / 10, 0)}%;
|
||||||
|
--brand-260-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[260])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[260]) * 10) / 10, 0)}%;
|
||||||
|
--brand-300-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[300])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[300]) * 10) / 10, 0)}%;
|
||||||
|
--brand-330-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[330])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[330]) * 10) / 10, 0)}%;
|
||||||
|
--brand-345-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[345])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[345]) * 10) / 10, 0)}%;
|
||||||
|
--brand-360-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[360])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[360]) * 10) / 10, 0)}%;
|
||||||
|
--brand-400-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[400])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[400]) * 10) / 10, 0)}%;
|
||||||
|
--brand-430-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[430])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[430]) * 10) / 10, 0)}%;
|
||||||
|
--brand-460-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[460])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[460]) * 10) / 10, 0)}%;
|
||||||
|
--brand-500-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + accentColor)[1]}%) ${HexToHSL("#" + accentColor)[2]}%;
|
||||||
|
--brand-530-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[530])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[530]) * 10) / 10, 100)}%;
|
||||||
|
--brand-560-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[560])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[560]) * 10) / 10, 100)}%;
|
||||||
|
--brand-600-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[600])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[600]) * 10) / 10, 100)}%;
|
||||||
|
--brand-630-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[630])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[630]) * 10) / 10, 100)}%;
|
||||||
|
--brand-660-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[660])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[660]) * 10) / 10, 100)}%;
|
||||||
|
--brand-700-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[700])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[700]) * 10) / 10, 100)}%;
|
||||||
|
--brand-730-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[730])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[730]) * 10) / 10, 100)}%;
|
||||||
|
--brand-760-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[760])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[760]) * 10) / 10, 100)}%;
|
||||||
|
--brand-800-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[800])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[800]) * 10) / 10, 100)}%;
|
||||||
|
--brand-830-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[830])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[830]) * 10) / 10, 100)}%;
|
||||||
|
--brand-860-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[860])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[860]) * 10) / 10, 100)}%;
|
||||||
|
--brand-900-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[900])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[900]) * 10) / 10, 100)}%;
|
||||||
|
--primary-800-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*12%) 7%;
|
||||||
|
--primary-730-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*10%) 13%;
|
||||||
|
--primary-700-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*10%) 13%;
|
||||||
|
--primary-660-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*11%) 15%;
|
||||||
|
--primary-645-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*11%) 16%;
|
||||||
|
--primary-630-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*11%) 18%;
|
||||||
|
--primary-600-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*11%) 21%;
|
||||||
|
--primary-560-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*11%) 24%;
|
||||||
|
--primary-530-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*11%) 24%;
|
||||||
|
--primary-500-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*11%) 24%;
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function accentSwap(discordSaturation = false) {
|
||||||
|
return `:root:root {
|
||||||
|
--brand-100-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[100])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[100]) * 10) / 10, 0)};
|
||||||
|
--brand-130-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[130])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[130]) * 10) / 10, 0)}%;
|
||||||
|
--brand-160-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[160])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[160]) * 10) / 10, 0)}%;
|
||||||
|
--brand-200-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[200])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[200]) * 10) / 10, 0)}%;
|
||||||
|
--brand-230-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[230])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[230]) * 10) / 10, 0)}%;
|
||||||
|
--brand-260-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[260])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[260]) * 10) / 10, 0)}%;
|
||||||
|
--brand-300-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[300])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[300]) * 10) / 10, 0)}%;
|
||||||
|
--brand-330-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[330])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[330]) * 10) / 10, 0)}%;
|
||||||
|
--brand-345-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[345])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[345]) * 10) / 10, 0)}%;
|
||||||
|
--brand-360-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[360])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[360]) * 10) / 10, 0)}%;
|
||||||
|
--brand-400-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[400])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[400]) * 10) / 10, 0)}%;
|
||||||
|
--brand-430-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[430])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[430]) * 10) / 10, 0)}%;
|
||||||
|
--brand-460-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[460])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[460]) * 10) / 10, 0)}%;
|
||||||
|
--brand-500-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + accentColor)[1]}%) ${HexToHSL("#" + accentColor)[2]}%;
|
||||||
|
--brand-530-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[530])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[530]) * 10) / 10, 100)}%;
|
||||||
|
--brand-560-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[560])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[560]) * 10) / 10, 100)}%;
|
||||||
|
--brand-600-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[600])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[600]) * 10) / 10, 100)}%;
|
||||||
|
--brand-630-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[630])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[630]) * 10) / 10, 100)}%;
|
||||||
|
--brand-660-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[660])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[660]) * 10) / 10, 100)}%;
|
||||||
|
--brand-700-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[700])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[700]) * 10) / 10, 100)}%;
|
||||||
|
--brand-730-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[730])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[730]) * 10) / 10, 100)}%;
|
||||||
|
--brand-760-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[760])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[760]) * 10) / 10, 100)}%;
|
||||||
|
--brand-800-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[800])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[800]) * 10) / 10, 100)}%;
|
||||||
|
--brand-830-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[830])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[830]) * 10) / 10, 100)}%;
|
||||||
|
--brand-860-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[860])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[860]) * 10) / 10, 100)}%;
|
||||||
|
--brand-900-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[900])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.min(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[900]) * 10) / 10, 100)}%;
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
cyan: {
|
||||||
|
name: "Cyan",
|
||||||
|
preset: cyan,
|
||||||
|
id: "cyan",
|
||||||
|
colors: ["primary", "secondary", "accent"]
|
||||||
|
},
|
||||||
|
virtualBoy: {
|
||||||
|
name: "Virtual Boy",
|
||||||
|
preset: virtualBoy,
|
||||||
|
id: "virtualBoy",
|
||||||
|
colors: ["tertiary", "accent"]
|
||||||
|
},
|
||||||
|
modular: {
|
||||||
|
name: "Modular",
|
||||||
|
preset: modular,
|
||||||
|
id: "modular",
|
||||||
|
colors: ["accent"]
|
||||||
|
},
|
||||||
|
solana: {
|
||||||
|
name: "Solana",
|
||||||
|
preset: solana,
|
||||||
|
id: "solana",
|
||||||
|
colors: ["primary", "accent"]
|
||||||
|
},
|
||||||
|
gradientType1: {
|
||||||
|
name: "Gradient Type 1",
|
||||||
|
preset: gradientType1,
|
||||||
|
id: "gradientType1",
|
||||||
|
colors: ["primary", "secondary", "tertiary", "accent"]
|
||||||
|
},
|
||||||
|
gradientType2: {
|
||||||
|
name: "Gradient Type 2",
|
||||||
|
preset: gradientType2,
|
||||||
|
id: "gradientType2",
|
||||||
|
colors: ["primary", "secondary", "accent"]
|
||||||
|
},
|
||||||
|
hueRotation: {
|
||||||
|
name: "Hue Rotation",
|
||||||
|
preset: hueRotation,
|
||||||
|
id: "hueRotation",
|
||||||
|
colors: ["accent"]
|
||||||
|
},
|
||||||
|
accentSwap: {
|
||||||
|
name: "Accent Swap",
|
||||||
|
preset: accentSwap,
|
||||||
|
id: "accentSwap",
|
||||||
|
colors: ["accent"]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
225
src/userplugins/DiscordColorways/index.tsx
Normal file
225
src/userplugins/DiscordColorways/index.tsx
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import { addAccessory, removeAccessory } from "@api/MessageAccessories";
|
||||||
|
import { addServerListElement, removeServerListElement, ServerListRenderPosition } from "@api/ServerList";
|
||||||
|
import { disableStyle, enableStyle } from "@api/Styles";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import { openModal } from "@utils/modal";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
SettingsRouter,
|
||||||
|
} from "@webpack/common";
|
||||||
|
|
||||||
|
import ColorPickerModal from "./components/ColorPicker";
|
||||||
|
import ColorwaysButton from "./components/ColorwaysButton";
|
||||||
|
import CreatorModal from "./components/CreatorModal";
|
||||||
|
import SelectorModal from "./components/SelectorModal";
|
||||||
|
import ManageColorwaysPage from "./components/SettingsTabs/ManageColorwaysPage";
|
||||||
|
import OnDemandWaysPage from "./components/SettingsTabs/OnDemandPage";
|
||||||
|
import SelectorPage from "./components/SettingsTabs/SelectorPage";
|
||||||
|
import SettingsPage from "./components/SettingsTabs/SettingsPage";
|
||||||
|
import Spinner from "./components/Spinner";
|
||||||
|
import { defaultColorwaySource } from "./constants";
|
||||||
|
import style from "./style.css?managed";
|
||||||
|
import { ColorPickerProps } from "./types";
|
||||||
|
|
||||||
|
export let ColorPicker: React.FunctionComponent<ColorPickerProps> = () => {
|
||||||
|
return <Spinner className="colorways-creator-module-warning" />;
|
||||||
|
};
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const [
|
||||||
|
customColorways,
|
||||||
|
colorwaySourcesFiles,
|
||||||
|
showColorwaysButton,
|
||||||
|
onDemandWays,
|
||||||
|
onDemandWaysTintedText,
|
||||||
|
useThinMenuButton,
|
||||||
|
onDemandWaysDiscordSaturation,
|
||||||
|
onDemandWaysColorArray
|
||||||
|
] = await DataStore.getMany([
|
||||||
|
"customColorways",
|
||||||
|
"colorwaySourceFiles",
|
||||||
|
"showColorwaysButton",
|
||||||
|
"onDemandWays",
|
||||||
|
"onDemandWaysTintedText",
|
||||||
|
"useThinMenuButton",
|
||||||
|
"onDemandWaysDiscordSaturation",
|
||||||
|
"onDemandWaysColorArray"
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!customColorways)
|
||||||
|
DataStore.set("customColorways", []);
|
||||||
|
|
||||||
|
if (!colorwaySourcesFiles)
|
||||||
|
DataStore.set("colorwaySourceFiles", [defaultColorwaySource]);
|
||||||
|
|
||||||
|
if (!showColorwaysButton)
|
||||||
|
DataStore.set("showColorwaysButton", false);
|
||||||
|
|
||||||
|
if (!onDemandWays)
|
||||||
|
DataStore.set("onDemandWays", false);
|
||||||
|
|
||||||
|
if (!onDemandWaysTintedText)
|
||||||
|
DataStore.set("onDemandWaysTintedText", true);
|
||||||
|
|
||||||
|
if (!useThinMenuButton)
|
||||||
|
DataStore.set("useThinMenuButton", false);
|
||||||
|
|
||||||
|
if (!onDemandWaysDiscordSaturation)
|
||||||
|
DataStore.set("onDemandWaysDiscordSaturation", false);
|
||||||
|
|
||||||
|
if (!onDemandWaysColorArray)
|
||||||
|
DataStore.set("onDemandWaysColorArray", ["313338", "2b2d31", "1e1f22", "5865f2"]);
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
export const ColorwayCSS = {
|
||||||
|
get: () => document.getElementById("activeColorwayCSS")?.textContent || "",
|
||||||
|
set: (e: string) => {
|
||||||
|
if (!document.getElementById("activeColorwayCSS")) {
|
||||||
|
var activeColorwayCSS: HTMLStyleElement =
|
||||||
|
document.createElement("style");
|
||||||
|
activeColorwayCSS.id = "activeColorwayCSS";
|
||||||
|
activeColorwayCSS.textContent = e;
|
||||||
|
document.head.append(activeColorwayCSS);
|
||||||
|
} else document.getElementById("activeColorwayCSS")!.textContent = e;
|
||||||
|
},
|
||||||
|
remove: () => document.getElementById("activeColorwayCSS")!.remove(),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const versionData = {
|
||||||
|
pluginVersion: "5.6.1",
|
||||||
|
creatorVersion: "1.18",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "DiscordColorways",
|
||||||
|
description:
|
||||||
|
"A plugin that offers easy access to simple color schemes/themes for Discord, also known as Colorways",
|
||||||
|
authors: [{
|
||||||
|
name: "DaBluLite",
|
||||||
|
id: 582170007505731594n
|
||||||
|
}, Devs.ImLvna],
|
||||||
|
dependencies: ["ServerListAPI", "MessageAccessoriesAPI"],
|
||||||
|
pluginVersion: versionData.pluginVersion,
|
||||||
|
creatorVersion: versionData.creatorVersion,
|
||||||
|
toolboxActions: {
|
||||||
|
"Change Colorway": () => openModal(props => <SelectorModal modalProps={props} />),
|
||||||
|
"Open Colorway Creator": () => openModal(props => <CreatorModal modalProps={props} />),
|
||||||
|
"Open Color Stealer": () => openModal(props => <ColorPickerModal modalProps={props} />),
|
||||||
|
"Open Settings": () => SettingsRouter.open("ColorwaysSettings"),
|
||||||
|
"Open On-Demand Settings": () => SettingsRouter.open("ColorwaysOnDemand"),
|
||||||
|
"Manage Colorways...": () => SettingsRouter.open("ColorwaysManagement"),
|
||||||
|
},
|
||||||
|
patches: [
|
||||||
|
// Credits to Kyuuhachi for the BetterSettings plugin patches
|
||||||
|
{
|
||||||
|
find: "this.renderArtisanalHack()",
|
||||||
|
replacement: {
|
||||||
|
match: /createPromise:\(\)=>([^:}]*?),webpackId:"\d+",name:(?!="CollectiblesShop")"[^"]+"/g,
|
||||||
|
replace: "$&,_:$1",
|
||||||
|
predicate: () => true
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "Messages.USER_SETTINGS_WITH_BUILD_OVERRIDE.format",
|
||||||
|
replacement: {
|
||||||
|
match: /(?<=(\i)\(this,"handleOpenSettingsContextMenu",.{0,100}?openContextMenuLazy.{0,100}?(await Promise\.all[^};]*?\)\)).*?,)(?=\1\(this)/,
|
||||||
|
replace: "(async ()=>$2)(),"
|
||||||
|
},
|
||||||
|
predicate: () => true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "colorPickerFooter:",
|
||||||
|
replacement: {
|
||||||
|
match: /function (\i).{0,200}colorPickerFooter:/,
|
||||||
|
replace: "$self.ColorPicker=$1;$&",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: "Messages.ACTIVITY_SETTINGS",
|
||||||
|
replacement: {
|
||||||
|
match: /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS\}/,
|
||||||
|
replace: "...$self.makeSettingsCategories($1),$&"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
set ColorPicker(e) {
|
||||||
|
ColorPicker = e;
|
||||||
|
},
|
||||||
|
|
||||||
|
makeSettingsCategories(SectionTypes: Record<string, unknown>) {
|
||||||
|
console.log(SectionTypes);
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
section: SectionTypes.HEADER,
|
||||||
|
label: "DiscordColorways",
|
||||||
|
className: "vc-settings-header"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
section: "ColorwaysSelector",
|
||||||
|
label: "Colorways",
|
||||||
|
element: SelectorPage,
|
||||||
|
className: "dc-colorway-selector"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
section: "ColorwaysSettings",
|
||||||
|
label: "Settings",
|
||||||
|
element: SettingsPage,
|
||||||
|
className: "dc-colorway-settings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
section: "ColorwaysOnDemand",
|
||||||
|
label: "On-Demand",
|
||||||
|
element: OnDemandWaysPage,
|
||||||
|
className: "dc-colorway-ondemand"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
section: "ColorwaysManagement",
|
||||||
|
label: "Manage...",
|
||||||
|
element: ManageColorwaysPage,
|
||||||
|
className: "dc-colorway-management"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
section: SectionTypes.DIVIDER
|
||||||
|
}
|
||||||
|
].filter(Boolean);
|
||||||
|
},
|
||||||
|
|
||||||
|
ColorwaysButton: () => <ColorwaysButton />,
|
||||||
|
|
||||||
|
async start() {
|
||||||
|
addServerListElement(ServerListRenderPosition.In, this.ColorwaysButton);
|
||||||
|
|
||||||
|
enableStyle(style);
|
||||||
|
ColorwayCSS.set((await DataStore.get("actveColorway")) || "");
|
||||||
|
|
||||||
|
addAccessory("colorways-btn", props => {
|
||||||
|
if (String(props.message.content).match(/colorway:[0-9a-f]{0,71}/))
|
||||||
|
return <Button onClick={() => {
|
||||||
|
openModal(propss => (
|
||||||
|
<CreatorModal
|
||||||
|
modalProps={propss}
|
||||||
|
colorwayID={String(props.message.content).match(/colorway:[0-9a-f]{0,71}/)![0]}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
}} size={Button.Sizes.SMALL} color={Button.Colors.PRIMARY}>Add this Colorway...</Button>;
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stop() {
|
||||||
|
removeServerListElement(ServerListRenderPosition.In, this.ColorwaysButton);
|
||||||
|
|
||||||
|
disableStyle(style);
|
||||||
|
ColorwayCSS.remove();
|
||||||
|
removeAccessory("colorways-btn");
|
||||||
|
},
|
||||||
|
});
|
1214
src/userplugins/DiscordColorways/style.css
Normal file
1214
src/userplugins/DiscordColorways/style.css
Normal file
File diff suppressed because it is too large
Load diff
29
src/userplugins/DiscordColorways/types.ts
Normal file
29
src/userplugins/DiscordColorways/types.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface Colorway {
|
||||||
|
name: string,
|
||||||
|
"dc-import": string,
|
||||||
|
accent: string,
|
||||||
|
primary: string,
|
||||||
|
secondary: string,
|
||||||
|
tertiary: string,
|
||||||
|
original?: boolean,
|
||||||
|
author: string,
|
||||||
|
authorID: string,
|
||||||
|
colors?: string[],
|
||||||
|
isGradient?: boolean,
|
||||||
|
sourceUrl?: string,
|
||||||
|
sourceName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ColorPickerProps {
|
||||||
|
color: number;
|
||||||
|
showEyeDropper: boolean;
|
||||||
|
suggestedColors: string[];
|
||||||
|
label: any;
|
||||||
|
onChange(color: number): void;
|
||||||
|
}
|
133
src/userplugins/DiscordColorways/utils.ts
Normal file
133
src/userplugins/DiscordColorways/utils.ts
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2023 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function HexToHSL(H: string) {
|
||||||
|
let r: any = 0, g: any = 0, b: any = 0;
|
||||||
|
if (H.length === 4) r = "0x" + H[1] + H[1], g = "0x" + H[2] + H[2], b = "0x" + H[3] + H[3];
|
||||||
|
else if (H.length === 7) {
|
||||||
|
r = "0x" + H[1] + H[2];
|
||||||
|
g = "0x" + H[3] + H[4];
|
||||||
|
b = "0x" + H[5] + H[6];
|
||||||
|
}
|
||||||
|
r /= 255, g /= 255, b /= 255;
|
||||||
|
var cmin = Math.min(r, g, b),
|
||||||
|
cmax = Math.max(r, g, b),
|
||||||
|
delta = cmax - cmin,
|
||||||
|
h = 0,
|
||||||
|
s = 0,
|
||||||
|
l = 0;
|
||||||
|
if (delta === 0) h = 0;
|
||||||
|
else if (cmax === r) h = ((g - b) / delta) % 6;
|
||||||
|
else if (cmax === g) h = (b - r) / delta + 2;
|
||||||
|
else h = (r - g) / delta + 4;
|
||||||
|
h = Math.round(h * 60);
|
||||||
|
if (h < 0) h += 360;
|
||||||
|
l = (cmax + cmin) / 2;
|
||||||
|
s = delta === 0
|
||||||
|
? 0
|
||||||
|
: delta / (1 - Math.abs(2 * l - 1));
|
||||||
|
s = +(s * 100).toFixed(1);
|
||||||
|
l = +(l * 100).toFixed(1);
|
||||||
|
|
||||||
|
return [Math.round(h), Math.round(s), Math.round(l)];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const canonicalizeHex = (hex: string) => {
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
const ctx = canvas.getContext("2d")!;
|
||||||
|
|
||||||
|
ctx.fillStyle = hex;
|
||||||
|
hex = ctx.fillStyle;
|
||||||
|
canvas.remove();
|
||||||
|
|
||||||
|
return hex;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const stringToHex = (str: string) => {
|
||||||
|
let hex = "";
|
||||||
|
for (
|
||||||
|
let i = 0;
|
||||||
|
i < str.length;
|
||||||
|
i++
|
||||||
|
) {
|
||||||
|
const charCode = str.charCodeAt(i);
|
||||||
|
const hexValue = charCode.toString(16);
|
||||||
|
hex += hexValue.padStart(2, "0");
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hexToString = (hex: string) => {
|
||||||
|
let str = "";
|
||||||
|
for (let i = 0; i < hex.length; i += 2) {
|
||||||
|
const hexValue = hex.substr(i, 2);
|
||||||
|
const decimalValue = parseInt(hexValue, 16);
|
||||||
|
str += String.fromCharCode(decimalValue);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getHex(str: string): string {
|
||||||
|
const color = Object.assign(
|
||||||
|
document.createElement("canvas").getContext("2d") as {},
|
||||||
|
{ fillStyle: str }
|
||||||
|
).fillStyle;
|
||||||
|
if (color.includes("rgba(")) {
|
||||||
|
return getHex(String([...color.split(",").slice(0, 3), ")"]).replace(",)", ")").replace("a", ""));
|
||||||
|
} else {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFontOnBg(bgColor: string) {
|
||||||
|
var color = (bgColor.charAt(0) === "#") ? bgColor.substring(1, 7) : bgColor;
|
||||||
|
var r = parseInt(color.substring(0, 2), 16);
|
||||||
|
var g = parseInt(color.substring(2, 4), 16);
|
||||||
|
var b = parseInt(color.substring(4, 6), 16);
|
||||||
|
return (((r * 0.299) + (g * 0.587) + (b * 0.114)) > 186) ?
|
||||||
|
"#000000" : "#ffffff";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function $e(funcArray: Array<(...vars: any) => void>, ...vars: any[]) {
|
||||||
|
funcArray.forEach(e => e(vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hslToHex(h: number, s: number, l: number) {
|
||||||
|
h /= 360;
|
||||||
|
s /= 100;
|
||||||
|
l /= 100;
|
||||||
|
let r: any, g: any, b: any;
|
||||||
|
if (s === 0) {
|
||||||
|
r = g = b = l; // achromatic
|
||||||
|
} else {
|
||||||
|
const hue2rgb = (p: number, q: number, t: number) => {
|
||||||
|
if (t < 0) t += 1;
|
||||||
|
if (t > 1) t -= 1;
|
||||||
|
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
||||||
|
if (t < 1 / 2) return q;
|
||||||
|
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||||
|
const p = 2 * l - q;
|
||||||
|
r = hue2rgb(p, q, h + 1 / 3);
|
||||||
|
g = hue2rgb(p, q, h);
|
||||||
|
b = hue2rgb(p, q, h - 1 / 3);
|
||||||
|
}
|
||||||
|
const toHex = (x: number) => {
|
||||||
|
const hex = Math.round(x * 255).toString(16);
|
||||||
|
return hex.length === 1 ? "0" + hex : hex;
|
||||||
|
};
|
||||||
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rgbToHex(r: number, g: number, b: number) {
|
||||||
|
const toHex = (x: number) => {
|
||||||
|
const hex = Math.round(x * 255).toString(16);
|
||||||
|
return hex.length === 1 ? "0" + hex : hex;
|
||||||
|
};
|
||||||
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
||||||
|
}
|
22
src/userplugins/QuickReactFrequents/index.ts
Normal file
22
src/userplugins/QuickReactFrequents/index.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2024 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "QuickReactFrequents",
|
||||||
|
description: "Make quick react use top frecency emojis instead of favourites",
|
||||||
|
authors: [Devs.Ven],
|
||||||
|
|
||||||
|
patches: [{
|
||||||
|
find: "this.favoriteEmojisWithoutFetchingLatest.concat",
|
||||||
|
replacement: {
|
||||||
|
match: "this.favoriteEmojisWithoutFetchingLatest.concat",
|
||||||
|
replace: "[].concat"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
Loading…
Reference in a new issue