fix(reader): make webview align with reading font family (#882)

* fix(reader): make webview align with reading font family

* feat(reader): external font support in webview
This commit is contained in:
junkfood 2024-11-20 16:17:40 +09:00 committed by GitHub
parent 47a911ae0d
commit 697e94eb88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 4 deletions

View File

@ -16,6 +16,7 @@ import androidx.compose.ui.viewinterop.AndroidView
import me.ash.reader.infrastructure.preference.LocalOpenLink import me.ash.reader.infrastructure.preference.LocalOpenLink
import me.ash.reader.infrastructure.preference.LocalOpenLinkSpecificBrowser import me.ash.reader.infrastructure.preference.LocalOpenLinkSpecificBrowser
import me.ash.reader.infrastructure.preference.LocalReadingBionicReading import me.ash.reader.infrastructure.preference.LocalReadingBionicReading
import me.ash.reader.infrastructure.preference.LocalReadingFonts
import me.ash.reader.infrastructure.preference.LocalReadingImageHorizontalPadding import me.ash.reader.infrastructure.preference.LocalReadingImageHorizontalPadding
import me.ash.reader.infrastructure.preference.LocalReadingImageRoundedCorners import me.ash.reader.infrastructure.preference.LocalReadingImageRoundedCorners
import me.ash.reader.infrastructure.preference.LocalReadingPageTonalElevation import me.ash.reader.infrastructure.preference.LocalReadingPageTonalElevation
@ -27,6 +28,8 @@ import me.ash.reader.infrastructure.preference.LocalReadingTextFontSize
import me.ash.reader.infrastructure.preference.LocalReadingTextHorizontalPadding import me.ash.reader.infrastructure.preference.LocalReadingTextHorizontalPadding
import me.ash.reader.infrastructure.preference.LocalReadingTextLetterSpacing import me.ash.reader.infrastructure.preference.LocalReadingTextLetterSpacing
import me.ash.reader.infrastructure.preference.LocalReadingTextLineHeight import me.ash.reader.infrastructure.preference.LocalReadingTextLineHeight
import me.ash.reader.infrastructure.preference.ReadingFontsPreference
import me.ash.reader.ui.ext.ExternalFonts
import me.ash.reader.ui.ext.openURL import me.ash.reader.ui.ext.openURL
import me.ash.reader.ui.ext.surfaceColorAtElevation import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.theme.palette.alwaysLight import me.ash.reader.ui.theme.palette.alwaysLight
@ -55,6 +58,7 @@ fun RYWebView(
val linkTextColor: Int = MaterialTheme.colorScheme.primary.toArgb() val linkTextColor: Int = MaterialTheme.colorScheme.primary.toArgb()
val subheadBold: Boolean = LocalReadingSubheadBold.current.value val subheadBold: Boolean = LocalReadingSubheadBold.current.value
val subheadUpperCase: Boolean = LocalReadingSubheadUpperCase.current.value val subheadUpperCase: Boolean = LocalReadingSubheadUpperCase.current.value
val readingFonts = LocalReadingFonts.current
val fontSize: Int = LocalReadingTextFontSize.current val fontSize: Int = LocalReadingTextFontSize.current
val letterSpacing: Float = LocalReadingTextLetterSpacing.current val letterSpacing: Float = LocalReadingTextLetterSpacing.current
val lineHeight: Float = LocalReadingTextLineHeight.current val lineHeight: Float = LocalReadingTextLineHeight.current
@ -69,6 +73,7 @@ fun RYWebView(
mutableStateOf( mutableStateOf(
WebViewLayout.get( WebViewLayout.get(
context = context, context = context,
readingFontsPreference = readingFonts,
webViewClient = WebViewClient( webViewClient = WebViewClient(
context = context, context = context,
refererDomain = refererDomain, refererDomain = refererDomain,
@ -81,6 +86,11 @@ fun RYWebView(
) )
} }
val fontPath =
if (readingFonts is ReadingFontsPreference.External) ExternalFonts.FontType.ReadingFont.toPath(
context
) else null
AndroidView( AndroidView(
modifier = modifier, modifier = modifier,
factory = { webView }, factory = { webView },
@ -95,6 +105,7 @@ fun RYWebView(
WebViewHtml.HTML.format( WebViewHtml.HTML.format(
WebViewStyle.get( WebViewStyle.get(
fontSize = fontSize, fontSize = fontSize,
fontPath = fontPath,
lineHeight = lineHeight, lineHeight = lineHeight,
letterSpacing = letterSpacing, letterSpacing = letterSpacing,
textMargin = textMargin, textMargin = textMargin,

View File

@ -5,12 +5,15 @@ import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.webkit.JavascriptInterface import android.webkit.JavascriptInterface
import android.webkit.WebView import android.webkit.WebView
import me.ash.reader.infrastructure.preference.BasicFontsPreference
import me.ash.reader.infrastructure.preference.ReadingFontsPreference
object WebViewLayout { object WebViewLayout {
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
fun get( fun get(
context: Context, context: Context,
readingFontsPreference: ReadingFontsPreference,
webViewClient: WebViewClient, webViewClient: WebViewClient,
onImageClick: ((imgUrl: String, altText: String) -> Unit)? = null, onImageClick: ((imgUrl: String, altText: String) -> Unit)? = null,
) = WebView(context).apply { ) = WebView(context).apply {
@ -20,6 +23,20 @@ object WebViewLayout {
isVerticalScrollBarEnabled = true isVerticalScrollBarEnabled = true
setBackgroundColor(Color.TRANSPARENT) setBackgroundColor(Color.TRANSPARENT)
with(this.settings) { with(this.settings) {
standardFontFamily = when (readingFontsPreference) {
ReadingFontsPreference.Cursive -> "cursive"
ReadingFontsPreference.Monospace -> "monospace"
ReadingFontsPreference.SansSerif -> "sans-serif"
ReadingFontsPreference.Serif -> "serif"
ReadingFontsPreference.External -> {
allowFileAccess = true
allowFileAccessFromFileURLs = true
"sans-serif"
}
else -> "sans-serif"
}
domStorageEnabled = true domStorageEnabled = true
javaScriptEnabled = true javaScriptEnabled = true
addJavascriptInterface(object : JavaScriptInterface { addJavascriptInterface(object : JavaScriptInterface {

View File

@ -4,8 +4,24 @@ object WebViewStyle {
private fun argbToCssColor(argb: Int): String = String.format("#%06X", 0xFFFFFF and argb) private fun argbToCssColor(argb: Int): String = String.format("#%06X", 0xFFFFFF and argb)
private fun applyFontFace(
fontPath: String? = null
): String = if (fontPath != null) """
@font-face {
font-family: external;
src: url("file://$fontPath")
}
""".trimIndent() else ""
private fun applyFontFamily(
fontPath: String? = null
): String = if (fontPath != null) """
--font-family: external;
""".trimIndent() else ""
fun get( fun get(
fontSize: Int, fontSize: Int,
fontPath: String? = null,
lineHeight: Float, lineHeight: Float,
letterSpacing: Float, letterSpacing: Float,
textMargin: Int, textMargin: Int,
@ -24,21 +40,22 @@ object WebViewStyle {
selectionTextColor: Int, selectionTextColor: Int,
selectionBgColor: Int, selectionBgColor: Int,
): String = """ ): String = """
${applyFontFace(fontPath)}
:root { :root {
/* --font-family: Inter; */ ${applyFontFamily(fontPath)}
--font-size: ${fontSize}px; --font-size: ${fontSize}px;
--line-height: ${lineHeight * 1.5f}; --line-height: ${lineHeight * 1.5f};
--letter-spacing: ${letterSpacing}px; --letter-spacing: ${letterSpacing}px;
--text-margin: ${textMargin}px; --text-margin: ${textMargin}px;
--text-color: ${argbToCssColor(textColor)}; --text-color: ${argbToCssColor(textColor)};
--text-bold: ${if(textBold) "600" else "normal"}; --text-bold: ${if (textBold) "600" else "normal"};
--text-align: ${textAlign}; --text-align: ${textAlign};
--bold-text-color: ${argbToCssColor(boldTextColor)}; --bold-text-color: ${argbToCssColor(boldTextColor)};
--link-text-color: ${argbToCssColor(linkTextColor)}; --link-text-color: ${argbToCssColor(linkTextColor)};
--selection-text-color: ${argbToCssColor(selectionTextColor)}; --selection-text-color: ${argbToCssColor(selectionTextColor)};
--selection-bg-color: ${argbToCssColor(selectionBgColor)}; --selection-bg-color: ${argbToCssColor(selectionBgColor)};
--subhead-bold: ${if(subheadBold) "600" else "normal"}; --subhead-bold: ${if (subheadBold) "600" else "normal"};
--subhead-upper-case: ${if(subheadUpperCase) "uppercase" else "none"}; --subhead-upper-case: ${if (subheadUpperCase) "uppercase" else "none"};
--img-margin: ${imgMargin}px; --img-margin: ${imgMargin}px;
--img-border-radius: ${imgBorderRadius}px; --img-border-radius: ${imgBorderRadius}px;
--content-padding; --content-padding;