[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

@ -21,6 +21,8 @@ import {
Menu,
nativeImage,
BrowserWindowConstructorOptions,
protocol,
net,
} from 'electron';
import electronLocalShortcut from 'electron-localshortcut';
import log from 'electron-log';
@ -43,6 +45,8 @@ export default class AppUpdater {
}
}
protocol.registerSchemesAsPrivileged([{ privileges: { bypassCSP: true }, scheme: 'feishin' }]);
process.on('uncaughtException', (error: any) => {
console.log('Error in main process', error);
});
@ -653,8 +657,34 @@ app.on('window-all-closed', () => {
}
});
const FONT_HEADERS = [
'font/collection',
'font/otf',
'font/sfnt',
'font/ttf',
'font/woff',
'font/woff2',
];
app.whenReady()
.then(() => {
protocol.handle('feishin', async (request) => {
const filePath = `file://${request.url.slice('feishin://'.length)}`;
const response = await net.fetch(filePath);
const contentType = response.headers.get('content-type');
if (!contentType || !FONT_HEADERS.includes(contentType)) {
getMainWindow()?.webContents.send('custom-font-error', filePath);
return new Response(null, {
status: 403,
statusText: 'Forbidden',
});
}
return response;
});
createWindow();
createTray();
app.on('activate', () => {

View file

@ -1,4 +1,4 @@
import { ipcRenderer, webFrame } from 'electron';
import { IpcRendererEvent, ipcRenderer, webFrame } from 'electron';
import Store from 'electron-store';
const store = new Store();
@ -39,9 +39,14 @@ const setZoomFactor = (zoomFactor: number) => {
webFrame.setZoomFactor(zoomFactor / 100);
};
const fontError = (cb: (event: IpcRendererEvent, file: string) => void) => {
ipcRenderer.on('custom-font-error', cb);
};
export const localSettings = {
disableMediaKeys,
enableMediaKeys,
fontError,
get,
passwordGet,
passwordRemove,