mirror of
https://github.com/Vendicated/Vencord.git
synced 2024-09-19 22:20:34 +00:00
complete settings overhaul, still needs work. see FIXME:
This commit is contained in:
parent
f4ca72c6f6
commit
a742cc2b53
4 changed files with 173 additions and 159 deletions
121
src/plugins/customFolderIcons/components.tsx
Normal file
121
src/plugins/customFolderIcons/components.tsx
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { closeModal, ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal";
|
||||
import { Button, Menu, Slider, TextInput, useState } from "@webpack/common";
|
||||
|
||||
import { folderProp } from ".";
|
||||
import settings, { folderIconsData } from "./settings";
|
||||
import { int2rgba, setFolderUrl } from "./util";
|
||||
|
||||
export function ImageModal(folderProps: folderProp) {
|
||||
const [data, setData] = useState("");
|
||||
const [size, setSize] = useState(100);
|
||||
return (
|
||||
<>
|
||||
<TextInput onChange={(val, _n) => {
|
||||
setData(val);
|
||||
}}
|
||||
placeholder="https://example.com/image.png"
|
||||
>
|
||||
</TextInput>
|
||||
<RenderPreview folderProps={folderProps} url={data} size={size} />
|
||||
{data && <>
|
||||
<div style={{
|
||||
color: "#FFF"
|
||||
}}>Change the size of the folder icon</div>
|
||||
<Slider
|
||||
initialValue={100}
|
||||
onValueChange={(v: number) => {
|
||||
setSize(v);
|
||||
}}
|
||||
maxValue={200}
|
||||
minValue={25}
|
||||
markers={Array.apply(0, Array(176)).map((_, i) => i + 25)}
|
||||
stickToMarkers={true}
|
||||
keyboardStep={1}
|
||||
renderMarker={() => null} />
|
||||
</>}
|
||||
<Button onClick={() => {
|
||||
setFolderUrl(folderProps, {
|
||||
url: data,
|
||||
size: size
|
||||
});
|
||||
closeModal("custom-folder-icon");
|
||||
}}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<hr />
|
||||
<Button onClick={() => {
|
||||
// INFO: unset button
|
||||
const folderSettings = settings.store.folderIcons as folderIconsData;
|
||||
if (folderSettings[folderProps.folderId]) {
|
||||
folderSettings[folderProps.folderId] = null;
|
||||
}
|
||||
closeModal("custom-folder-icon");
|
||||
}}>
|
||||
Unset
|
||||
</Button>
|
||||
<hr />
|
||||
</>
|
||||
);
|
||||
}
|
||||
export function RenderPreview({ folderProps, url, size }: { folderProps: folderProp; url: string; size: number; }) {
|
||||
if (!url) return null;
|
||||
return (
|
||||
<div style={{
|
||||
width: "20vh",
|
||||
height: "20vh",
|
||||
borderRadius: "24px",
|
||||
backgroundColor: int2rgba(folderProps.folderColor, 0.4),
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
}}>
|
||||
<img src={url} width={`${size}%`} height={`${size}%`} style={{
|
||||
// borderRadius: "24px",
|
||||
}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function makeContextItem(a: folderProp) {
|
||||
return (
|
||||
<Menu.MenuItem
|
||||
id="custom-folder-icons"
|
||||
key="custom-folder-icons"
|
||||
label="Change Icon"
|
||||
action={() => {
|
||||
openModalLazy(async () => {
|
||||
return props => (
|
||||
<ModalRoot {...props}>
|
||||
<ModalHeader >
|
||||
<div style={{
|
||||
color: "white"
|
||||
}}>
|
||||
Set a New Icon.
|
||||
</div>
|
||||
</ModalHeader>
|
||||
<ModalContent>
|
||||
<ImageModal folderId={a.folderId} folderColor={a.folderColor}/>
|
||||
</ModalContent>
|
||||
<div style={{
|
||||
color: "white",
|
||||
margin: "2.5%",
|
||||
marginTop: "1%"
|
||||
}}>
|
||||
You might have to hover the folder after setting in order for it to refresh.
|
||||
</div>
|
||||
</ModalRoot>
|
||||
);
|
||||
},
|
||||
{
|
||||
modalKey: "custom-folder-icon"
|
||||
});
|
||||
}}/>
|
||||
);
|
||||
}
|
|
@ -4,31 +4,19 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { DataStore } from "@api/index";
|
||||
import { showNotification } from "@api/Notifications";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { closeModal, ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Button, Menu, Slider, TextInput, useState } from "@webpack/common";
|
||||
import settings from "./settings";
|
||||
const DATA_STORE_NAME = "CFI_DATA";
|
||||
interface folderIcon{
|
||||
url: string,
|
||||
size: number,
|
||||
}
|
||||
interface folderStoredData {
|
||||
[key: string]: folderIcon | undefined
|
||||
}
|
||||
interface folderProp {
|
||||
|
||||
import { makeContextItem } from "./components";
|
||||
import settings, { folderIconsData } from "./settings";
|
||||
import { int2rgba } from "./util";
|
||||
export interface folderProp {
|
||||
folderId: string;
|
||||
folderColor: number;
|
||||
}
|
||||
let folderData: folderStoredData;
|
||||
export default definePlugin({
|
||||
settings,
|
||||
start: async ()=>{
|
||||
folderData = await DataStore.get(DATA_STORE_NAME).catch(e => handleUpdateError(e)) || {} as folderStoredData;
|
||||
},
|
||||
name: "CustomFolderIcons",
|
||||
description: "Customize folder icons with any png",
|
||||
authors: [
|
||||
|
@ -49,15 +37,14 @@ export default definePlugin({
|
|||
menuItems.push(makeContextItem(props));
|
||||
}
|
||||
},
|
||||
shouldReplace(props: any){
|
||||
return folderData
|
||||
&& props.folderNode.id in folderData
|
||||
&& folderData[props.folderNode.id]
|
||||
&& folderData[props.folderNode.id]?.url;
|
||||
shouldReplace(props: any): boolean{
|
||||
const folderSettings = (settings.store.folderIcons as folderIconsData);
|
||||
return !!(folderSettings?.[props.folderNode.id]?.url);
|
||||
},
|
||||
replace(props: any){
|
||||
if(folderData && folderData[props.folderNode.id]){
|
||||
const data = folderData[props.folderNode.id];
|
||||
const folderSettings = (settings.store.folderIcons as folderIconsData);
|
||||
if(folderSettings && folderSettings[props.folderNode.id]){
|
||||
const data = folderSettings[props.folderNode.id];
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
|
@ -69,147 +56,14 @@ export default definePlugin({
|
|||
height: "100%"
|
||||
}}
|
||||
>
|
||||
<img src={data!.url} width={`${data!.size}%`} height={`${data!.size}%`}
|
||||
<img src={data!.url} width={`${data!.size ?? 100}%`} height={`${data!.size ?? 100}%`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
/**
|
||||
* @param rgbVal RGB value
|
||||
* @param alpha alpha bewteen zero and 1
|
||||
*/
|
||||
function int2rgba(rgbVal: number, alpha: number = 1) {
|
||||
const b = rgbVal & 0xFF,
|
||||
g = (rgbVal & 0xFF00) >>> 8,
|
||||
r = (rgbVal & 0xFF0000) >>> 16;
|
||||
return `rgba(${[r, g, b].join(",")},${alpha})`;
|
||||
}
|
||||
async function setFolderUrl(props: folderProp, url: string, size: number) {
|
||||
DataStore.get<folderStoredData>(DATA_STORE_NAME).then(data => {
|
||||
data = data ?? {} as folderStoredData;
|
||||
data[props.folderId] = {
|
||||
url: url,
|
||||
size: size
|
||||
};
|
||||
DataStore.set(DATA_STORE_NAME, data).then(() => { folderData = data; }).catch(e => {
|
||||
handleUpdateError(e);
|
||||
});
|
||||
}
|
||||
)
|
||||
.catch(e => {
|
||||
handleUpdateError(e);
|
||||
});
|
||||
}
|
||||
function RenderPreview({ folderProps, url, size }: {folderProps: folderProp, url: string, size: number}){
|
||||
if (!url) return null;
|
||||
return(
|
||||
<div style={{
|
||||
width: "20vh",
|
||||
height: "20vh",
|
||||
borderRadius: "24px",
|
||||
backgroundColor: int2rgba(folderProps.folderColor, .4),
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
}}>
|
||||
<img src={url} width={`${size}%`} height={`${size}%`} style={{
|
||||
// borderRadius: "24px",
|
||||
}}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function ImageModal(folderProps: folderProp){
|
||||
const [data, setData]= useState("");
|
||||
const [size, setSize] = useState(100);
|
||||
return(
|
||||
<>
|
||||
<TextInput onChange={(val, n) => {
|
||||
setData(val);
|
||||
}}
|
||||
placeholder="https://example.com/image.png"
|
||||
>
|
||||
</TextInput>
|
||||
<RenderPreview folderProps={folderProps} url={data} size={size}/>
|
||||
{data && <>
|
||||
<div style= {{
|
||||
color: "#FFF"
|
||||
}}>Change the size of the folder icon</div>
|
||||
<Slider
|
||||
initialValue={100}
|
||||
onValueChange={(v: number) => {
|
||||
setSize(v);
|
||||
}}
|
||||
maxValue={200}
|
||||
minValue={25}
|
||||
markers={Array.apply(0, Array(176)).map((v, i) => i+25)}
|
||||
stickToMarkers = {true}
|
||||
keyboardStep={1}
|
||||
renderMarker={() => null}
|
||||
/>
|
||||
</>}
|
||||
<Button onClick={() => {
|
||||
setFolderUrl(folderProps, data, size);
|
||||
closeModal("custom-folder-icon");
|
||||
}}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<hr />
|
||||
<Button onClick={() => {
|
||||
DataStore.get(DATA_STORE_NAME).then(data => {
|
||||
if(!data) return;
|
||||
data[folderProps.folderId] = undefined;
|
||||
DataStore.set(DATA_STORE_NAME, data).then(() => {
|
||||
folderData = data;
|
||||
}).catch(e => handleUpdateError(e));
|
||||
}).catch(e => handleUpdateError(e));
|
||||
closeModal("custom-folder-icon");
|
||||
}}>
|
||||
Unset
|
||||
</Button>
|
||||
<hr />
|
||||
</>
|
||||
);
|
||||
}
|
||||
function makeContextItem(a: folderProp) {
|
||||
return (
|
||||
<Menu.MenuItem
|
||||
id="custom-folder-icons"
|
||||
key="custom-folder-icons"
|
||||
label="Change Icon"
|
||||
action={() => {
|
||||
openModalLazy(async () => {
|
||||
return props => (
|
||||
<ModalRoot {...props}>
|
||||
<ModalHeader >
|
||||
<div style={{
|
||||
color: "white"
|
||||
}}>
|
||||
Set a New Icon.
|
||||
</div>
|
||||
</ModalHeader>
|
||||
<ModalContent>
|
||||
<ImageModal folderId={a.folderId} folderColor={a.folderColor}/>
|
||||
</ModalContent>
|
||||
<div style={{
|
||||
color: "white",
|
||||
margin: "2.5%",
|
||||
marginTop: "1%"
|
||||
}}>
|
||||
You might have to hover the folder after setting in order for it to refresh.
|
||||
</div>
|
||||
</ModalRoot>
|
||||
);
|
||||
},
|
||||
{
|
||||
modalKey: "custom-folder-icon"
|
||||
});
|
||||
}}/>
|
||||
);
|
||||
}
|
||||
function handleUpdateError(e: any) {
|
||||
export function handleUpdateError(e: any) {
|
||||
showNotification({
|
||||
title: "CustomFolderIcons: Error",
|
||||
body: "An error has occurred. Check the console for more info."
|
||||
|
|
|
@ -7,9 +7,16 @@
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { IPluginOptionComponentProps, OptionType } from "@utils/types";
|
||||
|
||||
export interface folderIcon{
|
||||
url: string,
|
||||
size: number,
|
||||
}
|
||||
export type folderIconsData = Record<string, folderIcon | null>;
|
||||
|
||||
const settings = definePluginSettings({
|
||||
folderIcons: {
|
||||
type: OptionType.COMPONENT,
|
||||
hidden: true,
|
||||
description: "guh",
|
||||
component: props => <>
|
||||
<FolderIconsSettings
|
||||
|
|
32
src/plugins/customFolderIcons/util.tsx
Normal file
32
src/plugins/customFolderIcons/util.tsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { folderProp } from ".";
|
||||
import settings, { folderIcon, folderIconsData } from "./settings";
|
||||
|
||||
export async function setFolderUrl(props: folderProp, newData: folderIcon) {
|
||||
// FIXME: https://canary.discord.com/channels/1015060230222131221/1032770730703716362/1256504513125158924
|
||||
if(!settings.store.folderIcons){
|
||||
settings.store.folderIcons = {};
|
||||
}
|
||||
const folderSettings = (settings.store.folderIcons as folderIconsData);
|
||||
const data = folderSettings[props.folderId] ?? {} as folderIcon;
|
||||
for (const k in newData){
|
||||
data[k] = newData[k];
|
||||
}
|
||||
folderSettings[props.folderId] = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rgbVal RGB value
|
||||
* @param alpha alpha bewteen zero and 1
|
||||
*/
|
||||
export function int2rgba(rgbVal: number, alpha: number = 1) {
|
||||
const b = rgbVal & 0xFF,
|
||||
g = (rgbVal & 0xFF00) >>> 8,
|
||||
r = (rgbVal & 0xFF0000) >>> 16;
|
||||
return `rgba(${[r, g, b].join(",")},${alpha})`;
|
||||
}
|
Loading…
Reference in a new issue