diff --git a/src/plugins/customFolderIcons/README.md b/src/plugins/customFolderIcons/README.md new file mode 100644 index 000000000..9b67e4eba --- /dev/null +++ b/src/plugins/customFolderIcons/README.md @@ -0,0 +1,14 @@ +# CustomFolderIcons + +Allows you to set custom images/svgs as folder icons + +Available as "Change Icon" in the folder context menu + +![the context menu with the "Change Icon" button](https://github.com/sadan4/Vencord/assets/117494111/3dfb843c-6964-4ac3-a0b9-8772569953d3) + +![an image of some example custom folder icons](https://github.com/sadan4/Vencord/assets/117494111/c5324ab1-3b7a-4286-8cb5-41c0ceb2ea44) + +![the modal used to customize the folder icons](https://github.com/sadan4/Vencord/assets/117494111/1426d350-56db-4687-8052-6c1b1ce873a1) + + + diff --git a/src/plugins/customFolderIcons/components.tsx b/src/plugins/customFolderIcons/components.tsx new file mode 100644 index 000000000..aab5ee129 --- /dev/null +++ b/src/plugins/customFolderIcons/components.tsx @@ -0,0 +1,124 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 sadan + * 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 settings, { folderIconsData } from "./settings"; +import { folderProp, int2rgba, setFolderData } from "./util"; + +export function ImageModal(folderProps: folderProp) { + const [data, setData] = useState(((settings.store.folderIcons ?? {}) as folderIconsData)[folderProps.folderId]?.url ?? ""); + const [size, setSize] = useState(100); + return ( + <> + { + setData(val); + }} + placeholder="https://example.com/image.png" + > + + + {data && <> +
Change the size of the folder icon
+ { + setSize(v); + }} + maxValue={200} + minValue={25} + // [25, 200] + markers={Array.apply(0, Array(176)).map((_, i) => i + 25)} + stickToMarkers={true} + keyboardStep={1} + renderMarker={() => null} /> + } + +
+ +
+ + ); +} +export function RenderPreview({ folderProps, url, size }: { folderProps: folderProp; url: string; size: number; }) { + if (!url) return null; + return ( +
+ +
+ ); +} + +export function makeContextItem(a: folderProp) { + return ( + { + openModalLazy(async () => { + return props => ( + + +
+ Set a New Icon. +
+
+ + + +
+ You might have to hover the folder after setting in order for it to refresh. +
+
+ ); + }, + { + modalKey: "custom-folder-icon" + }); + }}/> + ); +} diff --git a/src/plugins/customFolderIcons/index.tsx b/src/plugins/customFolderIcons/index.tsx new file mode 100644 index 000000000..b86ae09bf --- /dev/null +++ b/src/plugins/customFolderIcons/index.tsx @@ -0,0 +1,60 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 sadan + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; + +import { makeContextItem } from "./components"; +import settings, { folderIconsData } from "./settings"; +import { folderProp, int2rgba } from "./util"; + +export default definePlugin({ + settings, + name: "CustomFolderIcons", + description: "Customize folder icons with any png", + authors: [ + Devs.sadan + ], + patches: [ + { + find: ".expandedFolderIconWrapper", + replacement: { + match: /(return.{0,80}expandedFolderIconWrapper.*,)(\(0,..jsxs\)\(.*]}\))/, + replace: "$1$self.shouldReplace(arguments[0])?$self.replace(arguments[0]):$2" + } + } + ], + contextMenus: { + "guild-context": (menuItems, props: folderProp) => { + if(!("folderId" in props)) return; + menuItems.push(makeContextItem(props)); + } + }, + shouldReplace(props: any): boolean{ + return !!((settings.store.folderIcons as folderIconsData)?.[props.folderNode.id]?.url); + }, + replace(props: any){ + const folderSettings = (settings.store.folderIcons as folderIconsData); + if(folderSettings && folderSettings[props.folderNode.id]){ + const data = folderSettings[props.folderNode.id]; + return ( +
+ +
+ ); + } + } +}); diff --git a/src/plugins/customFolderIcons/settings.tsx b/src/plugins/customFolderIcons/settings.tsx new file mode 100644 index 000000000..dbe15526a --- /dev/null +++ b/src/plugins/customFolderIcons/settings.tsx @@ -0,0 +1,29 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 sadan + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { OptionType } from "@utils/types"; + +export interface folderIcon{ + url: string, + size: number, +} +export type folderIconsData = Record; + +const settings = definePluginSettings({ + solidIcon: { + type: OptionType.BOOLEAN, + default: false, + description: "Use a solid background on the background of the image" + }, + folderIcons: { + type: OptionType.COMPONENT, + hidden: true, + description: "folder icon settings", + component: () => <> + } +}); +export default settings; diff --git a/src/plugins/customFolderIcons/util.tsx b/src/plugins/customFolderIcons/util.tsx new file mode 100644 index 000000000..efb37e3dc --- /dev/null +++ b/src/plugins/customFolderIcons/util.tsx @@ -0,0 +1,29 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 sadan + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import settings, { folderIcon, folderIconsData } from "./settings"; + +export async function setFolderData(props: folderProp, newData: folderIcon) { + if(!settings.store.folderIcons){ + settings.store.folderIcons = {}; + } + const folderSettings = (settings.store.folderIcons as folderIconsData); + folderSettings[props.folderId] = newData; +} +export interface folderProp { + folderId: string; + folderColor: number; +} +/** + * @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})`; +}