Skip to content

Commit

Permalink
Add options to tweak main text/bg colors
Browse files Browse the repository at this point in the history
  • Loading branch information
qu1ck committed Oct 27, 2023
1 parent 5b2e2e3 commit 5a494c6
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 12 deletions.
71 changes: 71 additions & 0 deletions src/components/colorswatch.tsx
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/

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 (
<Popover width="25rem" position="bottom" withArrow withinPortal shadow="md" opened={opened} onChange={setOpened} >
<Popover.Target>
<ActionIcon onClick={() => { setOpened((o) => !o); }}>
<ColorSwatch
color={theme.colors[props.value.color][props.value.shade]}
sx={{ border: `1px solid ${swatchOutline}` }} />
</ActionIcon>
</Popover.Target>
<Popover.Dropdown>
<ActionIcon p="lg" onClick={() => {
props.onChange(undefined);
setOpened(false);
}}>
Reset
</ActionIcon>
<Grid columns={10}>
{Object.keys(theme.colors).map((color) => shades.map((shade) => (
<Grid.Col key={`${color}:${shade}`} span={1}>
<ActionIcon onClick={() => {
props.onChange({ color, shade });
setOpened(false);
}}>
<ColorSwatch color={theme.colors[color][shade]} />
</ActionIcon>
</Grid.Col>
)))}
</Grid>
</Popover.Dropdown>
</Popover>
);
}
23 changes: 17 additions & 6 deletions src/components/mantinetheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand Down Expand Up @@ -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",
Expand All @@ -80,12 +80,21 @@ const Theme: (colorScheme: ColorScheme) => MantineThemeOverride = (colorScheme)

function GlobalStyles() {
const fontSize = useFontSize();
const styleOverrides = useGlobalStyleOverrides();

return (
<Global styles={(theme) => ({
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",
Expand Down Expand Up @@ -134,10 +143,12 @@ export default function CustomMantineProvider({ children }: { children: React.Re
return (
<ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
<FontsizeContextProvider>
<MantineProvider withGlobalStyles withNormalizeCSS theme={Theme(colorScheme)}>
<GlobalStyles />
{children}
</MantineProvider>
<GlobalStyleOverridesContextProvider>
<MantineProvider withGlobalStyles withNormalizeCSS theme={Theme(colorScheme)}>
<GlobalStyles />
{children}
</MantineProvider>
</GlobalStyleOverridesContextProvider>
</FontsizeContextProvider>
</ColorSchemeProvider>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/miscbuttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
39 changes: 37 additions & 2 deletions src/components/modals/interfacepanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

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: {
Expand All @@ -29,8 +32,40 @@ export interface InterfaceFormValues {
}

export function InterfaceSettigsPanel<V extends InterfaceFormValues>(props: { form: UseFormReturnType<V> }) {
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 (
<Grid>
<Grid.Col span={2}>
Text
</Grid.Col>
<Grid.Col span={1}>
<ColorChooser value={color ?? defaultColor} onChange={setTextColor} />
</Grid.Col>
<Grid.Col span={2}>
Bakground
</Grid.Col>
<Grid.Col span={1}>
<ColorChooser value={backgroundColor ?? defaultBg} onChange={setBgColor} />
</Grid.Col>
<Grid.Col span={6} />
<Grid.Col>
<Checkbox label="Skip add torrent dialog"
{...props.form.getInputProps("interface.skipAddDialog", { type: "checkbox" })} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/tables/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -116,6 +117,10 @@ interface Settings {
skipAddDialog: boolean,
numLastSaveDirs: number,
defaultTrackers: string[],
styleOverrides: {
color?: ColorSetting,
backgroundColor?: ColorSetting,
},
},
}

Expand Down Expand Up @@ -213,6 +218,7 @@ const DefaultSettings: Settings = {
skipAddDialog: false,
numLastSaveDirs: 20,
defaultTrackers: [...DefaultTrackerList],
styleOverrides: {},
},
};

Expand Down
30 changes: 29 additions & 1 deletion src/fontsize.tsx → src/themehooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<Omit<GlobalStyleOverrides, "setStyle">>,
}

const GlobalStyleOverridesContext = React.createContext<GlobalStyleOverrides>({ 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 (
<GlobalStyleOverridesContext.Provider value={{ ...style, setStyle }}>
{props.children}
</GlobalStyleOverridesContext.Provider>
);
}

export function useGlobalStyleOverrides() {
return useContext(GlobalStyleOverridesContext);
}
2 changes: 1 addition & 1 deletion src/types/mantine.d.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down

0 comments on commit 5a494c6

Please sign in to comment.