diff --git a/locales/en/translation.json b/locales/en/translation.json index 990c3c85..01ca5210 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -177,6 +177,7 @@ "save": "Save", "language": "Language", "font_size": "Font size", + "font_family": "Font family", "mode": "Color mode", "dark_mode": "Dark mode", "light_mode": "Light mode", diff --git a/main/background.ts b/main/background.ts index dffc3a10..e2a73e7b 100644 --- a/main/background.ts +++ b/main/background.ts @@ -3,6 +3,7 @@ import { app, ipcMain, shell, IpcMainInvokeEvent, BrowserWindow, Menu } from 'el import serve from 'electron-serve' import { createWindow } from './helpers' import { menu } from './menu' +import SystemFonts from 'system-font-families' const isProd = process.env.NODE_ENV === 'production' @@ -72,3 +73,9 @@ ipcMain.handle('set-proxy', (_event: IpcMainInvokeEvent, data: any) => { break } }) + +ipcMain.handle('list-fonts', async (_event: IpcMainInvokeEvent) => { + const systemFonts = new SystemFonts() + const res = await systemFonts.getFonts() + return Array.from(new Set(res)).sort() +}) diff --git a/main/preload.ts b/main/preload.ts index 4657da4f..03706982 100644 --- a/main/preload.ts +++ b/main/preload.ts @@ -2,10 +2,10 @@ import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron' const handler = { invoke(channel: string, value: any) { - ipcRenderer.invoke(channel, value) + return ipcRenderer.invoke(channel, value) }, send(channel: string, value: unknown) { - ipcRenderer.send(channel, value) + return ipcRenderer.send(channel, value) }, on(channel: string, callback: (...args: unknown[]) => void) { const subscription = (_event: IpcRendererEvent, ...args: unknown[]) => callback(...args) diff --git a/package.json b/package.json index 3641d0fc..b9f00746 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "react-icons": "^5.0.0", "react-intl": "^6.5.1", "react-virtuoso": "^4.6.2", - "sanitize-html": "^2.11.0" + "sanitize-html": "^2.11.0", + "system-font-families": "^0.6.0" }, "devDependencies": { "@babel/runtime-corejs3": "^7.23.2", diff --git a/renderer/components/Settings.tsx b/renderer/components/Settings.tsx index a84758ec..5943850b 100644 --- a/renderer/components/Settings.tsx +++ b/renderer/components/Settings.tsx @@ -1,4 +1,5 @@ import { localeType } from '@/provider/i18n' +import { invoke } from '@/utils/invoke' import { Button, Dialog, DialogBody, DialogFooter, DialogHeader, Input, Option, Radio, Select, Typography } from '@material-tailwind/react' import { ChangeEvent, useEffect, useState } from 'react' import { FormattedMessage, useIntl } from 'react-intl' @@ -70,9 +71,18 @@ export default function Settings(props: Props) { const [proxyProtocol, setProxyProtocol] = useState(null) const [proxyHost, setProxyHost] = useState(null) const [proxyPort, setProxyPort] = useState(null) + const [fontFamilies, setFontFamilies] = useState>([]) + const [fontFamily, setFontFamily] = useState(null) const { formatMessage } = useIntl() useEffect(() => { + const f = async () => { + const lists = await invoke('list-fonts', null) + if (lists) { + setFontFamilies(lists) + } + } + f() if (typeof localStorage !== 'undefined') { const lang = localStorage.getItem('language') if (lang) { @@ -80,6 +90,14 @@ export default function Settings(props: Props) { } else { setLanguage('en') } + const fontSize = localStorage.getItem('fontSize') + if (fontSize) { + setFontSize(parseInt(fontSize)) + } + const fontFamily = localStorage.getItem('fontFamily') + if (fontFamily) { + setFontFamily(fontFamily) + } const dark = localStorage.getItem('color-mode') if (dark === 'dark') { setIsDark(true) @@ -121,6 +139,14 @@ export default function Settings(props: Props) { props.reloadSettings() } + const fontFamilyChanged = (e: string) => { + setFontFamily(e) + if (typeof localStorage !== 'undefined') { + localStorage.setItem('fontFamily', e) + } + props.reloadSettings() + } + const themeChanged = (e: string) => { setTheme(e) if (typeof localStorage !== 'undefined') { @@ -168,6 +194,20 @@ export default function Settings(props: Props) {
+
+ + + +
+
+ +
diff --git a/renderer/components/layouts/account.tsx b/renderer/components/layouts/account.tsx index 08d87e54..ce630955 100644 --- a/renderer/components/layouts/account.tsx +++ b/renderer/components/layouts/account.tsx @@ -23,6 +23,19 @@ import { useUnreads } from '@/provider/unreads' import { useAccounts } from '@/provider/accounts' import { invoke } from '@/utils/invoke' +const defaultFontFamily = [ + 'Apple-System', + 'Hiragino Kaku Gothic ProN', + 'Hiragino Sans GB', + 'Arial', + 'Helvetica', + 'PingFang SC', + 'Meiryo', + 'Microsoft YaHei', + 'STXihei', + 'sans-serif' +] + type LayoutProps = { children: React.ReactNode } @@ -124,6 +137,15 @@ export default function Layout({ children }: LayoutProps) { fontSize: `${fontSize}px` }) } + const fontFamily = localStorage.getItem('fontFamily') + if (fontFamily) { + setStyle({ + fontFamily: [fontFamily] + .concat(defaultFontFamily) + .filter(f => f !== null) + .join(',') + }) + } const t = localStorage.getItem('theme') if (t && t.length > 0) { setTheme(t) diff --git a/renderer/utils/invoke.tsx b/renderer/utils/invoke.tsx index 16e16397..12f43ab7 100644 --- a/renderer/utils/invoke.tsx +++ b/renderer/utils/invoke.tsx @@ -1,7 +1,6 @@ -export function invoke(event: string, data: any) { +export function invoke(event: string, data: any): Promise { if (process.env.NEXT_PUBLIC_CLIENT_ENV !== 'browser') { - global.ipc.invoke(event, data) - return + return global.ipc.invoke(event, data) } switch (event) { case 'open-browser': diff --git a/yarn.lock b/yarn.lock index 3b811e36..f205c99c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2805,6 +2805,7 @@ __metadata: react-virtuoso: "npm:^4.6.2" sanitize-html: "npm:^2.11.0" sass: "npm:^1.71.1" + system-font-families: "npm:^0.6.0" tailwindcss: "npm:^3.3.3" typescript: "npm:^5.2.2" languageName: unknown @@ -3356,6 +3357,27 @@ __metadata: languageName: node linkType: hard +"babel-polyfill@npm:^6.23.0": + version: 6.26.0 + resolution: "babel-polyfill@npm:6.26.0" + dependencies: + babel-runtime: "npm:^6.26.0" + core-js: "npm:^2.5.0" + regenerator-runtime: "npm:^0.10.5" + checksum: 10/2abfe4bf4af39c7b0c42af8ccce14897aefbde6547a227e36f4f12ba5795e8603d2964cc72ceb59086b5a69fafcb00b0deda5c1055e373c3bef76dcc517d6d0d + languageName: node + linkType: hard + +"babel-runtime@npm:^6.26.0": + version: 6.26.0 + resolution: "babel-runtime@npm:6.26.0" + dependencies: + core-js: "npm:^2.4.0" + regenerator-runtime: "npm:^0.11.0" + checksum: 10/2cdf0f083b9598a43cdb11cbf1e7060584079a9a2230f06aec997ba81e887ef17fdcb5ad813a484ee099e06d2de0cea832bdd3011c06325acb284284c754ee8f + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -3974,6 +3996,13 @@ __metadata: languageName: node linkType: hard +"core-js@npm:^2.4.0, core-js@npm:^2.5.0": + version: 2.6.12 + resolution: "core-js@npm:2.6.12" + checksum: 10/7c624eb00a59c74c769d5d80f751f3bf1fc6201205b6562f27286ad5e00bbca1483f2f7eb0c2854b86f526ef5c7dc958b45f2ff536f8a31b8e9cb1a13a96efca + languageName: node + linkType: hard + "core-util-is@npm:1.0.2": version: 1.0.2 resolution: "core-util-is@npm:1.0.2" @@ -5104,6 +5133,13 @@ __metadata: languageName: node linkType: hard +"file-type@npm:^10.11.0": + version: 10.11.0 + resolution: "file-type@npm:10.11.0" + checksum: 10/787ab64574316dbd423eccbadac2876879c5d2f1d24309948debdaf1dfbd0f5f25f881a716f44d294090bf435407f6938da41c833895c888a78127113337a608 + languageName: node + linkType: hard + "filelist@npm:^1.0.4": version: 1.0.4 resolution: "filelist@npm:1.0.4" @@ -7350,6 +7386,13 @@ __metadata: languageName: node linkType: hard +"p-finally@npm:^1.0.0": + version: 1.0.0 + resolution: "p-finally@npm:1.0.0" + checksum: 10/93a654c53dc805dd5b5891bab16eb0ea46db8f66c4bfd99336ae929323b1af2b70a8b0654f8f1eae924b2b73d037031366d645f1fd18b3d30cbd15950cc4b1d4 + languageName: node + linkType: hard + "p-limit@npm:^2.0.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -7413,7 +7456,7 @@ __metadata: languageName: node linkType: hard -"p-try@npm:^2.0.0": +"p-try@npm:^2.0.0, p-try@npm:^2.1.0": version: 2.2.0 resolution: "p-try@npm:2.2.0" checksum: 10/f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae @@ -7539,6 +7582,13 @@ __metadata: languageName: node linkType: hard +"pify@npm:^4.0.1": + version: 4.0.1 + resolution: "pify@npm:4.0.1" + checksum: 10/8b97cbf9dc6d4c1320cc238a2db0fc67547f9dc77011729ff353faf34f1936ea1a4d7f3c63b2f4980b253be77bcc72ea1e9e76ee3fd53cce2aafb6a8854d07ec + languageName: node + linkType: hard + "pirates@npm:^4.0.1": version: 4.0.6 resolution: "pirates@npm:4.0.6" @@ -7896,6 +7946,16 @@ __metadata: languageName: node linkType: hard +"read-chunk@npm:^3.2.0": + version: 3.2.0 + resolution: "read-chunk@npm:3.2.0" + dependencies: + pify: "npm:^4.0.1" + with-open-file: "npm:^0.1.6" + checksum: 10/d643eab2c5b5ceb37a8662b8d4fc853aa7dd3f11717ba962249b3062b691ef0b64f500721227724aba8464dd02ad2992d54ecf7d7b0090f83df3d5e7fadf8bb9 + languageName: node + linkType: hard + "read-config-file@npm:6.3.2": version: 6.3.2 resolution: "read-config-file@npm:6.3.2" @@ -7949,6 +8009,20 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.10.5": + version: 0.10.5 + resolution: "regenerator-runtime@npm:0.10.5" + checksum: 10/a10d9a2510ee0ec2603f2fc316bff0233b7f41702dc69a19b6a23442395a7be9247668f06e5b7a81577d0e3ef677a11c8c63b4edd7a16f1550e5b8fb22173346 + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.11.0": + version: 0.11.1 + resolution: "regenerator-runtime@npm:0.11.1" + checksum: 10/64e62d78594c227e7d5269811bca9e4aa6451332adaae8c79a30cab0fa98733b1ad90bdb9d038095c340c6fad3b414a49a8d9e0b6b424ab7ff8f94f35704f8a2 + languageName: node + linkType: hard + "regenerator-runtime@npm:^0.14.0": version: 0.14.1 resolution: "regenerator-runtime@npm:0.14.1" @@ -8888,6 +8962,18 @@ __metadata: languageName: node linkType: hard +"system-font-families@npm:^0.6.0": + version: 0.6.0 + resolution: "system-font-families@npm:0.6.0" + dependencies: + babel-polyfill: "npm:^6.23.0" + file-type: "npm:^10.11.0" + read-chunk: "npm:^3.2.0" + ttfinfo: "git+https://github.com/rBurgett/ttfinfo.git" + checksum: 10/0e39c6d8121d597e5ff8c68f1cd2ec82ff557b5c362008071860f75fc543a38141c72a613f76087b952b920d1bda76130d70d69d87336712d649b4160f314df9 + languageName: node + linkType: hard + "tabbable@npm:^6.0.1": version: 6.2.0 resolution: "tabbable@npm:6.2.0" @@ -9138,6 +9224,13 @@ __metadata: languageName: node linkType: hard +"ttfinfo@git+https://github.com/rBurgett/ttfinfo.git": + version: 0.2.0 + resolution: "ttfinfo@https://github.com/rBurgett/ttfinfo.git#commit=f00e43e2a6d4c8a12a677df20b7804492d50863c" + checksum: 10/6dfc786a4277cb6f0b415bb4db6a7effedf761b21e2fdb57ff3b3da896f30a943ab36749fa575cf4ef6e4ddb4367bbe2da38baf34a87a452db315a951544589d + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -9625,6 +9718,17 @@ __metadata: languageName: node linkType: hard +"with-open-file@npm:^0.1.6": + version: 0.1.7 + resolution: "with-open-file@npm:0.1.7" + dependencies: + p-finally: "npm:^1.0.0" + p-try: "npm:^2.1.0" + pify: "npm:^4.0.1" + checksum: 10/993b30a2afb232e4e58fe02edb15c60ef8cb7e93bc272a833a50b45f30eaa1303b08f6224a42b5981bf102eedda0a3308e090c46fdb6ae429ffeee9d6189fee8 + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0"