[feature]: Support using system fonts (#304)

* [feature]: Support using system fonts

Uses the **experimental** queryLocalFonts API, when prompted, to get the fonts and do CSS.
Resolves #270 and #288 (by proxy)

Caveats/notes:
- This is experimental, and is only supported by Chrome/Chromium/Edgeium (see https://caniuse.com/?search=querylocalfonts)
- As far as I can tell, the only way to dynamically change the font (shown in https://wicg.github.io/local-font-access/#example-style-with-local-fonts) was by DOM manipulation; css variables did not seem to work
- This shows **all** fonts, including their variants (bold/italic/etc); given that the style names could be localized, not sure of a way to parse this (on my system, for instance, I had 859 different combinations)
- I made fonts a separate top-level setting because it was easier to manipulate without causing as many rerenders; feel free to put that back

* add permission chec

* add electron magic to support custom font

* restrict content types
This commit is contained in:
Kendall Garner 2023-10-22 22:25:17 +00:00 committed by GitHub
parent e6ed9229c2
commit 74cab01013
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 282 additions and 20 deletions

View file

@ -1,4 +1,4 @@
import { useEffect, useMemo } from 'react';
import { useEffect, useMemo, useRef } from 'react';
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model';
import { ModuleRegistry } from '@ag-grid-community/core';
import { InfiniteRowModelModule } from '@ag-grid-community/infinite-row-model';
@ -23,7 +23,7 @@ import { PlayQueueHandlerContext } from '/@/renderer/features/player';
import { AddToPlaylistContextModal } from '/@/renderer/features/playlists';
import { getMpvProperties } from '/@/renderer/features/settings/components/playback/mpv-settings';
import { PlayerState, usePlayerStore, useQueueControls } from '/@/renderer/store';
import { PlaybackType, PlayerStatus } from '/@/renderer/types';
import { FontType, PlaybackType, PlayerStatus } from '/@/renderer/types';
import '@ag-grid-community/styles/ag-grid.css';
ModuleRegistry.registerModules([ClientSideRowModelModule, InfiniteRowModelModule]);
@ -37,17 +37,48 @@ const remote = isElectron() ? window.electron.remote : null;
export const App = () => {
const theme = useTheme();
const contentFont = useSettingsStore((state) => state.general.fontContent);
const { builtIn, custom, system, type } = useSettingsStore((state) => state.font);
const { type: playbackType } = usePlaybackSettings();
const { bindings } = useHotkeySettings();
const handlePlayQueueAdd = useHandlePlayQueueAdd();
const { clearQueue, restoreQueue } = useQueueControls();
const remoteSettings = useRemoteSettings();
const textStyleRef = useRef<HTMLStyleElement>();
useEffect(() => {
const root = document.documentElement;
root.style.setProperty('--content-font-family', contentFont);
}, [contentFont]);
if (type === FontType.SYSTEM && system) {
const root = document.documentElement;
root.style.setProperty('--content-font-family', 'dynamic-font');
if (!textStyleRef.current) {
textStyleRef.current = document.createElement('style');
document.body.appendChild(textStyleRef.current);
}
textStyleRef.current.textContent = `
@font-face {
font-family: "dynamic-font";
src: local("${system}");
}`;
} else if (type === FontType.CUSTOM && custom) {
const root = document.documentElement;
root.style.setProperty('--content-font-family', 'dynamic-font');
if (!textStyleRef.current) {
textStyleRef.current = document.createElement('style');
document.body.appendChild(textStyleRef.current);
}
textStyleRef.current.textContent = `
@font-face {
font-family: "dynamic-font";
src: url("feishin://${custom}");
}`;
} else {
const root = document.documentElement;
root.style.setProperty('--content-font-family', builtIn);
}
}, [builtIn, custom, system, type]);
const providerValue = useMemo(() => {
return { handlePlayQueueAdd };