diff --git a/Cargo.lock b/Cargo.lock index 26be1861..ddd3d83b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,6 @@ version = "0.2.2" dependencies = [ "block", "cocoa", - "font-enumeration", "futures-util", "log", "objc", @@ -5438,6 +5437,7 @@ dependencies = [ name = "tauri-plugin-native-bridge" version = "0.1.0" dependencies = [ + "font-enumeration", "schemars", "serde", "tauri", diff --git a/apps/readest-app/src-tauri/Cargo.toml b/apps/readest-app/src-tauri/Cargo.toml index fdae46a6..0295eaf3 100644 --- a/apps/readest-app/src-tauri/Cargo.toml +++ b/apps/readest-app/src-tauri/Cargo.toml @@ -63,4 +63,3 @@ tauri-plugin-cli = "2" tauri-plugin-single-instance = "2.2.3" tauri-plugin-updater = "2.7.0" tauri-plugin-window-state = "2.2.2" -font-enumeration = "0.9.0" diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/Cargo.toml b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/Cargo.toml index 7674be76..b85ede13 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/Cargo.toml +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/Cargo.toml @@ -17,3 +17,6 @@ schemars = "0.8" [build-dependencies] tauri-plugin = { version = "2.0.4", features = ["build"] } schemars = "0.8" + +[target.'cfg(any(target_os = "macos", windows, target_os = "linux"))'.dependencies] +font-enumeration = "0.9.0" diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/android/src/main/java/NativeBridgePlugin.kt b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/android/src/main/java/NativeBridgePlugin.kt index 889d6b38..9330572e 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/android/src/main/java/NativeBridgePlugin.kt +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/android/src/main/java/NativeBridgePlugin.kt @@ -11,6 +11,8 @@ import android.view.WindowManager import android.view.WindowInsetsController import android.graphics.Color import android.webkit.WebView +import android.graphics.fonts.SystemFonts +import android.graphics.fonts.Font import androidx.core.view.WindowCompat import androidx.core.content.FileProvider import androidx.core.view.WindowInsetsCompat @@ -22,6 +24,7 @@ import app.tauri.annotation.TauriPlugin import app.tauri.plugin.JSObject import app.tauri.plugin.Plugin import app.tauri.plugin.Invoke +import org.json.JSONArray import java.io.* @InvokeArg @@ -247,4 +250,43 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) { } invoke.resolve(ret) } + + @Command + fun get_sys_fonts_list(invoke: Invoke) { + val ret = JSObject() + try { + val fontList = mutableListOf() + val fontFileList = mutableListOf() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val systemFonts = SystemFonts.getAvailableFonts() + for (font in systemFonts) { + val file = font.getFile()?: continue + if (file.isFile && (file.name.endsWith(".ttf", true) || file.name.endsWith(".otf", true))) { + fontFileList.add(file.name) + } + } + } else { + val fontDirs = listOf("/system/fonts", "/system/font", "/data/fonts") + for (dirPath in fontDirs) { + val dir = File(dirPath) + if (dir.exists() && dir.isDirectory) { + dir.listFiles()?.forEach { file -> + if (file.isFile && (file.name.endsWith(".ttf", true) || file.name.endsWith(".otf", true))) { + fontFileList.add(file.name) + } + } + } + } + } + for (fileFileName in fontFileList) { + var fontName = fileFileName + .replace(Regex("\\.(ttf|otf)$", RegexOption.IGNORE_CASE), "") + .trim() + } + ret.put("fonts", JSONArray(fontList)) + } catch (e: Exception) { + ret.put("error", e.message) + } + invoke.resolve(ret) + } } diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/build.rs b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/build.rs index 3505d5bf..5de5e897 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/build.rs +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/build.rs @@ -6,6 +6,7 @@ const COMMANDS: &[&str] = &[ "install_package", "set_system_ui_visibility", "get_status_bar_height", + "get_sys_fonts_list", ]; fn main() { diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/ios/Sources/NativeBridgePlugin.swift b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/ios/Sources/NativeBridgePlugin.swift index 0f953129..5c4fa93f 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/ios/Sources/NativeBridgePlugin.swift +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/ios/Sources/NativeBridgePlugin.swift @@ -1,11 +1,27 @@ -import AuthenticationServices import AVFoundation +import AuthenticationServices +import CoreText import MediaPlayer import SwiftRs import Tauri import UIKit import WebKit +func getLocalizedDisplayName(familyName: String) -> String? { + let fontDescriptor = CTFontDescriptorCreateWithAttributes( + [ + kCTFontFamilyNameAttribute: familyName + ] as CFDictionary) + + let font = CTFontCreateWithFontDescriptor(fontDescriptor, 0.0, nil) + + var actualLanguage: Unmanaged? + if let localizedName = CTFontCopyLocalizedName(font, kCTFontFamilyNameKey, &actualLanguage) { + return localizedName as String + } + return nil +} + class SafariAuthRequestArgs: Decodable { let authUrl: String } @@ -95,6 +111,25 @@ class NativeBridgePlugin: Plugin { } invoke.resolve(["success": true]) } + + @objc public func get_sys_fonts_list(_ invoke: Invoke) throws { + var fontList: [String] = [] + + for family in UIFont.familyNames.sorted() { + if let localized = getLocalizedDisplayName(familyName: family) { + fontList.append(localized) + } else { + let fontNames = UIFont.fontNames(forFamilyName: family) + if fontNames.isEmpty { + fontList.append(family) + } else { + fontList.append(contentsOf: fontNames) + } + } + } + + invoke.resolve(["fonts": fontList]) + } } @_cdecl("init_plugin_native_bridge") diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/autogenerated/commands/get_sys_fonts_list.toml b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/autogenerated/commands/get_sys_fonts_list.toml new file mode 100644 index 00000000..e34f3319 --- /dev/null +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/autogenerated/commands/get_sys_fonts_list.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-get-sys-fonts-list" +description = "Enables the get_sys_fonts_list command without any pre-configured scope." +commands.allow = ["get_sys_fonts_list"] + +[[permission]] +identifier = "deny-get-sys-fonts-list" +description = "Denies the get_sys_fonts_list command without any pre-configured scope." +commands.deny = ["get_sys_fonts_list"] diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/autogenerated/reference.md b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/autogenerated/reference.md index ccec6e4b..54ab55f0 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/autogenerated/reference.md +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/autogenerated/reference.md @@ -11,6 +11,7 @@ Default permissions for the plugin - `allow-install-package` - `allow-set-system-ui-visibility` - `allow-get-status-bar-height` +- `allow-get-sys-fonts-list` ## Permission Table @@ -128,6 +129,32 @@ Denies the get_status_bar_height command without any pre-configured scope. +`native-bridge:allow-get-sys-fonts-list` + + + + +Enables the get_sys_fonts_list command without any pre-configured scope. + + + + + + + +`native-bridge:deny-get-sys-fonts-list` + + + + +Denies the get_sys_fonts_list command without any pre-configured scope. + + + + + + + `native-bridge:allow-install-package` diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/default.toml b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/default.toml index ba4e6b8b..3fad039f 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/default.toml +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/default.toml @@ -8,4 +8,5 @@ permissions = [ "allow-install-package", "allow-set-system-ui-visibility", "allow-get-status-bar-height", + "allow-get-sys-fonts-list", ] diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/schemas/schema.json b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/schemas/schema.json index 03101ed0..249a2e77 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/schemas/schema.json +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/permissions/schemas/schema.json @@ -342,6 +342,18 @@ "const": "deny-get-status-bar-height", "markdownDescription": "Denies the get_status_bar_height command without any pre-configured scope." }, + { + "description": "Enables the get_sys_fonts_list command without any pre-configured scope.", + "type": "string", + "const": "allow-get-sys-fonts-list", + "markdownDescription": "Enables the get_sys_fonts_list command without any pre-configured scope." + }, + { + "description": "Denies the get_sys_fonts_list command without any pre-configured scope.", + "type": "string", + "const": "deny-get-sys-fonts-list", + "markdownDescription": "Denies the get_sys_fonts_list command without any pre-configured scope." + }, { "description": "Enables the install_package command without any pre-configured scope.", "type": "string", @@ -379,10 +391,10 @@ "markdownDescription": "Denies the use_background_audio command without any pre-configured scope." }, { - "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-auth-with-safari`\n- `allow-auth-with-custom-tab`\n- `allow-copy-uri-to-path`\n- `allow-use-background-audio`\n- `allow-install-package`\n- `allow-set-system-ui-visibility`\n- `allow-get-status-bar-height`", + "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-auth-with-safari`\n- `allow-auth-with-custom-tab`\n- `allow-copy-uri-to-path`\n- `allow-use-background-audio`\n- `allow-install-package`\n- `allow-set-system-ui-visibility`\n- `allow-get-status-bar-height`\n- `allow-get-sys-fonts-list`", "type": "string", "const": "default", - "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-auth-with-safari`\n- `allow-auth-with-custom-tab`\n- `allow-copy-uri-to-path`\n- `allow-use-background-audio`\n- `allow-install-package`\n- `allow-set-system-ui-visibility`\n- `allow-get-status-bar-height`" + "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-auth-with-safari`\n- `allow-auth-with-custom-tab`\n- `allow-copy-uri-to-path`\n- `allow-use-background-audio`\n- `allow-install-package`\n- `allow-set-system-ui-visibility`\n- `allow-get-status-bar-height`\n- `allow-get-sys-fonts-list`" } ] } diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/commands.rs b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/commands.rs index 04e24d3b..666cde2b 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/commands.rs +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/commands.rs @@ -58,3 +58,10 @@ pub(crate) async fn get_status_bar_height( ) -> Result { app.native_bridge().get_status_bar_height() } + +#[command] +pub(crate) async fn get_sys_fonts_list( + app: AppHandle, +) -> Result { + app.native_bridge().get_sys_fonts_list() +} diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/desktop.rs b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/desktop.rs index 2db2b046..33f4e781 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/desktop.rs +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/desktop.rs @@ -47,4 +47,13 @@ impl NativeBridge { pub fn get_status_bar_height(&self) -> crate::Result { Err(crate::Error::UnsupportedPlatformError) } + + pub fn get_sys_fonts_list(&self) -> crate::Result { + let font_collection = font_enumeration::Collection::new().unwrap(); + let mut fonts = Vec::new(); + for font in font_collection.all() { + fonts.push(font.font_name.clone()); + } + Ok(GetSysFontsListResponse { fonts, error: None }) + } } diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/lib.rs b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/lib.rs index 5f0d5b2e..559fcd58 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/lib.rs +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/lib.rs @@ -44,6 +44,7 @@ pub fn init() -> TauriPlugin { commands::install_package, commands::set_system_ui_visibility, commands::get_status_bar_height, + commands::get_sys_fonts_list, ]) .setup(|app, api| { #[cfg(mobile)] diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/mobile.rs b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/mobile.rs index 924655e9..3a8cc0bc 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/mobile.rs +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/mobile.rs @@ -85,3 +85,11 @@ impl NativeBridge { .map_err(Into::into) } } + +impl NativeBridge { + pub fn get_sys_fonts_list(&self) -> crate::Result { + self.0 + .run_mobile_plugin("get_sys_fonts_list", ()) + .map_err(Into::into) + } +} diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/models.rs b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/models.rs index 5451eb9f..64b004ce 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/models.rs +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-bridge/src/models.rs @@ -65,3 +65,10 @@ pub struct GetStatusBarHeightResponse { pub height: u32, pub error: Option, } + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GetSysFontsListResponse { + pub fonts: Vec, + pub error: Option, +} diff --git a/apps/readest-app/src-tauri/src/lib.rs b/apps/readest-app/src-tauri/src/lib.rs index c6321e25..c6685a46 100644 --- a/apps/readest-app/src-tauri/src/lib.rs +++ b/apps/readest-app/src-tauri/src/lib.rs @@ -105,17 +105,6 @@ async fn start_server(window: Window) -> Result { .map_err(|err| err.to_string()) } -#[cfg(desktop)] -#[command] -async fn list_fonts() -> Result, String> { - let font_collection = font_enumeration::Collection::new().unwrap(); - let mut fonts = Vec::new(); - for font in font_collection.all() { - fonts.push(font.family_name.clone()); - } - Ok(fonts) -} - #[derive(Clone, serde::Serialize)] #[allow(dead_code)] struct Payload { @@ -138,8 +127,6 @@ pub fn run() { macos::apple_auth::start_apple_sign_in, #[cfg(target_os = "macos")] macos::traffic_light::set_traffic_lights, - #[cfg(desktop)] - list_fonts ]) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_opener::init()) diff --git a/apps/readest-app/src/app/library/components/SettingsMenu.tsx b/apps/readest-app/src/app/library/components/SettingsMenu.tsx index e197b6d7..6c2179ea 100644 --- a/apps/readest-app/src/app/library/components/SettingsMenu.tsx +++ b/apps/readest-app/src/app/library/components/SettingsMenu.tsx @@ -12,6 +12,7 @@ import { useAuth } from '@/context/AuthContext'; import { useEnv } from '@/context/EnvContext'; import { useSettingsStore } from '@/store/settingsStore'; import { useTranslation } from '@/hooks/useTranslation'; +import { useResponsiveSize } from '@/hooks/useResponsiveSize'; import { getStoragePlanData } from '@/utils/access'; import { navigateToLogin, navigateToProfile } from '@/utils/nav'; import { tauriHandleSetAlwaysOnTop, tauriHandleToggleFullScreen } from '@/utils/window'; @@ -37,6 +38,7 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { const [isAutoImportBooksOnOpen, setIsAutoImportBooksOnOpen] = useState( settings.autoImportBooksOnOpen, ); + const iconSize = useResponsiveSize(16); const showAboutReadest = () => { setAboutDialogVisible(true); @@ -147,10 +149,10 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { {_('User ) : ( PiUserCircleCheck diff --git a/apps/readest-app/src/app/reader/components/settings/FontDropDown.tsx b/apps/readest-app/src/app/reader/components/settings/FontDropDown.tsx index a113c121..98fc6807 100644 --- a/apps/readest-app/src/app/reader/components/settings/FontDropDown.tsx +++ b/apps/readest-app/src/app/reader/components/settings/FontDropDown.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { FiChevronUp, FiChevronLeft } from 'react-icons/fi'; import { MdCheck } from 'react-icons/md'; import { useTranslation } from '@/hooks/useTranslation'; -import { useDefaultIconSize, useResponsiveSize } from '@/hooks/useResponsiveSize'; +import { useResponsiveSize } from '@/hooks/useResponsiveSize'; interface DropdownProps { family?: string; @@ -24,33 +24,40 @@ const FontDropdown: React.FC = ({ }) => { const _ = useTranslation(); const iconSize16 = useResponsiveSize(16); - const defaultIconSize = useDefaultIconSize(); const allOptions = [...options, ...(moreOptions ?? [])]; const selectedOption = allOptions.find((option) => option.option === selected) ?? allOptions[0]!; return (
    {options.map(({ option, label }) => (
  • onSelect(option)}> -
    - - {selected === option && } +
    + + {selected === option && } {label || option} @@ -60,8 +67,8 @@ const FontDropdown: React.FC = ({ ))} {moreOptions && moreOptions.length > 0 && (
  • -
    - +
    + {_('System Fonts')} @@ -69,15 +76,17 @@ const FontDropdown: React.FC = ({
      {moreOptions.map((option, index) => (
    • onSelect(option.option)}> -
      - - {selected === option.option && } +
      + + {selected === option.option && ( + + )} {option.label || option.option} diff --git a/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx b/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx index f38d3d2f..d710c62f 100644 --- a/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react'; import { ANDROID_FONTS, + CJK_EXCLUDE_PATTENS, CJK_FONTS_PATTENS, CJK_NAMES_PATTENS, CJK_SANS_SERIF_FONTS, @@ -19,12 +20,21 @@ import { useReaderStore } from '@/store/readerStore'; import { useTranslation } from '@/hooks/useTranslation'; import { useEnv } from '@/context/EnvContext'; import { getOSPlatform, isCJKEnv } from '@/utils/misc'; -import { getSysFontsList } from '@/utils/font'; +import { getSysFontsList } from '@/utils/bridge'; import { isTauriAppPlatform } from '@/services/environment'; import { saveViewSettings } from '../../utils/viewSettingsHelper'; import NumberInput from './NumberInput'; import FontDropdown from './FontDropDown'; +const genCJKFontsList = (sysFonts: string[]) => { + return Array.from(new Set([...sysFonts, ...CJK_SERIF_FONTS, ...CJK_SANS_SERIF_FONTS])) + .filter((font) => CJK_FONTS_PATTENS.test(font) || CJK_NAMES_PATTENS.test(font)) + .filter((font) => !CJK_EXCLUDE_PATTENS.test(font)) + .sort((a, b) => a.localeCompare(b)); +}; + +const isSymbolicFontName = (font: string) => + /emoji|icons|symbol|dingbats|ornaments|webdings|wingdings|miuiex/i.test(font); interface FontFaceProps { className?: string; family: string; @@ -51,7 +61,7 @@ const FontFace = ({ const _ = useTranslation(); return (
      - {label} + {label} ({ option, label: _(option) }))} @@ -66,7 +76,7 @@ const FontFace = ({ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { const _ = useTranslation(); - const { envConfig, appService } = useEnv(); + const { envConfig } = useEnv(); const { getView, getViewSettings } = useReaderStore(); const viewSettings = getViewSettings(bookKey)!; const view = getView(bookKey)!; @@ -113,19 +123,28 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { const [sansSerifFont, setSansSerifFont] = useState(viewSettings.sansSerifFont!); const [monospaceFont, setMonospaceFont] = useState(viewSettings.monospaceFont!); const [fontWeight, setFontWeight] = useState(viewSettings.fontWeight!); - const [CJKFonts] = useState(() => { - return Array.from(new Set([...sysFonts, ...CJK_SERIF_FONTS, ...CJK_SANS_SERIF_FONTS])) - .filter((font) => CJK_FONTS_PATTENS.test(font) || CJK_NAMES_PATTENS.test(font)) - .sort((a, b) => a.localeCompare(b)); + const [CJKFonts, setCJKFonts] = useState(() => { + return genCJKFontsList(sysFonts); }); useEffect(() => { - if (isTauriAppPlatform() && appService?.hasSysFontsList) { - getSysFontsList().then((fonts) => { - setSysFonts(fonts); + setCJKFonts((prev) => { + const newFonts = genCJKFontsList(sysFonts); + return prev.length !== newFonts.length ? newFonts : prev; + }); + }, [sysFonts]); + + useEffect(() => { + if (isTauriAppPlatform()) { + getSysFontsList().then((res) => { + if (res.error) { + console.error('Failed to get system fonts list:', res.error); + return; + } + const fonts = res.fonts.filter((font) => font && !isSymbolicFontName(font)); + setSysFonts([...new Set(fonts)].sort((a, b) => a.localeCompare(b))); }); } - // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { diff --git a/apps/readest-app/src/services/appService.ts b/apps/readest-app/src/services/appService.ts index ab1d8b96..6c77712f 100644 --- a/apps/readest-app/src/services/appService.ts +++ b/apps/readest-app/src/services/appService.ts @@ -58,7 +58,6 @@ export abstract class BaseAppService implements AppService { hasRoundedWindow = false; hasSafeAreaInset = false; hasHaptics = false; - hasSysFontsList = false; hasUpdater = false; abstract fs: FileSystem; diff --git a/apps/readest-app/src/services/constants.ts b/apps/readest-app/src/services/constants.ts index 60ddc6be..5aa6fb62 100644 --- a/apps/readest-app/src/services/constants.ts +++ b/apps/readest-app/src/services/constants.ts @@ -434,6 +434,10 @@ export const ANDROID_FONTS = [ ]; export const CJK_NAMES_PATTENS = /[\u3040-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF]/; +export const CJK_EXCLUDE_PATTENS = new RegExp( + ['AlBayan', 'STIX', 'Kailasa', 'ITCTT', 'Luminari', 'Myanmar'].join('|'), + 'i', +); export const CJK_FONTS_PATTENS = new RegExp( [ 'CJK', @@ -461,7 +465,6 @@ export const CJK_FONTS_PATTENS = new RegExp( 'Yu\\s?Gothic', 'Yu\\s?Mincho', 'Mincho', - 'Gothic', 'Nanum', 'Malgun', 'Gulim', diff --git a/apps/readest-app/src/services/nativeAppService.ts b/apps/readest-app/src/services/nativeAppService.ts index 92a0d6b8..f6dd39ea 100644 --- a/apps/readest-app/src/services/nativeAppService.ts +++ b/apps/readest-app/src/services/nativeAppService.ts @@ -220,7 +220,6 @@ export class NativeAppService extends BaseAppService { override hasRoundedWindow = !(OS_TYPE === 'ios' || OS_TYPE === 'android') && !!window.IS_ROUNDED; override hasSafeAreaInset = OS_TYPE === 'ios' || OS_TYPE === 'android'; override hasHaptics = OS_TYPE === 'ios' || OS_TYPE === 'android'; - override hasSysFontsList = !(OS_TYPE === 'ios' || OS_TYPE === 'android'); override hasUpdater = OS_TYPE !== 'ios' && !process.env['NEXT_PUBLIC_DISABLE_UPDATER']; override resolvePath(fp: string, base: BaseDir): { baseDir: number; base: BaseDir; fp: string } { diff --git a/apps/readest-app/src/types/system.ts b/apps/readest-app/src/types/system.ts index 2c576dce..ace4c7d9 100644 --- a/apps/readest-app/src/types/system.ts +++ b/apps/readest-app/src/types/system.ts @@ -33,7 +33,6 @@ export interface AppService { hasRoundedWindow: boolean; hasSafeAreaInset: boolean; hasHaptics: boolean; - hasSysFontsList: boolean; hasUpdater: boolean; isMobile: boolean; isAppDataSandbox: boolean; diff --git a/apps/readest-app/src/utils/bridge.ts b/apps/readest-app/src/utils/bridge.ts index 03bd6178..1892d702 100644 --- a/apps/readest-app/src/utils/bridge.ts +++ b/apps/readest-app/src/utils/bridge.ts @@ -38,6 +38,11 @@ export interface GetStatusBarHeightResponse { error?: string; } +export interface GetSystemFontsListResponse { + fonts: string[]; + error?: string; +} + export async function copyURIToPath(request: CopyURIRequest): Promise { const result = await invoke('plugin:native-bridge|copy_uri_to_path', { payload: request, @@ -79,3 +84,16 @@ export async function getStatusBarHeight(): Promise ); return result; } + +let cachedSysFontsResult: GetSystemFontsListResponse | null = null; + +export async function getSysFontsList(): Promise { + if (cachedSysFontsResult) { + return cachedSysFontsResult; + } + const result = await invoke( + 'plugin:native-bridge|get_sys_fonts_list', + ); + cachedSysFontsResult = result; + return result; +} diff --git a/apps/readest-app/src/utils/font.ts b/apps/readest-app/src/utils/font.ts deleted file mode 100644 index 2b65c1a6..00000000 --- a/apps/readest-app/src/utils/font.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { invoke } from '@tauri-apps/api/core'; -import { getOSPlatform } from './misc'; - -let cachedSysFonts: string[] | null = null; - -export const FONT_ENUM_SUPPORTED_OS_PLATFORMS = ['macos', 'windows', 'linux']; - -const isSymbolicFontName = (font: string) => - /emoji|icons|symbol|dingbats|ornaments|webdings|wingdings/i.test(font); - -export const getSysFontsList = async (): Promise => { - if (cachedSysFonts) { - return cachedSysFonts; - } - - try { - const osPlatform = getOSPlatform(); - if (FONT_ENUM_SUPPORTED_OS_PLATFORMS.includes(osPlatform)) { - const fonts = await invoke('list_fonts'); - cachedSysFonts = [...new Set(fonts.filter((font) => !isSymbolicFontName(font)))].sort(); - return cachedSysFonts; - } else { - console.warn(`Unsupported platform: ${osPlatform}`); - return []; - } - } catch (error) { - console.error('Error fetching font list:', error); - return []; - } -};