From 5a494c67c514e3c6138cf4a4c4dda90736fcc887 Mon Sep 17 00:00:00 2001 From: qu1ck Date: Fri, 27 Oct 2023 00:14:51 -0700 Subject: [PATCH] Add options to tweak main text/bg colors --- src/components/colorswatch.tsx | 71 ++++++++++++++++++++++++ src/components/mantinetheme.tsx | 23 ++++++-- src/components/miscbuttons.tsx | 2 +- src/components/modals/interfacepanel.tsx | 39 ++++++++++++- src/components/tables/common.tsx | 2 +- src/config.ts | 6 ++ src/{fontsize.tsx => themehooks.tsx} | 30 +++++++++- src/types/mantine.d.ts | 2 +- 8 files changed, 163 insertions(+), 12 deletions(-) create mode 100644 src/components/colorswatch.tsx rename src/{fontsize.tsx => themehooks.tsx} (70%) diff --git a/src/components/colorswatch.tsx b/src/components/colorswatch.tsx new file mode 100644 index 0000000..1aa118f --- /dev/null +++ b/src/components/colorswatch.tsx @@ -0,0 +1,71 @@ +/** + * TrguiNG - next gen remote GUI for transmission torrent daemon + * Copyright (C) 2023 qu1ck (mail at qu1ck.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import type { DefaultMantineColor } from "@mantine/core"; +import { ActionIcon, ColorSwatch, Grid, Popover, useMantineTheme } from "@mantine/core"; +import React, { useState } from "react"; + +export interface ColorSetting { + color: DefaultMantineColor, + shade: number, +} + +interface ColorChooserProps { + value: ColorSetting, + onChange: (value: ColorSetting | undefined) => void, +} + +const shades = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + +export default function ColorChooser(props: ColorChooserProps) { + const theme = useMantineTheme(); + const [opened, setOpened] = useState(false); + const swatchOutline = theme.colorScheme === "dark" ? theme.colors.gray[7] : theme.colors.dark[6]; + + return ( + + + { setOpened((o) => !o); }}> + + + + + { + props.onChange(undefined); + setOpened(false); + }}> + Reset + + + {Object.keys(theme.colors).map((color) => shades.map((shade) => ( + + { + props.onChange({ color, shade }); + setOpened(false); + }}> + + + + )))} + + + + ); +} diff --git a/src/components/mantinetheme.tsx b/src/components/mantinetheme.tsx index e9b3ad4..a6c9fbe 100644 --- a/src/components/mantinetheme.tsx +++ b/src/components/mantinetheme.tsx @@ -20,7 +20,7 @@ import { ColorSchemeProvider, Global, MantineProvider } from "@mantine/core"; import type { ColorScheme, MantineThemeOverride } from "@mantine/core"; import { useColorScheme } from "@mantine/hooks"; import { ConfigContext } from "config"; -import { FontsizeContextProvider, useFontSize } from "fontsize"; +import { FontsizeContextProvider, GlobalStyleOverridesContextProvider, useFontSize, useGlobalStyleOverrides } from "themehooks"; import React, { useCallback, useContext, useState } from "react"; const Theme: (colorScheme: ColorScheme) => MantineThemeOverride = (colorScheme) => ({ @@ -67,7 +67,7 @@ const Theme: (colorScheme: ColorScheme) => MantineThemeOverride = (colorScheme) }, }, colors: { - secondaryColorName: ["#dcfdff", "#b2f4fd", "#85ebf9", "#58e3f6", "#36d9f3", "#25c0d9", "#1696aa", "#066b7a", "#00404a", "#00171b"], + turquoise: ["#dcfdff", "#b2f4fd", "#85ebf9", "#58e3f6", "#36d9f3", "#25c0d9", "#1696aa", "#066b7a", "#00404a", "#00171b"], }, spacing: { xs: "0.3rem", @@ -80,12 +80,21 @@ const Theme: (colorScheme: ColorScheme) => MantineThemeOverride = (colorScheme) function GlobalStyles() { const fontSize = useFontSize(); + const styleOverrides = useGlobalStyleOverrides(); return ( ({ html: { fontSize: `${fontSize.value}em`, }, + body: { + color: styleOverrides.color === undefined + ? undefined + : theme.colors[styleOverrides.color.color][styleOverrides.color.shade], + backgroundColor: styleOverrides.backgroundColor === undefined + ? undefined + : theme.colors[styleOverrides.backgroundColor.color][styleOverrides.backgroundColor.shade], + }, "::-webkit-scrollbar": { width: "0.75em", height: "0.75em", @@ -134,10 +143,12 @@ export default function CustomMantineProvider({ children }: { children: React.Re return ( - - - {children} - + + + + {children} + + ); diff --git a/src/components/miscbuttons.tsx b/src/components/miscbuttons.tsx index d527333..fb2b3da 100644 --- a/src/components/miscbuttons.tsx +++ b/src/components/miscbuttons.tsx @@ -23,7 +23,7 @@ import React from "react"; import { VersionModal } from "components/modals/version"; import { useDisclosure, useHotkeys } from "@mantine/hooks"; import { modKeyString } from "trutil"; -import { useFontSize } from "fontsize"; +import { useFontSize } from "themehooks"; export function ColorSchemeToggle(props: { sz?: string, btn?: MantineNumberSize }) { const { colorScheme, toggleColorScheme } = useMantineColorScheme(); diff --git a/src/components/modals/interfacepanel.tsx b/src/components/modals/interfacepanel.tsx index 5341c94..f8b4831 100644 --- a/src/components/modals/interfacepanel.tsx +++ b/src/components/modals/interfacepanel.tsx @@ -16,9 +16,12 @@ * along with this program. If not, see . */ -import React from "react"; -import { Checkbox, Grid, NumberInput, Textarea } from "@mantine/core"; +import React, { useCallback } from "react"; +import { Checkbox, Grid, NumberInput, Textarea, useMantineTheme } from "@mantine/core"; import type { UseFormReturnType } from "@mantine/form"; +import type { ColorSetting } from "components/colorswatch"; +import ColorChooser from "components/colorswatch"; +import { useGlobalStyleOverrides } from "themehooks"; export interface InterfaceFormValues { interface: { @@ -29,8 +32,40 @@ export interface InterfaceFormValues { } export function InterfaceSettigsPanel(props: { form: UseFormReturnType }) { + const theme = useMantineTheme(); + const { color, backgroundColor, setStyle } = useGlobalStyleOverrides(); + + const setTextColor = useCallback((color: ColorSetting | undefined) => { + setStyle({ color, backgroundColor }); + }, [backgroundColor, setStyle]); + + const setBgColor = useCallback((backgroundColor: ColorSetting | undefined) => { + setStyle({ color, backgroundColor }); + }, [color, setStyle]); + + const defaultColor = theme.colorScheme === "dark" + ? { color: "dark", shade: 0 } + : { color: "dark", shade: 9 }; + + const defaultBg = theme.colorScheme === "dark" + ? { color: "dark", shade: 7 } + : { color: "gray", shade: 0 }; + return ( + + Text + + + + + + Bakground + + + + + diff --git a/src/components/tables/common.tsx b/src/components/tables/common.tsx index daf8534..e27d2fb 100644 --- a/src/components/tables/common.tsx +++ b/src/components/tables/common.tsx @@ -36,7 +36,7 @@ import type { DropResult } from "react-beautiful-dnd"; import { DragDropContext, Draggable } from "react-beautiful-dnd"; import { StrictModeDroppable } from "components/strictmodedroppable"; import { eventHasModKey, reorderElements } from "trutil"; -import { useFontSize } from "fontsize"; +import { useFontSize } from "themehooks"; const defaultColumn = { minSize: 30, diff --git a/src/config.ts b/src/config.ts index b5f77d1..6d05e37 100644 --- a/src/config.ts +++ b/src/config.ts @@ -22,6 +22,7 @@ import type { } from "@tanstack/react-table"; import type { ColorScheme } from "@mantine/core"; import { deobfuscate, obfuscate } from "trutil"; +import type { ColorSetting } from "components/colorswatch"; const { readConfigText, writeConfigText } = await import(/* webpackChunkName: "taurishim" */"taurishim"); export interface ServerConnection { @@ -116,6 +117,10 @@ interface Settings { skipAddDialog: boolean, numLastSaveDirs: number, defaultTrackers: string[], + styleOverrides: { + color?: ColorSetting, + backgroundColor?: ColorSetting, + }, }, } @@ -213,6 +218,7 @@ const DefaultSettings: Settings = { skipAddDialog: false, numLastSaveDirs: 20, defaultTrackers: [...DefaultTrackerList], + styleOverrides: {}, }, }; diff --git a/src/fontsize.tsx b/src/themehooks.tsx similarity index 70% rename from src/fontsize.tsx rename to src/themehooks.tsx index 967b8fc..a56d8fb 100644 --- a/src/fontsize.tsx +++ b/src/themehooks.tsx @@ -17,8 +17,9 @@ */ import { useToggle } from "@mantine/hooks"; +import type { ColorSetting } from "components/colorswatch"; import { ConfigContext } from "config"; -import React, { useContext, useEffect, useMemo } from "react"; +import React, { useContext, useEffect, useMemo, useState } from "react"; interface FontsizeContextValue { value: number, @@ -67,3 +68,30 @@ export function FontsizeContextProvider(props: React.PropsWithChildren) { export function useFontSize() { return useContext(FontsizeContext); } + +interface GlobalStyleOverrides { + color?: ColorSetting, + backgroundColor?: ColorSetting, + setStyle: React.Dispatch>, +} + +const GlobalStyleOverridesContext = React.createContext({ setStyle: () => { } }); + +export function GlobalStyleOverridesContextProvider(props: React.PropsWithChildren) { + const config = useContext(ConfigContext); + const [style, setStyle] = useState(config.values.interface.styleOverrides); + + useEffect(() => { + config.values.interface.styleOverrides = style; + }, [config, style]); + + return ( + + {props.children} + + ); +} + +export function useGlobalStyleOverrides() { + return useContext(GlobalStyleOverridesContext); +} diff --git a/src/types/mantine.d.ts b/src/types/mantine.d.ts index 29f750a..e8e6a02 100644 --- a/src/types/mantine.d.ts +++ b/src/types/mantine.d.ts @@ -1,6 +1,6 @@ import type { Tuple, DefaultMantineColor } from "@mantine/core"; -type ExtendedCustomColors = "primaryColorName" | "secondaryColorName" | DefaultMantineColor; +type ExtendedCustomColors = "primaryColorName" | "turquoise" | DefaultMantineColor; declare module "@mantine/core" { export interface MantineThemeColorsOverride {