Skip to content

Commit 5a494c6

Browse files
committed
Add options to tweak main text/bg colors
1 parent 5b2e2e3 commit 5a494c6

8 files changed

Lines changed: 163 additions & 12 deletions

File tree

src/components/colorswatch.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* TrguiNG - next gen remote GUI for transmission torrent daemon
3+
* Copyright (C) 2023 qu1ck (mail at qu1ck.org)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published
7+
* by the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
import type { DefaultMantineColor } from "@mantine/core";
20+
import { ActionIcon, ColorSwatch, Grid, Popover, useMantineTheme } from "@mantine/core";
21+
import React, { useState } from "react";
22+
23+
export interface ColorSetting {
24+
color: DefaultMantineColor,
25+
shade: number,
26+
}
27+
28+
interface ColorChooserProps {
29+
value: ColorSetting,
30+
onChange: (value: ColorSetting | undefined) => void,
31+
}
32+
33+
const shades = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
34+
35+
export default function ColorChooser(props: ColorChooserProps) {
36+
const theme = useMantineTheme();
37+
const [opened, setOpened] = useState(false);
38+
const swatchOutline = theme.colorScheme === "dark" ? theme.colors.gray[7] : theme.colors.dark[6];
39+
40+
return (
41+
<Popover width="25rem" position="bottom" withArrow withinPortal shadow="md" opened={opened} onChange={setOpened} >
42+
<Popover.Target>
43+
<ActionIcon onClick={() => { setOpened((o) => !o); }}>
44+
<ColorSwatch
45+
color={theme.colors[props.value.color][props.value.shade]}
46+
sx={{ border: `1px solid ${swatchOutline}` }} />
47+
</ActionIcon>
48+
</Popover.Target>
49+
<Popover.Dropdown>
50+
<ActionIcon p="lg" onClick={() => {
51+
props.onChange(undefined);
52+
setOpened(false);
53+
}}>
54+
Reset
55+
</ActionIcon>
56+
<Grid columns={10}>
57+
{Object.keys(theme.colors).map((color) => shades.map((shade) => (
58+
<Grid.Col key={`${color}:${shade}`} span={1}>
59+
<ActionIcon onClick={() => {
60+
props.onChange({ color, shade });
61+
setOpened(false);
62+
}}>
63+
<ColorSwatch color={theme.colors[color][shade]} />
64+
</ActionIcon>
65+
</Grid.Col>
66+
)))}
67+
</Grid>
68+
</Popover.Dropdown>
69+
</Popover>
70+
);
71+
}

src/components/mantinetheme.tsx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { ColorSchemeProvider, Global, MantineProvider } from "@mantine/core";
2020
import type { ColorScheme, MantineThemeOverride } from "@mantine/core";
2121
import { useColorScheme } from "@mantine/hooks";
2222
import { ConfigContext } from "config";
23-
import { FontsizeContextProvider, useFontSize } from "fontsize";
23+
import { FontsizeContextProvider, GlobalStyleOverridesContextProvider, useFontSize, useGlobalStyleOverrides } from "themehooks";
2424
import React, { useCallback, useContext, useState } from "react";
2525

