mirror of
https://github.com/readest/readest.git
synced 2026-04-29 03:50:52 +00:00
feat: retrieve system fonts on iOS and Android and show font weight variants, closes #949 and closes #557 (#976)
This commit is contained in:
parent
9303ec8c5f
commit
a424ae8b15
25 changed files with 254 additions and 84 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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<String>()
|
||||
val fontFileList = mutableListOf<String>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ const COMMANDS: &[&str] = &[
|
|||
"install_package",
|
||||
"set_system_ui_visibility",
|
||||
"get_status_bar_height",
|
||||
"get_sys_fonts_list",
|
||||
];
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -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<CFString>?
|
||||
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")
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
@ -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.
|
|||
<tr>
|
||||
<td>
|
||||
|
||||
`native-bridge:allow-get-sys-fonts-list`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the get_sys_fonts_list command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`native-bridge:deny-get-sys-fonts-list`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the get_sys_fonts_list command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`native-bridge:allow-install-package`
|
||||
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -8,4 +8,5 @@ permissions = [
|
|||
"allow-install-package",
|
||||
"allow-set-system-ui-visibility",
|
||||
"allow-get-status-bar-height",
|
||||
"allow-get-sys-fonts-list",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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`"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,3 +58,10 @@ pub(crate) async fn get_status_bar_height<R: Runtime>(
|
|||
) -> Result<GetStatusBarHeightResponse> {
|
||||
app.native_bridge().get_status_bar_height()
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub(crate) async fn get_sys_fonts_list<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
) -> Result<GetSysFontsListResponse> {
|
||||
app.native_bridge().get_sys_fonts_list()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,4 +47,13 @@ impl<R: Runtime> NativeBridge<R> {
|
|||
pub fn get_status_bar_height(&self) -> crate::Result<GetStatusBarHeightResponse> {
|
||||
Err(crate::Error::UnsupportedPlatformError)
|
||||
}
|
||||
|
||||
pub fn get_sys_fonts_list(&self) -> crate::Result<GetSysFontsListResponse> {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|||
commands::install_package,
|
||||
commands::set_system_ui_visibility,
|
||||
commands::get_status_bar_height,
|
||||
commands::get_sys_fonts_list,
|
||||
])
|
||||
.setup(|app, api| {
|
||||
#[cfg(mobile)]
|
||||
|
|
|
|||
|
|
@ -85,3 +85,11 @@ impl<R: Runtime> NativeBridge<R> {
|
|||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Runtime> NativeBridge<R> {
|
||||
pub fn get_sys_fonts_list(&self) -> crate::Result<GetSysFontsListResponse> {
|
||||
self.0
|
||||
.run_mobile_plugin("get_sys_fonts_list", ())
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,3 +65,10 @@ pub struct GetStatusBarHeightResponse {
|
|||
pub height: u32,
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetSysFontsListResponse {
|
||||
pub fonts: Vec<String>,
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue