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 7db8f5dd..48e5a288 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 @@ -296,7 +296,11 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) { .trim() fontList.add(fontName) } - ret.put("fonts", JSONArray(fontList)) + var fontDict = JSObject() + for (fontName in fontList) { + fontDict.put(fontName, fontName) + } + ret.put("fonts", fontDict) } catch (e: Exception) { ret.put("error", e.message) } 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 db26cb8a..13a13ea1 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 @@ -299,22 +299,24 @@ class NativeBridgePlugin: Plugin { } @objc public func get_sys_fonts_list(_ invoke: Invoke) throws { - var fontList: [String] = [] + var fontDict: [String: String] = [:] for family in UIFont.familyNames.sorted() { if let localized = getLocalizedDisplayName(familyName: family) { - fontList.append(localized) + fontDict[family] = localized } else { let fontNames = UIFont.fontNames(forFamilyName: family) if fontNames.isEmpty { - fontList.append(family) + fontDict[family] = family } else { - fontList.append(contentsOf: fontNames) + for fontName in fontNames { + fontDict[fontName] = family + } } } } - invoke.resolve(["fonts": fontList]) + invoke.resolve(["fonts": fontDict]) } @objc public func intercept_keys(_ invoke: Invoke) { 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 de854d57..80fd1f57 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 @@ -1,4 +1,5 @@ use serde::de::DeserializeOwned; +use std::collections::HashMap; use tauri::{plugin::PluginApi, AppHandle, Runtime}; use crate::models::*; @@ -50,9 +51,9 @@ impl NativeBridge { pub fn get_sys_fonts_list(&self) -> crate::Result { let font_collection = font_enumeration::Collection::new().unwrap(); - let mut fonts = Vec::new(); + let mut fonts = HashMap::new(); for font in font_collection.all() { - fonts.push(font.font_name.clone()); + fonts.insert(font.font_name.clone(), font.family_name.clone()); } Ok(GetSysFontsListResponse { fonts, error: None }) } 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 00046c93..23e0eb2c 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 @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use std::collections::HashMap; #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -69,7 +70,7 @@ pub struct GetStatusBarHeightResponse { #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct GetSysFontsListResponse { - pub fonts: Vec, + pub fonts: HashMap, pub error: Option, } 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 98fc6807..b97ad63a 100644 --- a/apps/readest-app/src/app/reader/components/settings/FontDropDown.tsx +++ b/apps/readest-app/src/app/reader/components/settings/FontDropDown.tsx @@ -2,6 +2,7 @@ import clsx from 'clsx'; import React from 'react'; import { FiChevronUp, FiChevronLeft } from 'react-icons/fi'; import { MdCheck } from 'react-icons/md'; +import { useEnv } from '@/context/EnvContext'; import { useTranslation } from '@/hooks/useTranslation'; import { useResponsiveSize } from '@/hooks/useResponsiveSize'; @@ -23,6 +24,7 @@ const FontDropdown: React.FC = ({ onGetFontFamily, }) => { const _ = useTranslation(); + const { appService } = useEnv(); const iconSize16 = useResponsiveSize(16); const allOptions = [...options, ...(moreOptions ?? [])]; const selectedOption = allOptions.find((option) => option.option === selected) ?? allOptions[0]!; @@ -88,7 +90,13 @@ const FontDropdown: React.FC = ({ )} - + {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 5ed3c11a..bb29265b 100644 --- a/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx +++ b/apps/readest-app/src/app/reader/components/settings/FontPanel.tsx @@ -142,12 +142,26 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => { useEffect(() => { if (isTauriAppPlatform()) { getSysFontsList().then((res) => { - if (res.error || res.fonts.length === 0) { + if (res.error || Object.keys(res.fonts).length === 0) { 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))); + const processedFonts: string[] = []; + Object.entries(res.fonts).forEach(([fontName, fontFamily]) => { + if (!fontName || isSymbolicFontName(fontName)) return; + + const fontsInFamily = Object.entries(res.fonts).filter( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + ([_, family]) => family === fontFamily, + ); + + if (fontsInFamily.length === 1) { + processedFonts.push(fontFamily); + } else { + processedFonts.push(fontName); + } + }); + setSysFonts([...new Set(processedFonts)].sort((a, b) => a.localeCompare(b))); }); } }, []); diff --git a/apps/readest-app/src/services/appService.ts b/apps/readest-app/src/services/appService.ts index 7c00c974..129c5f90 100644 --- a/apps/readest-app/src/services/appService.ts +++ b/apps/readest-app/src/services/appService.ts @@ -48,6 +48,7 @@ export abstract class BaseAppService implements AppService { localBooksDir = ''; isMobile = false; isMacOSApp = false; + isLinuxApp = false; isAppDataSandbox = false; isAndroidApp = false; isIOSApp = false; diff --git a/apps/readest-app/src/services/nativeAppService.ts b/apps/readest-app/src/services/nativeAppService.ts index 6529f58b..0b93c38c 100644 --- a/apps/readest-app/src/services/nativeAppService.ts +++ b/apps/readest-app/src/services/nativeAppService.ts @@ -213,6 +213,7 @@ export class NativeAppService extends BaseAppService { override isAndroidApp = OS_TYPE === 'android'; override isIOSApp = OS_TYPE === 'ios'; override isMacOSApp = OS_TYPE === 'macos'; + override isLinuxApp = OS_TYPE === 'linux'; override isMobileApp = ['android', 'ios'].includes(OS_TYPE); override hasTrafficLight = OS_TYPE === 'macos'; override hasWindow = !(OS_TYPE === 'ios' || OS_TYPE === 'android'); diff --git a/apps/readest-app/src/types/system.ts b/apps/readest-app/src/types/system.ts index ebf80a84..59cf6e07 100644 --- a/apps/readest-app/src/types/system.ts +++ b/apps/readest-app/src/types/system.ts @@ -40,6 +40,7 @@ export interface AppService { isAndroidApp: boolean; isIOSApp: boolean; isMacOSApp: boolean; + isLinuxApp: boolean; selectDirectory(): Promise; selectFiles(name: string, extensions: string[]): Promise; diff --git a/apps/readest-app/src/utils/bridge.ts b/apps/readest-app/src/utils/bridge.ts index 1a9b49e3..64da07ec 100644 --- a/apps/readest-app/src/utils/bridge.ts +++ b/apps/readest-app/src/utils/bridge.ts @@ -39,7 +39,7 @@ export interface GetStatusBarHeightResponse { } export interface GetSystemFontsListResponse { - fonts: string[]; + fonts: Record; // { fontName: fontFamily } error?: string; }