From df29fa3f8d06fa7f10df3293cb2770b2efa2cc29 Mon Sep 17 00:00:00 2001 From: Beebles <102569435+beebls@users.noreply.github.com> Date: Sat, 1 Jul 2023 23:26:26 -0600 Subject: [PATCH] feat: Preset Menu Dropdown Next to Profiles/Presets, there is a dropdown Currently the only option is delete preset, however "Rename Preset" will likely be added soon --- backend/backendHelpers/deletePreset.ts | 15 ++++ backend/backendHelpers/index.ts | 1 + components/ManageThemes/YourProfilesList.tsx | 7 +- .../Presets/PresetSelectionDropdown.tsx | 80 +++++++++++++------ components/Primitives/MenuDropdown.tsx | 70 ++++++++++++++++ components/Primitives/Tooltip.tsx | 7 +- components/Primitives/index.ts | 1 + 7 files changed, 154 insertions(+), 27 deletions(-) create mode 100644 backend/backendHelpers/deletePreset.ts create mode 100644 components/Primitives/MenuDropdown.tsx diff --git a/backend/backendHelpers/deletePreset.ts b/backend/backendHelpers/deletePreset.ts new file mode 100644 index 0000000..20d4265 --- /dev/null +++ b/backend/backendHelpers/deletePreset.ts @@ -0,0 +1,15 @@ +import { Theme } from "ThemeTypes"; +import { changePreset } from "./changePreset"; +import { deleteTheme } from "backend/pythonMethods"; + +export async function deletePreset( + presetName: string, + themes: Theme[], + refreshThemes: (e?: boolean) => void +) { + if (themes.find((e) => e.name === presetName)!.enabled) { + await changePreset("Default Profile", themes); + } + await deleteTheme(presetName); + refreshThemes(); +} diff --git a/backend/backendHelpers/index.ts b/backend/backendHelpers/index.ts index 81b459d..768bcca 100644 --- a/backend/backendHelpers/index.ts +++ b/backend/backendHelpers/index.ts @@ -1 +1,2 @@ export * from "./changePreset"; +export * from "./deletePreset"; diff --git a/components/ManageThemes/YourProfilesList.tsx b/components/ManageThemes/YourProfilesList.tsx index ef1f281..b8e700e 100644 --- a/components/ManageThemes/YourProfilesList.tsx +++ b/components/ManageThemes/YourProfilesList.tsx @@ -3,6 +3,7 @@ import { ManageThemeCard } from "./ManageThemeCard"; import { themeContext } from "@contexts/themeContext"; import { LocalThemeStatus } from "@pages/manage-themes"; import { Flags, MinimalCSSThemeInfo, Theme } from "ThemeTypes"; +import { deletePreset } from "backend"; export function YourProfilesList({ updateStatuses, @@ -15,7 +16,7 @@ export function YourProfilesList({ handleUninstall: (e: Theme) => void; handleUpdate: (e: MinimalCSSThemeInfo) => void; }) { - const { themes } = useContext(themeContext); + const { themes, refreshThemes } = useContext(themeContext); const userChangeablePresets = themes.filter( (e) => e.flags.includes(Flags.isPreset) && e.name !== "Default Profile" ); @@ -32,7 +33,9 @@ export function YourProfilesList({ themeData={e} updateStatuses={updateStatuses} uninstalling={uninstalling} - handleUninstall={handleUninstall} + handleUninstall={(e: Theme) => { + deletePreset(e.name, themes, refreshThemes); + }} handleUpdate={handleUpdate} /> ))} diff --git a/components/Presets/PresetSelectionDropdown.tsx b/components/Presets/PresetSelectionDropdown.tsx index 45ba0c1..ddfc1bf 100644 --- a/components/Presets/PresetSelectionDropdown.tsx +++ b/components/Presets/PresetSelectionDropdown.tsx @@ -1,39 +1,71 @@ import { useContext, useMemo, useState } from "react"; -import { CreatePresetModal, RadioDropdown } from ".."; +import { CreatePresetModal, RadioDropdown, Tooltip } from ".."; import { themeContext } from "@contexts/themeContext"; import { Flags } from "ThemeTypes"; -import { changePreset, setThemeState } from "backend"; +import { changePreset, deletePreset, setThemeState } from "backend"; +import { MenuDropdown } from "@components/Primitives/MenuDropdown"; +import { BiTrash } from "react-icons/bi"; +import { twMerge } from "tailwind-merge"; export function PresetSelectionDropdown() { - const { themes, refreshThemes } = useContext(themeContext); + const { themes, refreshThemes, selectedPreset } = useContext(themeContext); const presets = useMemo(() => themes.filter((e) => e.flags.includes(Flags.isPreset)), [themes]); const [showModal, setShowModal] = useState(false); - console.log(showModal); + console.log(selectedPreset?.name); return ( <> - {showModal && setShowModal(false)} />} - e.enabled)?.name || "Default Profile"} - options={[ - // This just ensures that default profile is the first result - "Default Profile", - ...presets.map((e) => e.name).filter((e) => e !== "Default Profile"), - "New Profile", - ]} - onValueChange={async (e) => { - if (e === "New Profile") { - setShowModal(true); - return; +
+ {showModal && setShowModal(false)} />} + e.enabled)?.name || "Default Profile"} + value={selectedPreset?.name || "Default Profile"} + options={[ + // This just ensures that default profile is the first result + "Default Profile", + ...presets.map((e) => e.name).filter((e) => e !== "Default Profile"), + "New Profile", + ]} + onValueChange={async (e) => { + if (e === "New Profile") { + setShowModal(true); + return; + } + await changePreset(e, themes); + refreshThemes(); + }} + /> + , + onSelect: async () => { + deletePreset(selectedPreset!.name, themes, refreshThemes); + }, + }, + ]} + triggerClass={twMerge( + "h-12 w-12 self-end rounded-xl border-2 border-borders-base1-dark bg-base-5.5-dark transition-all hover:border-borders-base2-dark", + selectedPreset?.name === "Default Profile" && "opacity-50" + )} + /> } - await changePreset(e, themes); - refreshThemes(); - }} - /> + /> +
); } diff --git a/components/Primitives/MenuDropdown.tsx b/components/Primitives/MenuDropdown.tsx new file mode 100644 index 0000000..37b47be --- /dev/null +++ b/components/Primitives/MenuDropdown.tsx @@ -0,0 +1,70 @@ +import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; +import { ReactNode, useContext } from "react"; +import { twMerge } from "tailwind-merge"; +import { GiHamburgerMenu } from "react-icons/gi"; +import { fontContext } from "@contexts/FontContext"; + +export function MenuDropdown({ + options, + triggerClass = "", + align = "center", + triggerDisabled = false, +}: { + options: { + disabled?: boolean; + displayText: string; + icon: ReactNode; + onSelect: () => void; + }[]; + triggerClass?: string; + triggerDisabled?: boolean; + align?: "center" | "start" | "end"; +}) { + const { montserrat } = useContext(fontContext); + return ( + + + + + + +
+ + {options.map((e) => { + return ( + +
+ + {e.displayText} + + {e.icon} +
+
+ ); + })} +
+
+
+
+ ); +} diff --git a/components/Primitives/Tooltip.tsx b/components/Primitives/Tooltip.tsx index 9a0df9c..4c8f636 100644 --- a/components/Primitives/Tooltip.tsx +++ b/components/Primitives/Tooltip.tsx @@ -10,6 +10,8 @@ export function Tooltip({ arrow = false, disabled = false, content, + triggerRootClass = "", + align = "center", }: { triggerContent: ReactElement; delayDuration?: number; @@ -18,6 +20,8 @@ export function Tooltip({ disabled?: boolean; arrow?: boolean; content: ReactElement | string; + triggerRootClass?: string; + align?: "center" | "end" | "start"; }) { const { montserrat } = useContext(fontContext); const [open, setOpen] = useState(false); @@ -28,10 +32,11 @@ export function Tooltip({ onOpenChange={(open) => !disabled && setOpen(open)} delayDuration={delayDuration} > - {triggerContent} + {triggerContent}