Skip to content

Commit

Permalink
Add configurable font
Browse files Browse the repository at this point in the history
Issue #86
  • Loading branch information
qu1ck committed Oct 28, 2023
1 parent 5a494c6 commit 0f34896
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 38 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ jobs:
if: matrix.platform.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf libasound2-dev
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf libasound2-dev libfontconfig-dev
- name: install npm packages
run: npm ci

Expand Down
77 changes: 77 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ hyper-tls = "0.5.0"
notify-rust = "4.8.0"
flate2 = "1.0.26"
maxminddb = "0.23"
font-loader = "0.11.0"

[target.'cfg(windows)'.dependencies]
winreg = "0.50.0"
Expand Down
6 changes: 6 additions & 0 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use base64::{engine::general_purpose::STANDARD as b64engine, Engine as _};
use font_loader::system_fonts;
use lava_torrent::torrent::v1::Torrent;
use tauri::{Manager, State};

Expand Down Expand Up @@ -239,3 +240,8 @@ pub async fn pass_to_window(
);
}
}

#[tauri::command]
pub async fn list_system_fonts() -> Vec<String> {
system_fonts::query_all()
}
1 change: 1 addition & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ fn main() {
commands::cancel_create_torrent,
commands::save_create_torrent,
commands::pass_to_window,
commands::list_system_fonts,
])
.manage(ListenerHandle(Arc::new(RwLock::new(ipc))))
.manage(TorrentCacheHandle::default())
Expand Down
27 changes: 19 additions & 8 deletions src/components/mantinetheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ 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, GlobalStyleOverridesContextProvider, useFontSize, useGlobalStyleOverrides } from "themehooks";
import React, { useCallback, useContext, useState } from "react";
import { FontsizeContextProvider, GlobalStyleOverridesContext, useFontSize, useGlobalStyleOverrides } from "themehooks";
import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";

const Theme: (colorScheme: ColorScheme) => MantineThemeOverride = (colorScheme) => ({
const Theme: (colorScheme: ColorScheme, font?: string) => MantineThemeOverride = (colorScheme, font) => ({
colorScheme,
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
fontFamily: font ?? "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
headings: {
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
fontFamily: font ?? "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
},
components: {
Table: {
Expand Down Expand Up @@ -140,15 +140,26 @@ export default function CustomMantineProvider({ children }: { children: React.Re
setColorScheme(value);
}, [config, colorScheme]);

const [style, setStyle] = useState(config.values.interface.styleOverrides);

useEffect(() => {
config.values.interface.styleOverrides = style;
console.log("Style written to config", style);
}, [config, style]);

const theme = useMemo(() => {
return Theme(colorScheme, style.font);
}, [colorScheme, style.font]);

return (
<ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
<FontsizeContextProvider>
<GlobalStyleOverridesContextProvider>
<MantineProvider withGlobalStyles withNormalizeCSS theme={Theme(colorScheme)}>
<GlobalStyleOverridesContext.Provider value={{ ...style, setStyle }}>
<MantineProvider withGlobalStyles withNormalizeCSS theme={theme}>
<GlobalStyles />
{children}
</MantineProvider>
</GlobalStyleOverridesContextProvider>
</GlobalStyleOverridesContext.Provider>
</FontsizeContextProvider>
</ColorSchemeProvider>
);
Expand Down
57 changes: 46 additions & 11 deletions src/components/modals/interfacepanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import React, { useCallback } from "react";
import { Checkbox, Grid, NumberInput, Textarea, useMantineTheme } from "@mantine/core";
import React, { useCallback, useEffect, useState } from "react";
import { Checkbox, Grid, NativeSelect, 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";
const { TAURI, invoke } = await import(/* webpackChunkName: "taurishim" */"taurishim");

export interface InterfaceFormValues {
interface: {
styleOverrides: {
color?: ColorSetting,
backgroundColor?: ColorSetting,
font?: string,
},
skipAddDialog: boolean,
numLastSaveDirs: number,
defaultTrackers: string[],
Expand All @@ -33,15 +39,39 @@ export interface InterfaceFormValues {

export function InterfaceSettigsPanel<V extends InterfaceFormValues>(props: { form: UseFormReturnType<V> }) {
const theme = useMantineTheme();
const { color, backgroundColor, setStyle } = useGlobalStyleOverrides();
const { color, backgroundColor, font, setStyle } = useGlobalStyleOverrides();
const [systemFonts, setSystemFonts] = useState<string[]>(["Default"]);

useEffect(() => {
if (TAURI) {
invoke<string[]>("list_system_fonts").then((fonts) => {
fonts.sort();
setSystemFonts(["Default"].concat(fonts));
}).catch(console.error);
} else {
setSystemFonts(["Default", "Arial", "Verdana", "Tahoma", "Roboto"]);
}
}, []);

const { setFieldValue } = props.form as unknown as UseFormReturnType<InterfaceFormValues>;

const setTextColor = useCallback((color: ColorSetting | undefined) => {
setStyle({ color, backgroundColor });
}, [backgroundColor, setStyle]);
const style = { color, backgroundColor, font };
setStyle(style);
setFieldValue("interface.styleOverrides", style);
}, [backgroundColor, font, setFieldValue, setStyle]);

const setBgColor = useCallback((backgroundColor: ColorSetting | undefined) => {
setStyle({ color, backgroundColor });
}, [color, setStyle]);
const style = { color, backgroundColor, font };
setStyle(style);
setFieldValue("interface.styleOverrides", style);
}, [color, font, setFieldValue, setStyle]);

const setFont = useCallback((font: string) => {
const style = { color, backgroundColor, font: font === "Default" ? undefined : font };
setStyle(style);
setFieldValue("interface.styleOverrides", style);
}, [backgroundColor, color, setFieldValue, setStyle]);

const defaultColor = theme.colorScheme === "dark"
? { color: "dark", shade: 0 }
Expand All @@ -52,20 +82,25 @@ export function InterfaceSettigsPanel<V extends InterfaceFormValues>(props: { fo
: { color: "gray", shade: 0 };

return (
<Grid>
<Grid align="center">
<Grid.Col span={2}>
Font
</Grid.Col>
<Grid.Col span={4}>
<NativeSelect data={systemFonts} value={font} onChange={(e) => { setFont(e.currentTarget.value); }} />
</Grid.Col>
<Grid.Col span={2}>
Text
Text color
</Grid.Col>
<Grid.Col span={1}>
<ColorChooser value={color ?? defaultColor} onChange={setTextColor} />
</Grid.Col>
<Grid.Col span={2}>
Bakground
Background
</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
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ interface Settings {
styleOverrides: {
color?: ColorSetting,
backgroundColor?: ColorSetting,
font?: string,
},
},
}
Expand Down
20 changes: 3 additions & 17 deletions src/themehooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import { useToggle } from "@mantine/hooks";
import type { ColorSetting } from "components/colorswatch";
import { ConfigContext } from "config";
import React, { useContext, useEffect, useMemo, useState } from "react";
import React, { useContext, useEffect, useMemo } from "react";

interface FontsizeContextValue {
value: number,
Expand Down Expand Up @@ -72,25 +72,11 @@ export function useFontSize() {
interface GlobalStyleOverrides {
color?: ColorSetting,
backgroundColor?: ColorSetting,
font?: string,
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 const GlobalStyleOverridesContext = React.createContext<GlobalStyleOverrides>({ setStyle: () => { } });

export function useGlobalStyleOverrides() {
return useContext(GlobalStyleOverridesContext);
Expand Down

0 comments on commit 0f34896

Please sign in to comment.