2626
const Theme: (colorScheme: ColorScheme) => MantineThemeOverride = (colorScheme) => ({
@@ -67,7 +67,7 @@ const Theme: (colorScheme: ColorScheme) => MantineThemeOverride = (colorScheme)
6767
},
6868
},
6969
colors: {
70-
secondaryColorName: ["#dcfdff", "#b2f4fd", "#85ebf9", "#58e3f6", "#36d9f3", "#25c0d9", "#1696aa", "#066b7a", "#00404a", "#00171b"],
70+
turquoise: ["#dcfdff", "#b2f4fd", "#85ebf9", "#58e3f6", "#36d9f3", "#25c0d9", "#1696aa", "#066b7a", "#00404a", "#00171b"],
7171
},
7272
spacing: {
7373
xs: "0.3rem",
@@ -80,12 +80,21 @@ const Theme: (colorScheme: ColorScheme) => MantineThemeOverride = (colorScheme)
8080

8181
function GlobalStyles() {
8282
const fontSize = useFontSize();
83+
const styleOverrides = useGlobalStyleOverrides();
8384

8485
return (
8586
<Global styles={(theme) => ({
8687
html: {
8788
fontSize: `${fontSize.value}em`,
8889
},
90+
body: {
91+
color: styleOverrides.color === undefined
92+
? undefined
93+
: theme.colors[styleOverrides.color.color][styleOverrides.color.shade],
94+
backgroundColor: styleOverrides.backgroundColor === undefined
95+
? undefined
96+
: theme.colors[styleOverrides.backgroundColor.color][styleOverrides.backgroundColor.shade],
97+
},
8998
"::-webkit-scrollbar": {
9099
width: "0.75em",
91100
height: "0.75em",
@@ -134,10 +143,12 @@ export default function CustomMantineProvider({ children }: { children: React.Re
134143
return (
135144
<ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
136145
<FontsizeContextProvider>
137-
<MantineProvider withGlobalStyles withNormalizeCSS theme={Theme(colorScheme)}>
138-
<GlobalStyles />
139-
{children}
140-
</MantineProvider>
146+
<GlobalStyleOverridesContextProvider>
147+
<MantineProvider withGlobalStyles withNormalizeCSS theme={Theme(colorScheme)}>
148+
<GlobalStyles />
149+
{children}
150+
</MantineProvider>
151+
</GlobalStyleOverridesContextProvider>
141152
</FontsizeContextProvider>
142153
</ColorSchemeProvider>
143154
);

src/components/miscbuttons.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import React from "react";
2323
import { VersionModal } from "components/modals/version";
2424
import { useDisclosure, useHotkeys } from "@mantine/hooks";
2525
import { modKeyString } from "trutil";
26-
import { useFontSize } from "fontsize";
26+
import { useFontSize } from "themehooks";
2727

2828
export function ColorSchemeToggle(props: { sz?: string, btn?: MantineNumberSize }) {
2929
const { colorScheme, toggleColorScheme } = useMantineColorScheme();

src/components/modals/interfacepanel.tsx

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19-
import React from "react";
20-
import { Checkbox, Grid, NumberInput, Textarea } from "@mantine/core";
19+
import React, { useCallback } from "react";
20+
import { Checkbox, Grid, NumberInput, Textarea, useMantineTheme } from "@mantine/core";
2121
import type { UseFormReturnType } from "@mantine/form";
22+
import type { ColorSetting } from "components/colorswatch";
23+
import ColorChooser from "components/colorswatch";
24+
import { useGlobalStyleOverrides } from "themehooks";
2225

2326
export interface InterfaceFormValues {
2427
interface: {
@@ -29,8 +32,40 @@ export interface InterfaceFormValues {
2932
}
3033

3134
export function InterfaceSettigsPanel<V extends InterfaceFormValues>(props: { form: UseFormReturnType<V> }) {
35+
const theme = useMantineTheme();
36+
const { color, backgroundColor, setStyle } = useGlobalStyleOverrides();
37+
38+
const setTextColor = useCallback((color: ColorSetting | undefined) => {
39+
setStyle({ color, backgroundColor });
40+
}, [backgroundColor, setStyle]);
41+
42+
const setBgColor = useCallback((backgroundColor: ColorSetting | undefined) => {
43+
setStyle({ color, backgroundColor });
44+
}, [color, setStyle]);
45+
46+
const defaultColor = theme.colorScheme === "dark"
47+
? { color: "dark", shade: 0 }
48+
: { color: "dark", shade: 9 };
49+
50+
const defaultBg = theme.colorScheme === "dark"
51+
? { color: "dark", shade: 7 }
52+
: { color: "gray", shade: 0 };
53+
3254
return (
3355
<Grid>
56+
<Grid.Col span={2}>
57+
Text
58+
</Grid.Col>
59+
<Grid.Col span={1}>
60+
<ColorChooser value={color ?? defaultColor} onChange={setTextColor} />
61+
</Grid.Col>
62+
<Grid.Col span={2}>
63+
Bakground
64+
</Grid.Col>
65+
<Grid.Col span={1}>
66+
<ColorChooser value={backgroundColor ?? defaultBg} onChange={setBgColor} />
67+
</Grid.Col>
68+
<Grid.Col span={6} />
3469
<Grid.Col>
3570
<Checkbox label="Skip add torrent dialog"
3671
{...props.form.getInputProps("interface.skipAddDialog", { type: "checkbox" })} />

src/components/tables/common.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import type { DropResult } from "react-beautiful-dnd";
3636
import { DragDropContext, Draggable } from "react-beautiful-dnd";
3737
import { StrictModeDroppable } from "components/strictmodedroppable";
3838
import { eventHasModKey, reorderElements } from "trutil";
39-
import { useFontSize } from "fontsize";
39+
import { useFontSize } from "themehooks";
4040

4141
const defaultColumn = {
4242
minSize: 30,

src/config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type {
2222
} from "@tanstack/react-table";
2323
import type { ColorScheme } from "@mantine/core";
2424
import { deobfuscate, obfuscate } from "trutil";
25+
import type { ColorSetting } from "components/colorswatch";
2526
const { readConfigText, writeConfigText } = await import(/* webpackChunkName: "taurishim" */"taurishim");
2627

2728
export interface ServerConnection {
@@ -116,6 +117,10 @@ interface Settings {
116117
skipAddDialog: boolean,
117118
numLastSaveDirs: number,
118119
defaultTrackers: string[],
120+
styleOverrides: {
121+
color?: ColorSetting,
122+
backgroundColor?: ColorSetting,
123+
},
119124
},
120125
}
121126

@@ -213,6 +218,7 @@ const DefaultSettings: Settings = {
213218
skipAddDialog: false,
214219
numLastSaveDirs: 20,
215220
defaultTrackers: [...DefaultTrackerList],
221+
styleOverrides: {},
216222
},
217223
};
218224

src/fontsize.tsx renamed to src/themehooks.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
*/
1818

1919
import { useToggle } from "@mantine/hooks";
20+
import type { ColorSetting } from "components/colorswatch";
2021
import { ConfigContext } from "config";
21-
import React, { useContext, useEffect, useMemo } from "react";
22+
import React, { useContext, useEffect, useMemo, useState } from "react";
2223

2324
interface FontsizeContextValue {
2425
value: number,
@@ -67,3 +68,30 @@ export function FontsizeContextProvider(props: React.PropsWithChildren) {
6768
export function useFontSize() {
6869
return useContext(FontsizeContext);
6970
}
71+
72+
interface GlobalStyleOverrides {
73+
color?: ColorSetting,
74+
backgroundColor?: ColorSetting,
75+
setStyle: React.Dispatch<Omit<GlobalStyleOverrides, "setStyle">>,
76+
}
77+
78+
const GlobalStyleOverridesContext = React.createContext<GlobalStyleOverrides>({ setStyle: () => { } });
79+
80+
export function GlobalStyleOverridesContextProvider(props: React.PropsWithChildren) {
81+
const config = useContext(ConfigContext);
82+
const [style, setStyle] = useState(config.values.interface.styleOverrides);
83+
84+
useEffect(() => {
85+
config.values.interface.styleOverrides = style;
86+
}, [config, style]);
87+
88+
return (
89+
<GlobalStyleOverridesContext.Provider value={{ ...style, setStyle }}>
90+
{props.children}
91+
</GlobalStyleOverridesContext.Provider>
92+
);
93+
}
94+
95+
export function useGlobalStyleOverrides() {
96+
return useContext(GlobalStyleOverridesContext);
97+
}

src/types/mantine.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Tuple, DefaultMantineColor } from "@mantine/core";
22

3-
type ExtendedCustomColors = "primaryColorName" | "secondaryColorName" | DefaultMantineColor;
3+
type ExtendedCustomColors = "primaryColorName" | "turquoise" | DefaultMantineColor;
44

55
declare module "@mantine/core" {
66
export interface MantineThemeColorsOverride {

0 commit comments

Comments
 (0)