Support using external fonts as basic and reading fonts (#333)
This commit is contained in:
parent
c10354ce34
commit
4b04f96b4c
@ -57,6 +57,8 @@ Nachfolgend sind die bisher erzielten Fortschritte und die Ziele aufgeführt, an
|
||||
- [ ] Android Widget
|
||||
- [ ] ...
|
||||
|
||||
[Was mache ich gerade?](https://github.com/users/Ashinch/projects/2)
|
||||
|
||||
## Integration
|
||||
|
||||
**Read You** ist mit einigen APIs von Drittanbietern kompatibel, um bei der Nutzung Ihrer bestehenden Cloud-Konten als Datenquellen zu unterstützen.
|
||||
|
@ -55,6 +55,8 @@
|
||||
- [ ] Android 微件 / 小组件
|
||||
- [ ] ...
|
||||
|
||||
[我目前在做什么?](https://github.com/users/Ashinch/projects/2)
|
||||
|
||||
## 集成
|
||||
|
||||
**Read You** 也集成了一些第三方服务 API,支持您使用已有的云端账户来作为数据源。
|
||||
|
@ -57,6 +57,8 @@ The following are the progress made so far and the goals to be worked on in the
|
||||
- [ ] Android widget
|
||||
- [ ] ...
|
||||
|
||||
[What am I doing now?](https://github.com/users/Ashinch/projects/2)
|
||||
|
||||
## Integration
|
||||
|
||||
**Read You** integrates with some of third-party service APIs to support you in using your existing cloud accounts as data sources.
|
||||
|
@ -0,0 +1,56 @@
|
||||
package me.ash.reader.data.model.preference
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import me.ash.reader.R
|
||||
import me.ash.reader.ui.ext.DataStoreKeys
|
||||
import me.ash.reader.ui.ext.ExternalFonts
|
||||
import me.ash.reader.ui.ext.dataStore
|
||||
import me.ash.reader.ui.ext.put
|
||||
import me.ash.reader.ui.theme.SystemTypography
|
||||
|
||||
sealed class BasicFontsPreference(val value: Int) : Preference() {
|
||||
object System : BasicFontsPreference(0)
|
||||
object External : BasicFontsPreference(5)
|
||||
|
||||
override fun put(context: Context, scope: CoroutineScope) {
|
||||
scope.launch {
|
||||
context.dataStore.put(DataStoreKeys.BasicFonts, value)
|
||||
}
|
||||
}
|
||||
|
||||
fun toDesc(context: Context): String =
|
||||
when (this) {
|
||||
System -> context.getString(R.string.system_default)
|
||||
External -> context.getString(R.string.external_fonts)
|
||||
}
|
||||
|
||||
fun asFontFamily(context: Context): FontFamily =
|
||||
when (this) {
|
||||
System -> FontFamily.Default
|
||||
External -> ExternalFonts.loadBasicTypography(context).displayLarge.fontFamily ?: FontFamily.Default
|
||||
}
|
||||
|
||||
fun asTypography(context: Context): Typography =
|
||||
when (this) {
|
||||
System -> SystemTypography
|
||||
External -> ExternalFonts.loadBasicTypography(context)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val default = System
|
||||
val values = listOf(System, External)
|
||||
|
||||
fun fromPreferences(preferences: Preferences): BasicFontsPreference =
|
||||
when (preferences[DataStoreKeys.BasicFonts.key]) {
|
||||
0 -> System
|
||||
5 -> External
|
||||
else -> default
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ fun Preferences.toSettings(): Settings {
|
||||
customPrimaryColor = CustomPrimaryColorPreference.fromPreferences(this),
|
||||
darkTheme = DarkThemePreference.fromPreferences(this),
|
||||
amoledDarkTheme = AmoledDarkThemePreference.fromPreferences(this),
|
||||
basicFonts = BasicFontsPreference.fromPreferences(this),
|
||||
|
||||
// Feeds page
|
||||
feedsFilterBarStyle = FeedsFilterBarStylePreference.fromPreferences(this),
|
||||
|
@ -7,6 +7,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import me.ash.reader.R
|
||||
import me.ash.reader.ui.ext.DataStoreKeys
|
||||
import me.ash.reader.ui.ext.ExternalFonts
|
||||
import me.ash.reader.ui.ext.dataStore
|
||||
import me.ash.reader.ui.ext.put
|
||||
|
||||
@ -34,14 +35,14 @@ sealed class ReadingFontsPreference(val value: Int) : Preference() {
|
||||
External -> context.getString(R.string.external_fonts)
|
||||
}
|
||||
|
||||
fun asFontFamily(): FontFamily =
|
||||
fun asFontFamily(context: Context): FontFamily =
|
||||
when (this) {
|
||||
System -> FontFamily.Default
|
||||
Serif -> FontFamily.Serif
|
||||
SansSerif -> FontFamily.SansSerif
|
||||
Monospace -> FontFamily.Monospace
|
||||
Cursive -> FontFamily.Cursive
|
||||
External -> FontFamily.Default
|
||||
External -> ExternalFonts.loadReadingTypography(context).displayLarge.fontFamily ?: FontFamily.Default
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -25,6 +25,7 @@ data class Settings(
|
||||
val customPrimaryColor: String = CustomPrimaryColorPreference.default,
|
||||
val darkTheme: DarkThemePreference = DarkThemePreference.default,
|
||||
val amoledDarkTheme: AmoledDarkThemePreference = AmoledDarkThemePreference.default,
|
||||
val basicFonts: BasicFontsPreference = BasicFontsPreference.default,
|
||||
|
||||
// Feeds page
|
||||
val feedsFilterBarStyle: FeedsFilterBarStylePreference = FeedsFilterBarStylePreference.default,
|
||||
@ -95,6 +96,7 @@ val LocalDarkTheme =
|
||||
compositionLocalOf<DarkThemePreference> { DarkThemePreference.default }
|
||||
val LocalAmoledDarkTheme =
|
||||
compositionLocalOf<AmoledDarkThemePreference> { AmoledDarkThemePreference.default }
|
||||
val LocalBasicFonts = compositionLocalOf<BasicFontsPreference> { BasicFontsPreference.default }
|
||||
|
||||
// Feeds page
|
||||
val LocalFeedsFilterBarStyle =
|
||||
@ -141,8 +143,10 @@ val LocalFlowArticleListTonalElevation =
|
||||
// Reading page
|
||||
val LocalReadingTheme = compositionLocalOf<ReadingThemePreference> { ReadingThemePreference.default }
|
||||
val LocalReadingDarkTheme = compositionLocalOf<ReadingDarkThemePreference> { ReadingDarkThemePreference.default }
|
||||
val LocalReadingPageTonalElevation = compositionLocalOf<ReadingPageTonalElevationPreference> { ReadingPageTonalElevationPreference.default }
|
||||
val LocalReadingAutoHideToolbar = compositionLocalOf<ReadingAutoHideToolbarPreference> { ReadingAutoHideToolbarPreference.default }
|
||||
val LocalReadingPageTonalElevation =
|
||||
compositionLocalOf<ReadingPageTonalElevationPreference> { ReadingPageTonalElevationPreference.default }
|
||||
val LocalReadingAutoHideToolbar =
|
||||
compositionLocalOf<ReadingAutoHideToolbarPreference> { ReadingAutoHideToolbarPreference.default }
|
||||
val LocalReadingTextFontSize = compositionLocalOf { ReadingTextFontSizePreference.default }
|
||||
val LocalReadingLetterSpacing = compositionLocalOf { ReadingLetterSpacingPreference.default }
|
||||
val LocalReadingTextHorizontalPadding = compositionLocalOf { ReadingTextHorizontalPaddingPreference.default }
|
||||
@ -161,7 +165,8 @@ val LocalReadingSubheadUpperCase =
|
||||
compositionLocalOf<ReadingSubheadUpperCasePreference> { ReadingSubheadUpperCasePreference.default }
|
||||
val LocalReadingImageHorizontalPadding = compositionLocalOf { ReadingImageHorizontalPaddingPreference.default }
|
||||
val LocalReadingImageRoundedCorners = compositionLocalOf { ReadingImageRoundedCornersPreference.default }
|
||||
val LocalReadingImageMaximize = compositionLocalOf<ReadingImageMaximizePreference> { ReadingImageMaximizePreference.default }
|
||||
val LocalReadingImageMaximize =
|
||||
compositionLocalOf<ReadingImageMaximizePreference> { ReadingImageMaximizePreference.default }
|
||||
|
||||
// Interaction
|
||||
val LocalInitialPage = compositionLocalOf<InitialPagePreference> { InitialPagePreference.default }
|
||||
@ -192,12 +197,14 @@ fun SettingsProvider(
|
||||
LocalNewVersionLog provides settings.newVersionLog,
|
||||
LocalNewVersionSize provides settings.newVersionSize,
|
||||
LocalNewVersionDownloadUrl provides settings.newVersionDownloadUrl,
|
||||
LocalBasicFonts provides settings.basicFonts,
|
||||
|
||||
// Theme
|
||||
LocalThemeIndex provides settings.themeIndex,
|
||||
LocalCustomPrimaryColor provides settings.customPrimaryColor,
|
||||
LocalDarkTheme provides settings.darkTheme,
|
||||
LocalAmoledDarkTheme provides settings.amoledDarkTheme,
|
||||
LocalBasicFonts provides settings.basicFonts,
|
||||
|
||||
// Feeds page
|
||||
LocalFeedsTopBarTonalElevation provides settings.feedsTopBarTonalElevation,
|
||||
|
@ -26,6 +26,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
@ -79,7 +80,7 @@ fun bodyForeground(): Color = onSurfaceVariantColor()
|
||||
@ReadOnlyComposable
|
||||
fun bodyStyle(): TextStyle =
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
fontWeight = if (LocalReadingTextBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
fontSize = LocalReadingTextFontSize.current.sp,
|
||||
letterSpacing = LocalReadingLetterSpacing.current.sp,
|
||||
@ -92,7 +93,7 @@ fun bodyStyle(): TextStyle =
|
||||
@ReadOnlyComposable
|
||||
fun h1Style(): TextStyle =
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
fontSize = 28.sp,
|
||||
letterSpacing = 0.sp,
|
||||
@ -105,7 +106,7 @@ fun h1Style(): TextStyle =
|
||||
@ReadOnlyComposable
|
||||
fun h2Style(): TextStyle =
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
fontSize = 28.sp,
|
||||
letterSpacing = 0.sp,
|
||||
@ -118,7 +119,7 @@ fun h2Style(): TextStyle =
|
||||
@ReadOnlyComposable
|
||||
fun h3Style(): TextStyle =
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
fontSize = 19.sp,
|
||||
letterSpacing = 0.sp,
|
||||
@ -131,7 +132,7 @@ fun h3Style(): TextStyle =
|
||||
@ReadOnlyComposable
|
||||
fun h4Style(): TextStyle =
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
fontSize = 17.sp,
|
||||
letterSpacing = 0.sp,
|
||||
@ -144,7 +145,7 @@ fun h4Style(): TextStyle =
|
||||
@ReadOnlyComposable
|
||||
fun h5Style(): TextStyle =
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
fontSize = 17.sp,
|
||||
letterSpacing = 0.sp,
|
||||
@ -157,7 +158,7 @@ fun h5Style(): TextStyle =
|
||||
@ReadOnlyComposable
|
||||
fun h6Style(): TextStyle =
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
fontSize = 17.sp,
|
||||
letterSpacing = 0.sp,
|
||||
@ -171,7 +172,7 @@ fun h6Style(): TextStyle =
|
||||
fun captionStyle(): TextStyle =
|
||||
MaterialTheme.typography.bodySmall.merge(
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
color = bodyForeground().copy(alpha = 0.6f),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
@ -182,7 +183,7 @@ fun captionStyle(): TextStyle =
|
||||
@ReadOnlyComposable
|
||||
fun linkTextStyle(): TextStyle =
|
||||
TextStyle(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(LocalContext.current),
|
||||
fontSize = LocalReadingTextFontSize.current.sp,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
textDecoration = TextDecoration.Underline,
|
||||
|
@ -148,6 +148,12 @@ sealed class DataStoreKeys<T> {
|
||||
get() = booleanPreferencesKey("amoledDarkTheme")
|
||||
}
|
||||
|
||||
object BasicFonts : DataStoreKeys<Int>() {
|
||||
|
||||
override val key: Preferences.Key<Int>
|
||||
get() = intPreferencesKey("basicFonts")
|
||||
}
|
||||
|
||||
// Feeds page
|
||||
object FeedsFilterBarStyle : DataStoreKeys<Int>() {
|
||||
|
||||
|
117
app/src/main/java/me/ash/reader/ui/ext/ExternalFonts.kt
Normal file
117
app/src/main/java/me/ash/reader/ui/ext/ExternalFonts.kt
Normal file
@ -0,0 +1,117 @@
|
||||
package me.ash.reader.ui.ext
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.net.Uri
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import me.ash.reader.ui.theme.SystemTypography
|
||||
import java.io.File
|
||||
|
||||
class ExternalFonts(
|
||||
private val ctx: Context,
|
||||
private val uri: Uri,
|
||||
private val type: FontType,
|
||||
) {
|
||||
|
||||
enum class FontType(val value: String) {
|
||||
BasicFont("basic_font.ttf"),
|
||||
ReadingFont("reading_font.ttf"),
|
||||
;
|
||||
|
||||
fun toPath(ctx: Context): String = ctx.filesDir.absolutePath + File.separator + value
|
||||
}
|
||||
|
||||
private lateinit var fontByteArray: ByteArray
|
||||
|
||||
init {
|
||||
ctx.contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||
fontByteArray = inputStream.readBytes()
|
||||
// File(inputStream.readString()).let {
|
||||
// if (!it.exists()) throw IllegalArgumentException("Invalid path")
|
||||
// if (!it.isFile) throw IllegalArgumentException("Invalid path")
|
||||
// if (it.extension.lowercase() != "ttf") throw IllegalArgumentException("Only *.ttf fonts are supported")
|
||||
// fontByteArray = it
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
fun copyToInternalStorage() {
|
||||
File(type.toPath(ctx)).let {
|
||||
if (it.exists()) it.delete()
|
||||
if (it.createNewFile()) it.writeBytes(fontByteArray)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun loadBasicTypography(ctx: Context): Typography = loadTypography(ctx, FontType.BasicFont)
|
||||
|
||||
fun loadReadingTypography(ctx: Context): Typography = loadTypography(ctx, FontType.ReadingFont)
|
||||
|
||||
private var basicTypography: Typography? = null
|
||||
private var readingTypography: Typography? = null
|
||||
|
||||
private fun createFontFamily(ctx: Context, type: FontType): FontFamily =
|
||||
File(type.toPath(ctx)).takeIf { it.exists() }
|
||||
?.run { FontFamily(Typeface.createFromFile(this)) } ?: FontFamily.Default
|
||||
|
||||
private fun createTypography(fontFamily: FontFamily): Typography =
|
||||
Typography(
|
||||
displayLarge = SystemTypography.displayLarge.copy(
|
||||
fontFamily = fontFamily,
|
||||
),
|
||||
displayMedium = SystemTypography.displayMedium.copy(
|
||||
fontFamily = fontFamily,
|
||||
),
|
||||
displaySmall = SystemTypography.displaySmall.copy(
|
||||
fontFamily = fontFamily,
|
||||
),
|
||||
headlineLarge = SystemTypography.headlineLarge.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
headlineMedium = SystemTypography.headlineMedium.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
headlineSmall = SystemTypography.headlineSmall.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
titleLarge = SystemTypography.titleLarge.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
titleMedium = SystemTypography.titleMedium.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
titleSmall = SystemTypography.titleSmall.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
labelLarge = SystemTypography.labelLarge.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
bodyLarge = SystemTypography.bodyLarge.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
bodyMedium = SystemTypography.bodyMedium.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
bodySmall = SystemTypography.bodySmall.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
labelMedium = SystemTypography.labelMedium.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
labelSmall = SystemTypography.labelSmall.copy(
|
||||
fontFamily = fontFamily
|
||||
),
|
||||
)
|
||||
|
||||
private fun loadTypography(ctx: Context, type: FontType): Typography =
|
||||
when (type) {
|
||||
FontType.BasicFont -> basicTypography ?: createTypography(createFontFamily(ctx, type))
|
||||
.also { basicTypography = it }
|
||||
|
||||
FontType.ReadingFont -> readingTypography ?: createTypography(createFontFamily(ctx, type))
|
||||
.also { readingTypography = it }
|
||||
}
|
||||
}
|
||||
}
|
@ -47,7 +47,7 @@ fun SubscribeDialog(
|
||||
val groupsState = subscribeUiState.groups.collectAsState(initial = emptyList())
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
|
||||
it?.let { uri ->
|
||||
context.contentResolver.openInputStream(uri)?.let { inputStream ->
|
||||
context.contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||
subscribeViewModel.importFromInputStream(inputStream)
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ fun Metadata(
|
||||
text = dateString,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
style = MaterialTheme.typography.labelMedium.copy(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(context),
|
||||
),
|
||||
textAlign = titleAlign.toTextAlign(),
|
||||
)
|
||||
@ -64,7 +64,7 @@ fun Metadata(
|
||||
text = if (titleUpperCase.value) titleUpperCaseString else title,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
style = MaterialTheme.typography.headlineLarge.copy(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(context),
|
||||
fontWeight = if (titleBold.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
),
|
||||
textAlign = titleAlign.toTextAlign(),
|
||||
@ -79,7 +79,7 @@ fun Metadata(
|
||||
text = it,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
style = MaterialTheme.typography.labelMedium.copy(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(context),
|
||||
),
|
||||
textAlign = titleAlign.toTextAlign(),
|
||||
)
|
||||
@ -92,7 +92,7 @@ fun Metadata(
|
||||
text = feedName,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
style = MaterialTheme.typography.labelMedium.copy(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(context),
|
||||
),
|
||||
textAlign = titleAlign.toTextAlign(),
|
||||
)
|
||||
|
@ -2,6 +2,8 @@ package me.ash.reader.ui.page.settings.color
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
@ -25,11 +27,13 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import me.ash.reader.R
|
||||
import me.ash.reader.data.model.preference.*
|
||||
import me.ash.reader.ui.component.base.*
|
||||
import me.ash.reader.ui.ext.ExternalFonts
|
||||
import me.ash.reader.ui.page.common.RouteName
|
||||
import me.ash.reader.ui.page.settings.SettingItem
|
||||
import me.ash.reader.ui.svg.PALETTE
|
||||
@ -47,10 +51,19 @@ fun ColorAndStylePage(
|
||||
val darkThemeNot = !darkTheme
|
||||
val themeIndex = LocalThemeIndex.current
|
||||
val customPrimaryColor = LocalCustomPrimaryColor.current
|
||||
val fonts = LocalBasicFonts.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val wallpaperTonalPalettes = extractTonalPalettesFromUserWallpaper()
|
||||
var radioButtonSelected by remember { mutableStateOf(if (themeIndex > 4) 0 else 1) }
|
||||
var fontsDialogVisible by remember { mutableStateOf(false) }
|
||||
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||
uri?.let {
|
||||
ExternalFonts(context, it, ExternalFonts.FontType.BasicFont).copyToInternalStorage()
|
||||
BasicFontsPreference.External.put(context, scope)
|
||||
}
|
||||
}
|
||||
|
||||
RYScaffold(
|
||||
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
|
||||
@ -152,9 +165,8 @@ fun ColorAndStylePage(
|
||||
}
|
||||
SettingItem(
|
||||
title = stringResource(R.string.basic_fonts),
|
||||
desc = stringResource(R.string.system_default),
|
||||
enable = false,
|
||||
onClick = {},
|
||||
desc = fonts.toDesc(context),
|
||||
onClick = { fontsDialogVisible = true },
|
||||
) {}
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
}
|
||||
@ -195,6 +207,26 @@ fun ColorAndStylePage(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
RadioDialog(
|
||||
visible = fontsDialogVisible,
|
||||
title = stringResource(R.string.basic_fonts),
|
||||
options = BasicFontsPreference.values.map {
|
||||
RadioDialogOption(
|
||||
text = it.toDesc(context),
|
||||
style = TextStyle(fontFamily = it.asFontFamily(context)),
|
||||
selected = it == fonts,
|
||||
) {
|
||||
if (it.value == BasicFontsPreference.External.value) {
|
||||
launcher.launch("*/*")
|
||||
} else {
|
||||
it.put(context, scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
fontsDialogVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
@ -1,5 +1,7 @@
|
||||
package me.ash.reader.ui.page.settings.color.reading
|
||||
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
@ -27,6 +29,7 @@ import me.ash.reader.R
|
||||
import me.ash.reader.data.model.preference.*
|
||||
import me.ash.reader.ui.component.ReadingThemePrev
|
||||
import me.ash.reader.ui.component.base.*
|
||||
import me.ash.reader.ui.ext.ExternalFonts
|
||||
import me.ash.reader.ui.page.common.RouteName
|
||||
import me.ash.reader.ui.page.settings.SettingItem
|
||||
import me.ash.reader.ui.theme.palette.onLight
|
||||
@ -48,6 +51,13 @@ fun ReadingStylePage(
|
||||
var tonalElevationDialogVisible by remember { mutableStateOf(false) }
|
||||
var fontsDialogVisible by remember { mutableStateOf(false) }
|
||||
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||
uri?.let {
|
||||
ExternalFonts(context, it, ExternalFonts.FontType.ReadingFont).copyToInternalStorage()
|
||||
ReadingFontsPreference.External.put(context, scope)
|
||||
}
|
||||
}
|
||||
|
||||
RYScaffold(
|
||||
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
|
||||
navigationIcon = {
|
||||
@ -247,10 +257,14 @@ fun ReadingStylePage(
|
||||
options = ReadingFontsPreference.values.map {
|
||||
RadioDialogOption(
|
||||
text = it.toDesc(context),
|
||||
style = TextStyle(fontFamily = it.asFontFamily()),
|
||||
style = TextStyle(fontFamily = it.asFontFamily(context)),
|
||||
selected = it == fonts,
|
||||
) {
|
||||
it.put(context, scope)
|
||||
if (it.value == ReadingFontsPreference.External.value) {
|
||||
launcher.launch("*/*")
|
||||
} else {
|
||||
it.put(context, scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
|
@ -48,7 +48,7 @@ fun TitleAndTextPreview() {
|
||||
text = if (titleUpperCase.value) titleUpperCaseString else stringResource(id = R.string.title),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
style = MaterialTheme.typography.headlineLarge.copy(
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||
fontFamily = LocalReadingFonts.current.asFontFamily(context),
|
||||
fontWeight = if (titleBold.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||
),
|
||||
textAlign = titleAlign.toTextAlign(),
|
||||
|
@ -2,19 +2,15 @@ package me.ash.reader.ui.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import me.ash.reader.R
|
||||
|
||||
val AppTypography = Typography(
|
||||
val SystemTypography = Typography(
|
||||
displayLarge = TextStyle(
|
||||
fontWeight = FontWeight.W400,
|
||||
fontSize = 57.sp,
|
||||
lineHeight = 64.sp,
|
||||
letterSpacing = -0.25.sp,
|
||||
letterSpacing = (-0.25).sp,
|
||||
),
|
||||
displayMedium = TextStyle(
|
||||
fontWeight = FontWeight.W400,
|
@ -3,6 +3,8 @@ package me.ash.reader.ui.theme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import me.ash.reader.data.model.preference.LocalBasicFonts
|
||||
import me.ash.reader.data.model.preference.LocalThemeIndex
|
||||
import me.ash.reader.ui.theme.palette.LocalTonalPalettes
|
||||
import me.ash.reader.ui.theme.palette.TonalPalettes
|
||||
@ -20,26 +22,26 @@ fun AppTheme(
|
||||
val themeIndex = LocalThemeIndex.current
|
||||
|
||||
val tonalPalettes = wallpaperPalettes[
|
||||
if (themeIndex >= wallpaperPalettes.size) {
|
||||
when {
|
||||
wallpaperPalettes.size == 5 -> 0
|
||||
wallpaperPalettes.size > 5 -> 5
|
||||
else -> 0
|
||||
}
|
||||
} else {
|
||||
themeIndex
|
||||
if (themeIndex >= wallpaperPalettes.size) {
|
||||
when {
|
||||
wallpaperPalettes.size == 5 -> 0
|
||||
wallpaperPalettes.size > 5 -> 5
|
||||
else -> 0
|
||||
}
|
||||
} else {
|
||||
themeIndex
|
||||
}
|
||||
]
|
||||
|
||||
ProvideZcamViewingConditions {
|
||||
CompositionLocalProvider(
|
||||
LocalTonalPalettes provides tonalPalettes.apply { Preheating() },
|
||||
LocalTonalPalettes provides tonalPalettes.apply { Preparing() },
|
||||
) {
|
||||
MaterialTheme(
|
||||
colorScheme =
|
||||
if (useDarkTheme) dynamicDarkColorScheme()
|
||||
else dynamicLightColorScheme(),
|
||||
typography = AppTypography,
|
||||
typography = LocalBasicFonts.current.asTypography(LocalContext.current),
|
||||
shapes = Shapes,
|
||||
content = content,
|
||||
)
|
||||
|
@ -106,7 +106,7 @@ data class TonalPalettes(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Preheating() {
|
||||
fun Preparing() {
|
||||
tonalTokens.forEach { primary(it) }
|
||||
tonalTokens.forEach { secondary(it) }
|
||||
tonalTokens.forEach { tertiary(it) }
|
||||
|
@ -390,5 +390,5 @@
|
||||
<string name="username">Username</string>
|
||||
<string name="password">Password</string>
|
||||
<string name="connection">Connection</string>
|
||||
<string name="system_default">System Default</string>
|
||||
<string name="system_default">System</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user