Add reading page style settings (#132)
* Add reading page style settings * improved german language (#134) * Add Hindi translation Thanks augurer * Add auto hide toolbar and image maximize setting * Add tonal elevation setting in reading page * Add reading dark theme and previews * Add dynamic custom reading theme preview Co-authored-by: helloworldtest123 <36381315+helloworldtest123@users.noreply.github.com>
This commit is contained in:
parent
e32c0fbfd3
commit
f21a0c9fd8
|
@ -66,6 +66,14 @@ Nachfolgend sind die bisher erzielten Fortschritte und die Ziele aufgeführt, an
|
||||||
|
|
||||||
> Bei den oben genannten Funktionen handelt es sich nur um vorläufige Implementierungen, und es können noch unbekannte Probleme auftreten.
|
> Bei den oben genannten Funktionen handelt es sich nur um vorläufige Implementierungen, und es können noch unbekannte Probleme auftreten.
|
||||||
|
|
||||||
|
## Herunterladen
|
||||||
|
|
||||||
|
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on-de.png"
|
||||||
|
alt="Jetzt bei F-Droid"
|
||||||
|
height="80">](https://f-droid.org/packages/me.ash.reader/)
|
||||||
|
|
||||||
|
oder hole die APK aus dem [GitHub Releasebereich](https://github.com/Ashinch/ReadYou/releases).
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
> Wenn Sie eine Vorschau der Read You App wollen, können Sie die **Vorschau-Version** der APK-Datei in [Telegram] (https://t.me/ReadYouApp) herunterladen.
|
> Wenn Sie eine Vorschau der Read You App wollen, können Sie die **Vorschau-Version** der APK-Datei in [Telegram] (https://t.me/ReadYouApp) herunterladen.
|
||||||
|
|
|
@ -20,6 +20,8 @@ sealed class LanguagesPreference(val value: Int) : Preference() {
|
||||||
object Czech : LanguagesPreference(5)
|
object Czech : LanguagesPreference(5)
|
||||||
object Italian : LanguagesPreference(6)
|
object Italian : LanguagesPreference(6)
|
||||||
|
|
||||||
|
object Hindi : LanguagesPreference(7)
|
||||||
|
|
||||||
override fun put(context: Context, scope: CoroutineScope) {
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
context.dataStore.put(
|
context.dataStore.put(
|
||||||
|
@ -39,6 +41,7 @@ sealed class LanguagesPreference(val value: Int) : Preference() {
|
||||||
French -> context.getString(R.string.french)
|
French -> context.getString(R.string.french)
|
||||||
Czech -> context.getString(R.string.czech)
|
Czech -> context.getString(R.string.czech)
|
||||||
Italian -> context.getString(R.string.italian)
|
Italian -> context.getString(R.string.italian)
|
||||||
|
Hindi -> context.getString(R.string.hindi)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLocale(): Locale =
|
fun getLocale(): Locale =
|
||||||
|
@ -50,6 +53,7 @@ sealed class LanguagesPreference(val value: Int) : Preference() {
|
||||||
French -> Locale("fr", "FR")
|
French -> Locale("fr", "FR")
|
||||||
Czech -> Locale("cs", "CZ")
|
Czech -> Locale("cs", "CZ")
|
||||||
Italian -> Locale("it", "IT")
|
Italian -> Locale("it", "IT")
|
||||||
|
Hindi -> Locale("hi", "IN")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLocale(context: Context) {
|
fun setLocale(context: Context) {
|
||||||
|
@ -74,7 +78,7 @@ sealed class LanguagesPreference(val value: Int) : Preference() {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val default = UseDeviceLanguages
|
val default = UseDeviceLanguages
|
||||||
val values = listOf(UseDeviceLanguages, English, ChineseSimplified, German, French, Czech, Italian)
|
val values = listOf(UseDeviceLanguages, English, ChineseSimplified, German, French, Czech, Italian, Hindi)
|
||||||
|
|
||||||
fun fromPreferences(preferences: Preferences): LanguagesPreference =
|
fun fromPreferences(preferences: Preferences): LanguagesPreference =
|
||||||
when (preferences[DataStoreKeys.Languages.key]) {
|
when (preferences[DataStoreKeys.Languages.key]) {
|
||||||
|
@ -85,6 +89,7 @@ sealed class LanguagesPreference(val value: Int) : Preference() {
|
||||||
4 -> French
|
4 -> French
|
||||||
5 -> Czech
|
5 -> Czech
|
||||||
6 -> Italian
|
6 -> Italian
|
||||||
|
7 -> Hindi
|
||||||
else -> default
|
else -> default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +102,7 @@ sealed class LanguagesPreference(val value: Int) : Preference() {
|
||||||
4 -> French
|
4 -> French
|
||||||
5 -> Czech
|
5 -> Czech
|
||||||
6 -> Italian
|
6 -> Italian
|
||||||
|
7 -> Hindi
|
||||||
else -> default
|
else -> default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ sealed class Preference {
|
||||||
|
|
||||||
fun Preferences.toSettings(): Settings {
|
fun Preferences.toSettings(): Settings {
|
||||||
return Settings(
|
return Settings(
|
||||||
|
// Version
|
||||||
newVersionNumber = NewVersionNumberPreference.fromPreferences(this),
|
newVersionNumber = NewVersionNumberPreference.fromPreferences(this),
|
||||||
skipVersionNumber = SkipVersionNumberPreference.fromPreferences(this),
|
skipVersionNumber = SkipVersionNumberPreference.fromPreferences(this),
|
||||||
newVersionPublishDate = NewVersionPublishDatePreference.fromPreferences(this),
|
newVersionPublishDate = NewVersionPublishDatePreference.fromPreferences(this),
|
||||||
|
@ -18,11 +19,13 @@ fun Preferences.toSettings(): Settings {
|
||||||
newVersionSize = NewVersionSizePreference.fromPreferences(this),
|
newVersionSize = NewVersionSizePreference.fromPreferences(this),
|
||||||
newVersionDownloadUrl = NewVersionDownloadUrlPreference.fromPreferences(this),
|
newVersionDownloadUrl = NewVersionDownloadUrlPreference.fromPreferences(this),
|
||||||
|
|
||||||
|
// Theme
|
||||||
themeIndex = ThemeIndexPreference.fromPreferences(this),
|
themeIndex = ThemeIndexPreference.fromPreferences(this),
|
||||||
customPrimaryColor = CustomPrimaryColorPreference.fromPreferences(this),
|
customPrimaryColor = CustomPrimaryColorPreference.fromPreferences(this),
|
||||||
darkTheme = DarkThemePreference.fromPreferences(this),
|
darkTheme = DarkThemePreference.fromPreferences(this),
|
||||||
amoledDarkTheme = AmoledDarkThemePreference.fromPreferences(this),
|
amoledDarkTheme = AmoledDarkThemePreference.fromPreferences(this),
|
||||||
|
|
||||||
|
// Feeds page
|
||||||
feedsFilterBarStyle = FeedsFilterBarStylePreference.fromPreferences(this),
|
feedsFilterBarStyle = FeedsFilterBarStylePreference.fromPreferences(this),
|
||||||
feedsFilterBarFilled = FeedsFilterBarFilledPreference.fromPreferences(this),
|
feedsFilterBarFilled = FeedsFilterBarFilledPreference.fromPreferences(this),
|
||||||
feedsFilterBarPadding = FeedsFilterBarPaddingPreference.fromPreferences(this),
|
feedsFilterBarPadding = FeedsFilterBarPaddingPreference.fromPreferences(this),
|
||||||
|
@ -31,6 +34,7 @@ fun Preferences.toSettings(): Settings {
|
||||||
feedsGroupListExpand = FeedsGroupListExpandPreference.fromPreferences(this),
|
feedsGroupListExpand = FeedsGroupListExpandPreference.fromPreferences(this),
|
||||||
feedsGroupListTonalElevation = FeedsGroupListTonalElevationPreference.fromPreferences(this),
|
feedsGroupListTonalElevation = FeedsGroupListTonalElevationPreference.fromPreferences(this),
|
||||||
|
|
||||||
|
// Flow page
|
||||||
flowFilterBarStyle = FlowFilterBarStylePreference.fromPreferences(this),
|
flowFilterBarStyle = FlowFilterBarStylePreference.fromPreferences(this),
|
||||||
flowFilterBarFilled = FlowFilterBarFilledPreference.fromPreferences(this),
|
flowFilterBarFilled = FlowFilterBarFilledPreference.fromPreferences(this),
|
||||||
flowFilterBarPadding = FlowFilterBarPaddingPreference.fromPreferences(this),
|
flowFilterBarPadding = FlowFilterBarPaddingPreference.fromPreferences(this),
|
||||||
|
@ -46,9 +50,32 @@ fun Preferences.toSettings(): Settings {
|
||||||
),
|
),
|
||||||
flowArticleListTonalElevation = FlowArticleListTonalElevationPreference.fromPreferences(this),
|
flowArticleListTonalElevation = FlowArticleListTonalElevationPreference.fromPreferences(this),
|
||||||
|
|
||||||
|
// Reading page
|
||||||
|
readingTheme = ReadingThemePreference.fromPreferences(this),
|
||||||
|
readingDarkTheme = ReadingDarkThemePreference.fromPreferences(this),
|
||||||
|
readingPageTonalElevation = ReadingPageTonalElevationPreference.fromPreferences(this),
|
||||||
|
readingAutoHideToolbar = ReadingAutoHideToolbarPreference.fromPreferences(this),
|
||||||
|
readingTextFontSize = ReadingTextFontSizePreference.fromPreferences(this),
|
||||||
|
readingLetterSpacing = ReadingLetterSpacingPreference.fromPreferences(this),
|
||||||
|
readingTextHorizontalPadding = ReadingTextHorizontalPaddingPreference.fromPreferences(this),
|
||||||
|
readingTextAlign = ReadingTextAlignPreference.fromPreferences(this),
|
||||||
|
readingTextBold = ReadingTextBoldPreference.fromPreferences(this),
|
||||||
|
readingTitleAlign = ReadingTitleAlignPreference.fromPreferences(this),
|
||||||
|
readingSubheadAlign = ReadingSubheadAlignPreference.fromPreferences(this),
|
||||||
|
readingFonts = ReadingFontsPreference.fromPreferences(this),
|
||||||
|
readingTitleBold = ReadingTitleBoldPreference.fromPreferences(this),
|
||||||
|
readingSubheadBold = ReadingSubheadBoldPreference.fromPreferences(this),
|
||||||
|
readingTitleUpperCase = ReadingTitleUpperCasePreference.fromPreferences(this),
|
||||||
|
readingSubheadUpperCase = ReadingSubheadUpperCasePreference.fromPreferences(this),
|
||||||
|
readingImageHorizontalPadding = ReadingImageHorizontalPaddingPreference.fromPreferences(this),
|
||||||
|
readingImageRoundedCorners = ReadingImageRoundedCornersPreference.fromPreferences(this),
|
||||||
|
readingImageMaximize = ReadingImageMaximizePreference.fromPreferences(this),
|
||||||
|
|
||||||
|
// Interaction
|
||||||
initialPage = InitialPagePreference.fromPreferences(this),
|
initialPage = InitialPagePreference.fromPreferences(this),
|
||||||
initialFilter = InitialFilterPreference.fromPreferences(this),
|
initialFilter = InitialFilterPreference.fromPreferences(this),
|
||||||
|
|
||||||
|
// Languages
|
||||||
languages = LanguagesPreference.fromPreferences(this),
|
languages = LanguagesPreference.fromPreferences(this),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingAutoHideToolbarPreference(val value: Boolean) : Preference() {
|
||||||
|
object ON : ReadingAutoHideToolbarPreference(true)
|
||||||
|
object OFF : ReadingAutoHideToolbarPreference(false)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingAutoHideToolbar, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = ON
|
||||||
|
val values = listOf(ON, OFF)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingAutoHideToolbar.key]) {
|
||||||
|
true -> ON
|
||||||
|
false -> OFF
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun ReadingAutoHideToolbarPreference.not(): ReadingAutoHideToolbarPreference =
|
||||||
|
when (value) {
|
||||||
|
true -> ReadingAutoHideToolbarPreference.OFF
|
||||||
|
false -> ReadingAutoHideToolbarPreference.ON
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
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.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingDarkThemePreference(val value: Int) : Preference() {
|
||||||
|
object UseAppTheme : ReadingDarkThemePreference(0)
|
||||||
|
object ON : ReadingDarkThemePreference(1)
|
||||||
|
object OFF : ReadingDarkThemePreference(2)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingDarkTheme,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toDesc(context: Context): String =
|
||||||
|
when (this) {
|
||||||
|
UseAppTheme -> context.getString(R.string.use_app_theme)
|
||||||
|
ON -> context.getString(R.string.on)
|
||||||
|
OFF -> context.getString(R.string.off)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
fun isDarkTheme(): Boolean = when (this) {
|
||||||
|
UseAppTheme -> LocalDarkTheme.current.isDarkTheme()
|
||||||
|
ON -> true
|
||||||
|
OFF -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = UseAppTheme
|
||||||
|
val values = listOf(UseAppTheme, ON, OFF)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingDarkTheme.key]) {
|
||||||
|
0 -> UseAppTheme
|
||||||
|
1 -> ON
|
||||||
|
2 -> OFF
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
operator fun ReadingDarkThemePreference.not(): ReadingDarkThemePreference =
|
||||||
|
when (this) {
|
||||||
|
ReadingDarkThemePreference.UseAppTheme -> if (LocalDarkTheme.current.isDarkTheme()) {
|
||||||
|
ReadingDarkThemePreference.OFF
|
||||||
|
} else {
|
||||||
|
ReadingDarkThemePreference.ON
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadingDarkThemePreference.ON -> ReadingDarkThemePreference.OFF
|
||||||
|
ReadingDarkThemePreference.OFF -> ReadingDarkThemePreference.ON
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
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.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
import me.ash.reader.ui.theme.googleSansDisplay
|
||||||
|
import me.ash.reader.ui.theme.googleSansText
|
||||||
|
|
||||||
|
sealed class ReadingFontsPreference(val value: Int) : Preference() {
|
||||||
|
object GoogleSans : ReadingFontsPreference(0)
|
||||||
|
object Serif : ReadingFontsPreference(1)
|
||||||
|
object SansSerif : ReadingFontsPreference(2)
|
||||||
|
object Monospace : ReadingFontsPreference(3)
|
||||||
|
object Cursive : ReadingFontsPreference(4)
|
||||||
|
object External : ReadingFontsPreference(5)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingFonts, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toDesc(context: Context): String =
|
||||||
|
when (this) {
|
||||||
|
GoogleSans -> "Google Sans"
|
||||||
|
Serif -> "Serif"
|
||||||
|
SansSerif -> "Sans-Serif"
|
||||||
|
Monospace -> "Monospace"
|
||||||
|
Cursive -> "Cursive"
|
||||||
|
External -> context.getString(R.string.external_fonts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun asFontFamily(isDisplay: Boolean = false): FontFamily =
|
||||||
|
when (this) {
|
||||||
|
GoogleSans -> if (isDisplay) googleSansDisplay else googleSansText
|
||||||
|
Serif -> FontFamily.Serif
|
||||||
|
SansSerif -> FontFamily.SansSerif
|
||||||
|
Monospace -> FontFamily.Monospace
|
||||||
|
Cursive -> FontFamily.Cursive
|
||||||
|
External -> FontFamily.Default
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = GoogleSans
|
||||||
|
val values = listOf(GoogleSans, Serif, SansSerif, Monospace, Cursive, External)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences): ReadingFontsPreference =
|
||||||
|
when (preferences[DataStoreKeys.ReadingFonts.key]) {
|
||||||
|
0 -> GoogleSans
|
||||||
|
1 -> Serif
|
||||||
|
2 -> SansSerif
|
||||||
|
3 -> Monospace
|
||||||
|
4 -> Cursive
|
||||||
|
5 -> External
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
object ReadingImageHorizontalPaddingPreference {
|
||||||
|
|
||||||
|
const val default = 24
|
||||||
|
|
||||||
|
fun put(context: Context, scope: CoroutineScope, value: Int) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingImageHorizontalPadding, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
preferences[DataStoreKeys.ReadingImageHorizontalPadding.key] ?: default
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingImageMaximizePreference(val value: Boolean) : Preference() {
|
||||||
|
object ON : ReadingImageMaximizePreference(true)
|
||||||
|
object OFF : ReadingImageMaximizePreference(false)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingImageMaximize, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = ON
|
||||||
|
val values = listOf(ON, OFF)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingImageMaximize.key]) {
|
||||||
|
true -> ON
|
||||||
|
false -> OFF
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun ReadingImageMaximizePreference.not(): ReadingImageMaximizePreference =
|
||||||
|
when (value) {
|
||||||
|
true -> ReadingImageMaximizePreference.OFF
|
||||||
|
false -> ReadingImageMaximizePreference.ON
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
object ReadingImageRoundedCornersPreference {
|
||||||
|
|
||||||
|
const val default = 32
|
||||||
|
|
||||||
|
fun put(context: Context, scope: CoroutineScope, value: Int) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingImageRoundedCorners, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
preferences[DataStoreKeys.ReadingImageRoundedCorners.key] ?: default
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
object ReadingLetterSpacingPreference {
|
||||||
|
|
||||||
|
const val default = 0.5
|
||||||
|
|
||||||
|
fun put(context: Context, scope: CoroutineScope, value: Double) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingLetterSpacing, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
preferences[DataStoreKeys.ReadingLetterSpacing.key] ?: default
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.data.constant.ElevationTokens
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingPageTonalElevationPreference(val value: Int) : Preference() {
|
||||||
|
object Level0 : ReadingPageTonalElevationPreference(ElevationTokens.Level0)
|
||||||
|
object Level1 : ReadingPageTonalElevationPreference(ElevationTokens.Level1)
|
||||||
|
object Level2 : ReadingPageTonalElevationPreference(ElevationTokens.Level2)
|
||||||
|
object Level3 : ReadingPageTonalElevationPreference(ElevationTokens.Level3)
|
||||||
|
object Level4 : ReadingPageTonalElevationPreference(ElevationTokens.Level4)
|
||||||
|
object Level5 : ReadingPageTonalElevationPreference(ElevationTokens.Level5)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingPageTonalElevation, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toDesc(context: Context): String =
|
||||||
|
when (this) {
|
||||||
|
Level0 -> "Level 0 (${ElevationTokens.Level0}dp)"
|
||||||
|
Level1 -> "Level 1 (${ElevationTokens.Level1}dp)"
|
||||||
|
Level2 -> "Level 2 (${ElevationTokens.Level2}dp)"
|
||||||
|
Level3 -> "Level 3 (${ElevationTokens.Level3}dp)"
|
||||||
|
Level4 -> "Level 4 (${ElevationTokens.Level4}dp)"
|
||||||
|
Level5 -> "Level 5 (${ElevationTokens.Level5}dp)"
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = Level0
|
||||||
|
val values = listOf(Level0, Level1, Level2, Level3, Level4, Level5)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingPageTonalElevation.key]) {
|
||||||
|
ElevationTokens.Level0 -> Level0
|
||||||
|
ElevationTokens.Level1 -> Level1
|
||||||
|
ElevationTokens.Level2 -> Level2
|
||||||
|
ElevationTokens.Level3 -> Level3
|
||||||
|
ElevationTokens.Level4 -> Level4
|
||||||
|
ElevationTokens.Level5 -> Level5
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
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.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingSubheadAlignPreference(val value: Int) : Preference() {
|
||||||
|
object Left : ReadingSubheadAlignPreference(0)
|
||||||
|
object Right : ReadingSubheadAlignPreference(1)
|
||||||
|
object Center : ReadingSubheadAlignPreference(2)
|
||||||
|
object Justify : ReadingSubheadAlignPreference(3)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingSubheadAlign,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toDesc(context: Context): String =
|
||||||
|
when (this) {
|
||||||
|
Left -> context.getString(R.string.align_left)
|
||||||
|
Right -> context.getString(R.string.align_right)
|
||||||
|
Center -> context.getString(R.string.center_text)
|
||||||
|
Justify -> context.getString(R.string.justify)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toTextAlign(): TextAlign =
|
||||||
|
when (this) {
|
||||||
|
Left -> TextAlign.Start
|
||||||
|
Right -> TextAlign.End
|
||||||
|
Center -> TextAlign.Center
|
||||||
|
Justify -> TextAlign.Justify
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = Left
|
||||||
|
val values = listOf(Left, Right, Center, Justify)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences): ReadingSubheadAlignPreference =
|
||||||
|
when (preferences[DataStoreKeys.ReadingSubheadAlign.key]) {
|
||||||
|
0 -> Left
|
||||||
|
1 -> Right
|
||||||
|
2 -> Center
|
||||||
|
3 -> Justify
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingSubheadBoldPreference(val value: Boolean) : Preference() {
|
||||||
|
object ON : ReadingSubheadBoldPreference(true)
|
||||||
|
object OFF : ReadingSubheadBoldPreference(false)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingSubheadBold,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = OFF
|
||||||
|
val values = listOf(ON, OFF)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingSubheadBold.key]) {
|
||||||
|
true -> ON
|
||||||
|
false -> OFF
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun ReadingSubheadBoldPreference.not(): ReadingSubheadBoldPreference =
|
||||||
|
when (value) {
|
||||||
|
true -> ReadingSubheadBoldPreference.OFF
|
||||||
|
false -> ReadingSubheadBoldPreference.ON
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingSubheadUpperCasePreference(val value: Boolean) : Preference() {
|
||||||
|
object ON : ReadingSubheadUpperCasePreference(true)
|
||||||
|
object OFF : ReadingSubheadUpperCasePreference(false)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingSubheadUpperCase,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = OFF
|
||||||
|
val values = listOf(ON, OFF)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingSubheadUpperCase.key]) {
|
||||||
|
true -> ON
|
||||||
|
false -> OFF
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun ReadingSubheadUpperCasePreference.not(): ReadingSubheadUpperCasePreference =
|
||||||
|
when (value) {
|
||||||
|
true -> ReadingSubheadUpperCasePreference.OFF
|
||||||
|
false -> ReadingSubheadUpperCasePreference.ON
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
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.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingTextAlignPreference(val value: Int) : Preference() {
|
||||||
|
object Left : ReadingTextAlignPreference(0)
|
||||||
|
object Right : ReadingTextAlignPreference(1)
|
||||||
|
object Center : ReadingTextAlignPreference(2)
|
||||||
|
object Justify : ReadingTextAlignPreference(3)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingTextAlign,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toDesc(context: Context): String =
|
||||||
|
when (this) {
|
||||||
|
Left -> context.getString(R.string.align_left)
|
||||||
|
Right -> context.getString(R.string.align_right)
|
||||||
|
Center -> context.getString(R.string.center_text)
|
||||||
|
Justify -> context.getString(R.string.justify)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toTextAlign(): TextAlign =
|
||||||
|
when (this) {
|
||||||
|
Left -> TextAlign.Start
|
||||||
|
Right -> TextAlign.End
|
||||||
|
Center -> TextAlign.Center
|
||||||
|
Justify -> TextAlign.Justify
|
||||||
|
}
|
||||||
|
fun toAlignment(): Alignment.Horizontal =
|
||||||
|
when (this) {
|
||||||
|
Left -> Alignment.Start
|
||||||
|
Right -> Alignment.End
|
||||||
|
Center -> Alignment.CenterHorizontally
|
||||||
|
Justify -> Alignment.Start
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = Left
|
||||||
|
val values = listOf(Left, Right, Center, Justify)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences): ReadingTextAlignPreference =
|
||||||
|
when (preferences[DataStoreKeys.ReadingTextAlign.key]) {
|
||||||
|
0 -> Left
|
||||||
|
1 -> Right
|
||||||
|
2 -> Center
|
||||||
|
3 -> Justify
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingTextBoldPreference(val value: Boolean) : Preference() {
|
||||||
|
object ON : ReadingTextBoldPreference(true)
|
||||||
|
object OFF : ReadingTextBoldPreference(false)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingTextBold,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = OFF
|
||||||
|
val values = listOf(ON, OFF)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingTextBold.key]) {
|
||||||
|
true -> ON
|
||||||
|
false -> OFF
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun ReadingTextBoldPreference.not(): ReadingTextBoldPreference =
|
||||||
|
when (value) {
|
||||||
|
true -> ReadingTextBoldPreference.OFF
|
||||||
|
false -> ReadingTextBoldPreference.ON
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
object ReadingTextFontSizePreference {
|
||||||
|
|
||||||
|
const val default = 17
|
||||||
|
|
||||||
|
fun put(context: Context, scope: CoroutineScope, value: Int) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingTextFontSize, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
preferences[DataStoreKeys.ReadingTextFontSize.key] ?: default
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
object ReadingTextHorizontalPaddingPreference {
|
||||||
|
|
||||||
|
const val default = 24
|
||||||
|
|
||||||
|
fun put(context: Context, scope: CoroutineScope, value: Int) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingTextHorizontalPadding, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
preferences[DataStoreKeys.ReadingTextHorizontalPadding.key] ?: default
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
sealed class ReadingThemePreference(val value: Int) : Preference() {
|
||||||
|
|
||||||
|
object MaterialYou : ReadingThemePreference(0)
|
||||||
|
object Reeder : ReadingThemePreference(1)
|
||||||
|
object Paper : ReadingThemePreference(2)
|
||||||
|
object Custom : ReadingThemePreference(3)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.ReadingTheme, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toDesc(context: Context): String =
|
||||||
|
when (this) {
|
||||||
|
MaterialYou -> "Material You"
|
||||||
|
Reeder -> "Reeder"
|
||||||
|
Paper -> "Paper"
|
||||||
|
Custom -> "Custom"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyTheme(context: Context, scope: CoroutineScope) {
|
||||||
|
when (this) {
|
||||||
|
MaterialYou -> {
|
||||||
|
ReadingTitleBoldPreference.default.put(context, scope)
|
||||||
|
ReadingTitleUpperCasePreference.default.put(context, scope)
|
||||||
|
ReadingTitleAlignPreference.default.put(context, scope)
|
||||||
|
ReadingSubheadBoldPreference.default.put(context, scope)
|
||||||
|
ReadingSubheadUpperCasePreference.default.put(context, scope)
|
||||||
|
ReadingSubheadAlignPreference.default.put(context, scope)
|
||||||
|
ReadingTextBoldPreference.default.put(context, scope)
|
||||||
|
ReadingTextHorizontalPaddingPreference.put(context, scope,
|
||||||
|
ReadingTextHorizontalPaddingPreference.default)
|
||||||
|
ReadingTextAlignPreference.default.put(context, scope)
|
||||||
|
ReadingLetterSpacingPreference.put(context, scope, ReadingLetterSpacingPreference.default)
|
||||||
|
ReadingTextFontSizePreference.put(context, scope, ReadingTextFontSizePreference.default)
|
||||||
|
ReadingImageRoundedCornersPreference.put(context, scope, ReadingImageRoundedCornersPreference.default)
|
||||||
|
ReadingImageHorizontalPaddingPreference.put(context, scope,
|
||||||
|
ReadingImageHorizontalPaddingPreference.default)
|
||||||
|
ReadingImageMaximizePreference.default.put(context, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
Reeder -> {
|
||||||
|
ReadingTitleBoldPreference.ON.put(context, scope)
|
||||||
|
ReadingTitleUpperCasePreference.default.put(context, scope)
|
||||||
|
ReadingTitleAlignPreference.default.put(context, scope)
|
||||||
|
ReadingSubheadBoldPreference.ON.put(context, scope)
|
||||||
|
ReadingSubheadUpperCasePreference.default.put(context, scope)
|
||||||
|
ReadingSubheadAlignPreference.default.put(context, scope)
|
||||||
|
ReadingTextBoldPreference.default.put(context, scope)
|
||||||
|
ReadingTextHorizontalPaddingPreference.put(context, scope,
|
||||||
|
ReadingTextHorizontalPaddingPreference.default)
|
||||||
|
ReadingTextAlignPreference.default.put(context, scope)
|
||||||
|
ReadingLetterSpacingPreference.put(context, scope, ReadingLetterSpacingPreference.default)
|
||||||
|
ReadingTextFontSizePreference.put(context, scope, 18)
|
||||||
|
ReadingImageRoundedCornersPreference.put(context, scope, 0)
|
||||||
|
ReadingImageHorizontalPaddingPreference.put(context, scope, 0)
|
||||||
|
ReadingImageMaximizePreference.default.put(context, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
Paper -> {
|
||||||
|
ReadingTitleBoldPreference.ON.put(context, scope)
|
||||||
|
ReadingTitleUpperCasePreference.ON.put(context, scope)
|
||||||
|
ReadingTitleAlignPreference.Center.put(context, scope)
|
||||||
|
ReadingSubheadBoldPreference.ON.put(context, scope)
|
||||||
|
ReadingSubheadUpperCasePreference.ON.put(context, scope)
|
||||||
|
ReadingSubheadAlignPreference.Center.put(context, scope)
|
||||||
|
ReadingTextBoldPreference.default.put(context, scope)
|
||||||
|
ReadingTextHorizontalPaddingPreference.put(context, scope,
|
||||||
|
ReadingTextHorizontalPaddingPreference.default)
|
||||||
|
ReadingTextAlignPreference.Center.put(context, scope)
|
||||||
|
ReadingLetterSpacingPreference.put(context, scope, ReadingLetterSpacingPreference.default)
|
||||||
|
ReadingTextFontSizePreference.put(context, scope, 20)
|
||||||
|
ReadingImageRoundedCornersPreference.put(context, scope, 0)
|
||||||
|
ReadingImageHorizontalPaddingPreference.put(context, scope,
|
||||||
|
ReadingImageHorizontalPaddingPreference.default)
|
||||||
|
ReadingImageMaximizePreference.default.put(context, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
Custom -> {
|
||||||
|
ReadingTitleBoldPreference.default.put(context, scope)
|
||||||
|
ReadingTitleUpperCasePreference.default.put(context, scope)
|
||||||
|
ReadingTitleAlignPreference.default.put(context, scope)
|
||||||
|
ReadingSubheadBoldPreference.default.put(context, scope)
|
||||||
|
ReadingSubheadUpperCasePreference.default.put(context, scope)
|
||||||
|
ReadingSubheadAlignPreference.default.put(context, scope)
|
||||||
|
ReadingTextBoldPreference.default.put(context, scope)
|
||||||
|
ReadingTextHorizontalPaddingPreference.put(context, scope,
|
||||||
|
ReadingTextHorizontalPaddingPreference.default)
|
||||||
|
ReadingTextAlignPreference.default.put(context, scope)
|
||||||
|
ReadingLetterSpacingPreference.put(context, scope, ReadingLetterSpacingPreference.default)
|
||||||
|
ReadingTextFontSizePreference.put(context, scope, ReadingTextFontSizePreference.default)
|
||||||
|
ReadingImageRoundedCornersPreference.put(context, scope, ReadingImageRoundedCornersPreference.default)
|
||||||
|
ReadingImageHorizontalPaddingPreference.put(context, scope,
|
||||||
|
ReadingImageHorizontalPaddingPreference.default)
|
||||||
|
ReadingImageMaximizePreference.default.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = MaterialYou
|
||||||
|
val values = listOf(MaterialYou, Reeder, Paper, Custom)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences): ReadingThemePreference =
|
||||||
|
when (preferences[DataStoreKeys.ReadingTheme.key]) {
|
||||||
|
0 -> MaterialYou
|
||||||
|
1 -> Reeder
|
||||||
|
2 -> Paper
|
||||||
|
3 -> Custom
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
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.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingTitleAlignPreference(val value: Int) : Preference() {
|
||||||
|
object Left : ReadingTitleAlignPreference(0)
|
||||||
|
object Right : ReadingTitleAlignPreference(1)
|
||||||
|
object Center : ReadingTitleAlignPreference(2)
|
||||||
|
object Justify : ReadingTitleAlignPreference(3)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingTitleAlign,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
fun toDesc(context: Context): String =
|
||||||
|
when (this) {
|
||||||
|
Left -> context.getString(R.string.align_left)
|
||||||
|
Right -> context.getString(R.string.align_right)
|
||||||
|
Center -> context.getString(R.string.center_text)
|
||||||
|
Justify -> context.getString(R.string.justify)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
fun toTextAlign(): TextAlign =
|
||||||
|
when (this) {
|
||||||
|
Left -> TextAlign.Start
|
||||||
|
Right -> TextAlign.End
|
||||||
|
Center -> TextAlign.Center
|
||||||
|
Justify -> TextAlign.Justify
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = Left
|
||||||
|
val values = listOf(Left, Right, Center, Justify)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences): ReadingTitleAlignPreference =
|
||||||
|
when (preferences[DataStoreKeys.ReadingTitleAlign.key]) {
|
||||||
|
0 -> Left
|
||||||
|
1 -> Right
|
||||||
|
2 -> Center
|
||||||
|
3 -> Justify
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingTitleBoldPreference(val value: Boolean) : Preference() {
|
||||||
|
object ON : ReadingTitleBoldPreference(true)
|
||||||
|
object OFF : ReadingTitleBoldPreference(false)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingTitleBold,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = OFF
|
||||||
|
val values = listOf(ON, OFF)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingTitleBold.key]) {
|
||||||
|
true -> ON
|
||||||
|
false -> OFF
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun ReadingTitleBoldPreference.not(): ReadingTitleBoldPreference =
|
||||||
|
when (value) {
|
||||||
|
true -> ReadingTitleBoldPreference.OFF
|
||||||
|
false -> ReadingTitleBoldPreference.ON
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package me.ash.reader.data.model.preference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
|
sealed class ReadingTitleUpperCasePreference(val value: Boolean) : Preference() {
|
||||||
|
object ON : ReadingTitleUpperCasePreference(true)
|
||||||
|
object OFF : ReadingTitleUpperCasePreference(false)
|
||||||
|
|
||||||
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.ReadingTitleUpperCase,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val default = OFF
|
||||||
|
val values = listOf(ON, OFF)
|
||||||
|
|
||||||
|
fun fromPreferences(preferences: Preferences) =
|
||||||
|
when (preferences[DataStoreKeys.ReadingTitleUpperCase.key]) {
|
||||||
|
true -> ON
|
||||||
|
false -> OFF
|
||||||
|
else -> default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun ReadingTitleUpperCasePreference.not(): ReadingTitleUpperCasePreference =
|
||||||
|
when (value) {
|
||||||
|
true -> ReadingTitleUpperCasePreference.OFF
|
||||||
|
false -> ReadingTitleUpperCasePreference.ON
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import me.ash.reader.ui.ext.collectAsStateValue
|
||||||
import me.ash.reader.ui.ext.dataStore
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
|
||||||
data class Settings(
|
data class Settings(
|
||||||
|
// Version
|
||||||
val newVersionNumber: Version = NewVersionNumberPreference.default,
|
val newVersionNumber: Version = NewVersionNumberPreference.default,
|
||||||
val skipVersionNumber: Version = SkipVersionNumberPreference.default,
|
val skipVersionNumber: Version = SkipVersionNumberPreference.default,
|
||||||
val newVersionPublishDate: String = NewVersionPublishDatePreference.default,
|
val newVersionPublishDate: String = NewVersionPublishDatePreference.default,
|
||||||
|
@ -19,11 +20,13 @@ data class Settings(
|
||||||
val newVersionSize: String = NewVersionSizePreference.default,
|
val newVersionSize: String = NewVersionSizePreference.default,
|
||||||
val newVersionDownloadUrl: String = NewVersionDownloadUrlPreference.default,
|
val newVersionDownloadUrl: String = NewVersionDownloadUrlPreference.default,
|
||||||
|
|
||||||
|
// Theme
|
||||||
val themeIndex: Int = ThemeIndexPreference.default,
|
val themeIndex: Int = ThemeIndexPreference.default,
|
||||||
val customPrimaryColor: String = CustomPrimaryColorPreference.default,
|
val customPrimaryColor: String = CustomPrimaryColorPreference.default,
|
||||||
val darkTheme: DarkThemePreference = DarkThemePreference.default,
|
val darkTheme: DarkThemePreference = DarkThemePreference.default,
|
||||||
val amoledDarkTheme: AmoledDarkThemePreference = AmoledDarkThemePreference.default,
|
val amoledDarkTheme: AmoledDarkThemePreference = AmoledDarkThemePreference.default,
|
||||||
|
|
||||||
|
// Feeds page
|
||||||
val feedsFilterBarStyle: FeedsFilterBarStylePreference = FeedsFilterBarStylePreference.default,
|
val feedsFilterBarStyle: FeedsFilterBarStylePreference = FeedsFilterBarStylePreference.default,
|
||||||
val feedsFilterBarFilled: FeedsFilterBarFilledPreference = FeedsFilterBarFilledPreference.default,
|
val feedsFilterBarFilled: FeedsFilterBarFilledPreference = FeedsFilterBarFilledPreference.default,
|
||||||
val feedsFilterBarPadding: Int = FeedsFilterBarPaddingPreference.default,
|
val feedsFilterBarPadding: Int = FeedsFilterBarPaddingPreference.default,
|
||||||
|
@ -32,6 +35,7 @@ data class Settings(
|
||||||
val feedsGroupListExpand: FeedsGroupListExpandPreference = FeedsGroupListExpandPreference.default,
|
val feedsGroupListExpand: FeedsGroupListExpandPreference = FeedsGroupListExpandPreference.default,
|
||||||
val feedsGroupListTonalElevation: FeedsGroupListTonalElevationPreference = FeedsGroupListTonalElevationPreference.default,
|
val feedsGroupListTonalElevation: FeedsGroupListTonalElevationPreference = FeedsGroupListTonalElevationPreference.default,
|
||||||
|
|
||||||
|
// Flow page
|
||||||
val flowFilterBarStyle: FlowFilterBarStylePreference = FlowFilterBarStylePreference.default,
|
val flowFilterBarStyle: FlowFilterBarStylePreference = FlowFilterBarStylePreference.default,
|
||||||
val flowFilterBarFilled: FlowFilterBarFilledPreference = FlowFilterBarFilledPreference.default,
|
val flowFilterBarFilled: FlowFilterBarFilledPreference = FlowFilterBarFilledPreference.default,
|
||||||
val flowFilterBarPadding: Int = FlowFilterBarPaddingPreference.default,
|
val flowFilterBarPadding: Int = FlowFilterBarPaddingPreference.default,
|
||||||
|
@ -45,67 +49,36 @@ data class Settings(
|
||||||
val flowArticleListDateStickyHeader: FlowArticleListDateStickyHeaderPreference = FlowArticleListDateStickyHeaderPreference.default,
|
val flowArticleListDateStickyHeader: FlowArticleListDateStickyHeaderPreference = FlowArticleListDateStickyHeaderPreference.default,
|
||||||
val flowArticleListTonalElevation: FlowArticleListTonalElevationPreference = FlowArticleListTonalElevationPreference.default,
|
val flowArticleListTonalElevation: FlowArticleListTonalElevationPreference = FlowArticleListTonalElevationPreference.default,
|
||||||
|
|
||||||
|
// Reading page
|
||||||
|
val readingTheme: ReadingThemePreference = ReadingThemePreference.default,
|
||||||
|
val readingDarkTheme: ReadingDarkThemePreference = ReadingDarkThemePreference.default,
|
||||||
|
val readingPageTonalElevation: ReadingPageTonalElevationPreference = ReadingPageTonalElevationPreference.default,
|
||||||
|
val readingAutoHideToolbar: ReadingAutoHideToolbarPreference = ReadingAutoHideToolbarPreference.default,
|
||||||
|
val readingTextFontSize: Int = ReadingTextFontSizePreference.default,
|
||||||
|
val readingLetterSpacing: Double = ReadingLetterSpacingPreference.default,
|
||||||
|
val readingTextHorizontalPadding: Int = ReadingTextHorizontalPaddingPreference.default,
|
||||||
|
val readingTextAlign: ReadingTextAlignPreference = ReadingTextAlignPreference.default,
|
||||||
|
val readingTextBold: ReadingTextBoldPreference = ReadingTextBoldPreference.default,
|
||||||
|
val readingTitleAlign: ReadingTitleAlignPreference = ReadingTitleAlignPreference.default,
|
||||||
|
val readingSubheadAlign: ReadingSubheadAlignPreference = ReadingSubheadAlignPreference.default,
|
||||||
|
val readingFonts: ReadingFontsPreference = ReadingFontsPreference.default,
|
||||||
|
val readingTitleBold: ReadingTitleBoldPreference = ReadingTitleBoldPreference.default,
|
||||||
|
val readingSubheadBold: ReadingSubheadBoldPreference = ReadingSubheadBoldPreference.default,
|
||||||
|
val readingTitleUpperCase: ReadingTitleUpperCasePreference = ReadingTitleUpperCasePreference.default,
|
||||||
|
val readingSubheadUpperCase: ReadingSubheadUpperCasePreference = ReadingSubheadUpperCasePreference.default,
|
||||||
|
val readingImageHorizontalPadding: Int = ReadingImageHorizontalPaddingPreference.default,
|
||||||
|
val readingImageRoundedCorners: Int = ReadingImageRoundedCornersPreference.default,
|
||||||
|
val readingImageMaximize: ReadingImageMaximizePreference = ReadingImageMaximizePreference.default,
|
||||||
|
|
||||||
|
// Interaction
|
||||||
val initialPage: InitialPagePreference = InitialPagePreference.default,
|
val initialPage: InitialPagePreference = InitialPagePreference.default,
|
||||||
val initialFilter: InitialFilterPreference = InitialFilterPreference.default,
|
val initialFilter: InitialFilterPreference = InitialFilterPreference.default,
|
||||||
|
|
||||||
|
// Languages
|
||||||
val languages: LanguagesPreference = LanguagesPreference.default,
|
val languages: LanguagesPreference = LanguagesPreference.default,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
// Version
|
||||||
fun SettingsProvider(
|
|
||||||
content: @Composable () -> Unit,
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
val settings = remember {
|
|
||||||
context.dataStore.data.map {
|
|
||||||
Log.i("RLog", "AppTheme: ${it}")
|
|
||||||
it.toSettings()
|
|
||||||
}
|
|
||||||
}.collectAsStateValue(initial = Settings())
|
|
||||||
|
|
||||||
CompositionLocalProvider(
|
|
||||||
LocalNewVersionNumber provides settings.newVersionNumber,
|
|
||||||
LocalSkipVersionNumber provides settings.skipVersionNumber,
|
|
||||||
LocalNewVersionPublishDate provides settings.newVersionPublishDate,
|
|
||||||
LocalNewVersionLog provides settings.newVersionLog,
|
|
||||||
LocalNewVersionSize provides settings.newVersionSize,
|
|
||||||
LocalNewVersionDownloadUrl provides settings.newVersionDownloadUrl,
|
|
||||||
|
|
||||||
LocalThemeIndex provides settings.themeIndex,
|
|
||||||
LocalCustomPrimaryColor provides settings.customPrimaryColor,
|
|
||||||
LocalDarkTheme provides settings.darkTheme,
|
|
||||||
LocalAmoledDarkTheme provides settings.amoledDarkTheme,
|
|
||||||
|
|
||||||
LocalFeedsTopBarTonalElevation provides settings.feedsTopBarTonalElevation,
|
|
||||||
LocalFeedsGroupListExpand provides settings.feedsGroupListExpand,
|
|
||||||
LocalFeedsGroupListTonalElevation provides settings.feedsGroupListTonalElevation,
|
|
||||||
LocalFeedsFilterBarStyle provides settings.feedsFilterBarStyle,
|
|
||||||
LocalFeedsFilterBarFilled provides settings.feedsFilterBarFilled,
|
|
||||||
LocalFeedsFilterBarPadding provides settings.feedsFilterBarPadding,
|
|
||||||
LocalFeedsFilterBarTonalElevation provides settings.feedsFilterBarTonalElevation,
|
|
||||||
|
|
||||||
LocalFlowTopBarTonalElevation provides settings.flowTopBarTonalElevation,
|
|
||||||
LocalFlowArticleListFeedIcon provides settings.flowArticleListFeedIcon,
|
|
||||||
LocalFlowArticleListFeedName provides settings.flowArticleListFeedName,
|
|
||||||
LocalFlowArticleListImage provides settings.flowArticleListImage,
|
|
||||||
LocalFlowArticleListDesc provides settings.flowArticleListDesc,
|
|
||||||
LocalFlowArticleListTime provides settings.flowArticleListTime,
|
|
||||||
LocalFlowArticleListDateStickyHeader provides settings.flowArticleListDateStickyHeader,
|
|
||||||
LocalFlowArticleListTonalElevation provides settings.flowArticleListTonalElevation,
|
|
||||||
LocalFlowFilterBarStyle provides settings.flowFilterBarStyle,
|
|
||||||
LocalFlowFilterBarFilled provides settings.flowFilterBarFilled,
|
|
||||||
LocalFlowFilterBarPadding provides settings.flowFilterBarPadding,
|
|
||||||
LocalFlowFilterBarTonalElevation provides settings.flowFilterBarTonalElevation,
|
|
||||||
|
|
||||||
LocalInitialPage provides settings.initialPage,
|
|
||||||
LocalInitialFilter provides settings.initialFilter,
|
|
||||||
|
|
||||||
LocalLanguages provides settings.languages,
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val LocalNewVersionNumber = compositionLocalOf { NewVersionNumberPreference.default }
|
val LocalNewVersionNumber = compositionLocalOf { NewVersionNumberPreference.default }
|
||||||
val LocalSkipVersionNumber = compositionLocalOf { SkipVersionNumberPreference.default }
|
val LocalSkipVersionNumber = compositionLocalOf { SkipVersionNumberPreference.default }
|
||||||
val LocalNewVersionPublishDate = compositionLocalOf { NewVersionPublishDatePreference.default }
|
val LocalNewVersionPublishDate = compositionLocalOf { NewVersionPublishDatePreference.default }
|
||||||
|
@ -113,6 +86,7 @@ val LocalNewVersionLog = compositionLocalOf { NewVersionLogPreference.default }
|
||||||
val LocalNewVersionSize = compositionLocalOf { NewVersionSizePreference.default }
|
val LocalNewVersionSize = compositionLocalOf { NewVersionSizePreference.default }
|
||||||
val LocalNewVersionDownloadUrl = compositionLocalOf { NewVersionDownloadUrlPreference.default }
|
val LocalNewVersionDownloadUrl = compositionLocalOf { NewVersionDownloadUrlPreference.default }
|
||||||
|
|
||||||
|
// Theme
|
||||||
val LocalThemeIndex =
|
val LocalThemeIndex =
|
||||||
compositionLocalOf { ThemeIndexPreference.default }
|
compositionLocalOf { ThemeIndexPreference.default }
|
||||||
val LocalCustomPrimaryColor =
|
val LocalCustomPrimaryColor =
|
||||||
|
@ -122,6 +96,7 @@ val LocalDarkTheme =
|
||||||
val LocalAmoledDarkTheme =
|
val LocalAmoledDarkTheme =
|
||||||
compositionLocalOf<AmoledDarkThemePreference> { AmoledDarkThemePreference.default }
|
compositionLocalOf<AmoledDarkThemePreference> { AmoledDarkThemePreference.default }
|
||||||
|
|
||||||
|
// Feeds page
|
||||||
val LocalFeedsFilterBarStyle =
|
val LocalFeedsFilterBarStyle =
|
||||||
compositionLocalOf<FeedsFilterBarStylePreference> { FeedsFilterBarStylePreference.default }
|
compositionLocalOf<FeedsFilterBarStylePreference> { FeedsFilterBarStylePreference.default }
|
||||||
val LocalFeedsFilterBarFilled =
|
val LocalFeedsFilterBarFilled =
|
||||||
|
@ -137,6 +112,7 @@ val LocalFeedsGroupListExpand =
|
||||||
val LocalFeedsGroupListTonalElevation =
|
val LocalFeedsGroupListTonalElevation =
|
||||||
compositionLocalOf<FeedsGroupListTonalElevationPreference> { FeedsGroupListTonalElevationPreference.default }
|
compositionLocalOf<FeedsGroupListTonalElevationPreference> { FeedsGroupListTonalElevationPreference.default }
|
||||||
|
|
||||||
|
// Flow page
|
||||||
val LocalFlowFilterBarStyle =
|
val LocalFlowFilterBarStyle =
|
||||||
compositionLocalOf<FlowFilterBarStylePreference> { FlowFilterBarStylePreference.default }
|
compositionLocalOf<FlowFilterBarStylePreference> { FlowFilterBarStylePreference.default }
|
||||||
val LocalFlowFilterBarFilled =
|
val LocalFlowFilterBarFilled =
|
||||||
|
@ -162,9 +138,119 @@ val LocalFlowArticleListDateStickyHeader =
|
||||||
val LocalFlowArticleListTonalElevation =
|
val LocalFlowArticleListTonalElevation =
|
||||||
compositionLocalOf<FlowArticleListTonalElevationPreference> { FlowArticleListTonalElevationPreference.default }
|
compositionLocalOf<FlowArticleListTonalElevationPreference> { FlowArticleListTonalElevationPreference.default }
|
||||||
|
|
||||||
|
// 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 LocalReadingTextFontSize = compositionLocalOf { ReadingTextFontSizePreference.default }
|
||||||
|
val LocalReadingLetterSpacing = compositionLocalOf { ReadingLetterSpacingPreference.default }
|
||||||
|
val LocalReadingTextHorizontalPadding = compositionLocalOf { ReadingTextHorizontalPaddingPreference.default }
|
||||||
|
val LocalReadingTextAlign = compositionLocalOf<ReadingTextAlignPreference> { ReadingTextAlignPreference.default }
|
||||||
|
val LocalReadingTextBold = compositionLocalOf<ReadingTextBoldPreference> { ReadingTextBoldPreference.default }
|
||||||
|
val LocalReadingTitleAlign = compositionLocalOf<ReadingTitleAlignPreference> { ReadingTitleAlignPreference.default }
|
||||||
|
val LocalReadingSubheadAlign =
|
||||||
|
compositionLocalOf<ReadingSubheadAlignPreference> { ReadingSubheadAlignPreference.default }
|
||||||
|
val LocalReadingFonts = compositionLocalOf<ReadingFontsPreference> { ReadingFontsPreference.default }
|
||||||
|
val LocalReadingTitleBold = compositionLocalOf<ReadingTitleBoldPreference> { ReadingTitleBoldPreference.default }
|
||||||
|
val LocalReadingSubheadBold =
|
||||||
|
compositionLocalOf<ReadingSubheadBoldPreference> { ReadingSubheadBoldPreference.default }
|
||||||
|
val LocalReadingTitleUpperCase =
|
||||||
|
compositionLocalOf<ReadingTitleUpperCasePreference> { ReadingTitleUpperCasePreference.default }
|
||||||
|
val LocalReadingSubheadUpperCase =
|
||||||
|
compositionLocalOf<ReadingSubheadUpperCasePreference> { ReadingSubheadUpperCasePreference.default }
|
||||||
|
val LocalReadingImageHorizontalPadding = compositionLocalOf { ReadingImageHorizontalPaddingPreference.default }
|
||||||
|
val LocalReadingImageRoundedCorners = compositionLocalOf { ReadingImageRoundedCornersPreference.default }
|
||||||
|
val LocalReadingImageMaximize = compositionLocalOf<ReadingImageMaximizePreference> { ReadingImageMaximizePreference.default }
|
||||||
|
|
||||||
|
// Interaction
|
||||||
val LocalInitialPage = compositionLocalOf<InitialPagePreference> { InitialPagePreference.default }
|
val LocalInitialPage = compositionLocalOf<InitialPagePreference> { InitialPagePreference.default }
|
||||||
val LocalInitialFilter =
|
val LocalInitialFilter =
|
||||||
compositionLocalOf<InitialFilterPreference> { InitialFilterPreference.default }
|
compositionLocalOf<InitialFilterPreference> { InitialFilterPreference.default }
|
||||||
|
|
||||||
|
// Languages
|
||||||
val LocalLanguages =
|
val LocalLanguages =
|
||||||
compositionLocalOf<LanguagesPreference> { LanguagesPreference.default }
|
compositionLocalOf<LanguagesPreference> { LanguagesPreference.default }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsProvider(
|
||||||
|
content: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val settings = remember {
|
||||||
|
context.dataStore.data.map {
|
||||||
|
Log.i("RLog", "AppTheme: ${it}")
|
||||||
|
it.toSettings()
|
||||||
|
}
|
||||||
|
}.collectAsStateValue(initial = Settings())
|
||||||
|
|
||||||
|
CompositionLocalProvider(
|
||||||
|
// Version
|
||||||
|
LocalNewVersionNumber provides settings.newVersionNumber,
|
||||||
|
LocalSkipVersionNumber provides settings.skipVersionNumber,
|
||||||
|
LocalNewVersionPublishDate provides settings.newVersionPublishDate,
|
||||||
|
LocalNewVersionLog provides settings.newVersionLog,
|
||||||
|
LocalNewVersionSize provides settings.newVersionSize,
|
||||||
|
LocalNewVersionDownloadUrl provides settings.newVersionDownloadUrl,
|
||||||
|
|
||||||
|
// Theme
|
||||||
|
LocalThemeIndex provides settings.themeIndex,
|
||||||
|
LocalCustomPrimaryColor provides settings.customPrimaryColor,
|
||||||
|
LocalDarkTheme provides settings.darkTheme,
|
||||||
|
LocalAmoledDarkTheme provides settings.amoledDarkTheme,
|
||||||
|
|
||||||
|
// Feeds page
|
||||||
|
LocalFeedsTopBarTonalElevation provides settings.feedsTopBarTonalElevation,
|
||||||
|
LocalFeedsGroupListExpand provides settings.feedsGroupListExpand,
|
||||||
|
LocalFeedsGroupListTonalElevation provides settings.feedsGroupListTonalElevation,
|
||||||
|
LocalFeedsFilterBarStyle provides settings.feedsFilterBarStyle,
|
||||||
|
LocalFeedsFilterBarFilled provides settings.feedsFilterBarFilled,
|
||||||
|
LocalFeedsFilterBarPadding provides settings.feedsFilterBarPadding,
|
||||||
|
LocalFeedsFilterBarTonalElevation provides settings.feedsFilterBarTonalElevation,
|
||||||
|
|
||||||
|
// Flow page
|
||||||
|
LocalFlowTopBarTonalElevation provides settings.flowTopBarTonalElevation,
|
||||||
|
LocalFlowArticleListFeedIcon provides settings.flowArticleListFeedIcon,
|
||||||
|
LocalFlowArticleListFeedName provides settings.flowArticleListFeedName,
|
||||||
|
LocalFlowArticleListImage provides settings.flowArticleListImage,
|
||||||
|
LocalFlowArticleListDesc provides settings.flowArticleListDesc,
|
||||||
|
LocalFlowArticleListTime provides settings.flowArticleListTime,
|
||||||
|
LocalFlowArticleListDateStickyHeader provides settings.flowArticleListDateStickyHeader,
|
||||||
|
LocalFlowArticleListTonalElevation provides settings.flowArticleListTonalElevation,
|
||||||
|
LocalFlowFilterBarStyle provides settings.flowFilterBarStyle,
|
||||||
|
LocalFlowFilterBarFilled provides settings.flowFilterBarFilled,
|
||||||
|
LocalFlowFilterBarPadding provides settings.flowFilterBarPadding,
|
||||||
|
LocalFlowFilterBarTonalElevation provides settings.flowFilterBarTonalElevation,
|
||||||
|
|
||||||
|
// Reading page
|
||||||
|
LocalReadingTheme provides settings.readingTheme,
|
||||||
|
LocalReadingDarkTheme provides settings.readingDarkTheme,
|
||||||
|
LocalReadingPageTonalElevation provides settings.readingPageTonalElevation,
|
||||||
|
LocalReadingAutoHideToolbar provides settings.readingAutoHideToolbar,
|
||||||
|
LocalReadingTextFontSize provides settings.readingTextFontSize,
|
||||||
|
LocalReadingLetterSpacing provides settings.readingLetterSpacing,
|
||||||
|
LocalReadingTextHorizontalPadding provides settings.readingTextHorizontalPadding,
|
||||||
|
LocalReadingTextAlign provides settings.readingTextAlign,
|
||||||
|
LocalReadingTextBold provides settings.readingTextBold,
|
||||||
|
LocalReadingTitleAlign provides settings.readingTitleAlign,
|
||||||
|
LocalReadingSubheadAlign provides settings.readingSubheadAlign,
|
||||||
|
LocalReadingFonts provides settings.readingFonts,
|
||||||
|
LocalReadingTitleBold provides settings.readingTitleBold,
|
||||||
|
LocalReadingSubheadBold provides settings.readingSubheadBold,
|
||||||
|
LocalReadingTitleUpperCase provides settings.readingTitleUpperCase,
|
||||||
|
LocalReadingSubheadUpperCase provides settings.readingSubheadUpperCase,
|
||||||
|
LocalReadingImageHorizontalPadding provides settings.readingImageHorizontalPadding,
|
||||||
|
LocalReadingImageRoundedCorners provides settings.readingImageRoundedCorners,
|
||||||
|
LocalReadingImageMaximize provides settings.readingImageMaximize,
|
||||||
|
|
||||||
|
// Interaction
|
||||||
|
LocalInitialPage provides settings.initialPage,
|
||||||
|
LocalInitialFilter provides settings.initialFilter,
|
||||||
|
|
||||||
|
// Languages
|
||||||
|
LocalLanguages provides settings.languages,
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
168
app/src/main/java/me/ash/reader/ui/component/ReadingThemePrev.kt
Normal file
168
app/src/main/java/me/ash/reader/ui/component/ReadingThemePrev.kt
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
package me.ash.reader.ui.component
|
||||||
|
|
||||||
|
import androidx.compose.animation.core.animateDpAsState
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingImageHorizontalPadding
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingImageRoundedCorners
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingTextAlign
|
||||||
|
import me.ash.reader.data.model.preference.ReadingThemePreference
|
||||||
|
import me.ash.reader.ui.theme.Shape24
|
||||||
|
import me.ash.reader.ui.theme.palette.onDark
|
||||||
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingThemePrev(
|
||||||
|
selected: ReadingThemePreference = ReadingThemePreference.MaterialYou,
|
||||||
|
theme: ReadingThemePreference = ReadingThemePreference.MaterialYou,
|
||||||
|
onClick: () -> Unit = {},
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val imageRoundedCorners = LocalReadingImageRoundedCorners.current
|
||||||
|
val roundedCorners by remember { mutableStateOf(RoundedCornerShape((imageRoundedCorners / 2).dp)) }
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(150.dp)
|
||||||
|
.clip(Shape24)
|
||||||
|
.background(MaterialTheme.colorScheme.inverseOnSurface
|
||||||
|
onLight MaterialTheme.colorScheme.surface
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = animateDpAsState(if (selected == theme) 4.dp else (-1).dp).value,
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
shape = Shape24
|
||||||
|
)
|
||||||
|
.clickable(onClick = onClick),
|
||||||
|
horizontalAlignment = when (theme) {
|
||||||
|
ReadingThemePreference.MaterialYou -> Alignment.Start
|
||||||
|
ReadingThemePreference.Reeder -> Alignment.Start
|
||||||
|
ReadingThemePreference.Paper -> Alignment.CenterHorizontally
|
||||||
|
ReadingThemePreference.Custom -> LocalReadingTextAlign.current.toAlignment()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.height(22.dp))
|
||||||
|
// Header
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(horizontal = 12.dp),
|
||||||
|
text = theme.toDesc(context),
|
||||||
|
style = MaterialTheme.typography.titleSmall,
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
|
// Metadata
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.padding(horizontal = 12.dp)
|
||||||
|
.size(width = 32.dp, height = 4.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(MaterialTheme.colorScheme.tertiaryContainer)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
// Paragraph
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.padding(horizontal = 12.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(12.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceVariant)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(modifier = Modifier
|
||||||
|
.padding(horizontal = 12.dp)
|
||||||
|
.width(114.dp)
|
||||||
|
.height(12.dp)
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.fillMaxSize()
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceVariant)
|
||||||
|
)
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.padding(start = 4.dp)
|
||||||
|
.weight(2f)
|
||||||
|
.fillMaxSize()
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceVariant)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
// Image
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.padding(horizontal = when (theme) {
|
||||||
|
ReadingThemePreference.MaterialYou -> 12.dp
|
||||||
|
ReadingThemePreference.Reeder -> 0.dp
|
||||||
|
ReadingThemePreference.Paper -> 12.dp
|
||||||
|
ReadingThemePreference.Custom -> (LocalReadingImageHorizontalPadding.current / 2).dp
|
||||||
|
})
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(46.dp)
|
||||||
|
.clip(when (theme) {
|
||||||
|
ReadingThemePreference.MaterialYou -> MaterialTheme.shapes.medium
|
||||||
|
ReadingThemePreference.Reeder -> RectangleShape
|
||||||
|
ReadingThemePreference.Paper -> RectangleShape
|
||||||
|
ReadingThemePreference.Custom -> roundedCorners
|
||||||
|
})
|
||||||
|
.background(MaterialTheme.colorScheme.primaryContainer onDark MaterialTheme.colorScheme.secondaryContainer)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
// Footer
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.padding(horizontal = 12.dp)
|
||||||
|
.width(100.dp)
|
||||||
|
.height(12.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceVariant)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(14.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun ReadYouPreview() {
|
||||||
|
ReadingThemePrev(
|
||||||
|
selected = ReadingThemePreference.MaterialYou,
|
||||||
|
theme = ReadingThemePreference.MaterialYou,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun ReederPreview() {
|
||||||
|
ReadingThemePrev(
|
||||||
|
theme = ReadingThemePreference.Reeder,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun PaperPreview() {
|
||||||
|
ReadingThemePrev(
|
||||||
|
theme = ReadingThemePreference.Paper,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun CustomPreview() {
|
||||||
|
ReadingThemePrev(
|
||||||
|
theme = ReadingThemePreference.Custom,
|
||||||
|
)
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.style.BaselineShift
|
import androidx.compose.ui.text.style.BaselineShift
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
@ -63,7 +64,7 @@ fun RadioDialog(
|
||||||
text = option.text,
|
text = option.text,
|
||||||
style = MaterialTheme.typography.bodyLarge.copy(
|
style = MaterialTheme.typography.bodyLarge.copy(
|
||||||
baselineShift = BaselineShift.None
|
baselineShift = BaselineShift.None
|
||||||
),
|
).merge(other = option.style),
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -78,6 +79,7 @@ fun RadioDialog(
|
||||||
@Immutable
|
@Immutable
|
||||||
data class RadioDialogOption(
|
data class RadioDialogOption(
|
||||||
val text: String = "",
|
val text: String = "",
|
||||||
|
val style: TextStyle? = null,
|
||||||
val selected: Boolean = false,
|
val selected: Boolean = false,
|
||||||
val onClick: () -> Unit = {},
|
val onClick: () -> Unit = {},
|
||||||
)
|
)
|
|
@ -33,6 +33,7 @@ import androidx.compose.foundation.text.selection.DisableSelection
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.RectangleShape
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
|
@ -51,6 +52,7 @@ import coil.size.Precision
|
||||||
import coil.size.Size
|
import coil.size.Size
|
||||||
import coil.size.pxOrElse
|
import coil.size.pxOrElse
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingImageMaximize
|
||||||
import me.ash.reader.ui.component.base.RYAsyncImage
|
import me.ash.reader.ui.component.base.RYAsyncImage
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.helper.StringUtil
|
import org.jsoup.helper.StringUtil
|
||||||
|
@ -63,6 +65,7 @@ import kotlin.math.roundToInt
|
||||||
|
|
||||||
fun LazyListScope.htmlFormattedText(
|
fun LazyListScope.htmlFormattedText(
|
||||||
inputStream: InputStream,
|
inputStream: InputStream,
|
||||||
|
subheadUpperCase: Boolean = false,
|
||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
@DrawableRes imagePlaceholder: Int,
|
@DrawableRes imagePlaceholder: Int,
|
||||||
onLinkClick: (String) -> Unit,
|
onLinkClick: (String) -> Unit,
|
||||||
|
@ -72,6 +75,7 @@ fun LazyListScope.htmlFormattedText(
|
||||||
?.let { body ->
|
?.let { body ->
|
||||||
formatBody(
|
formatBody(
|
||||||
element = body,
|
element = body,
|
||||||
|
subheadUpperCase = subheadUpperCase,
|
||||||
imagePlaceholder = imagePlaceholder,
|
imagePlaceholder = imagePlaceholder,
|
||||||
onLinkClick = onLinkClick,
|
onLinkClick = onLinkClick,
|
||||||
baseUrl = baseUrl,
|
baseUrl = baseUrl,
|
||||||
|
@ -81,6 +85,7 @@ fun LazyListScope.htmlFormattedText(
|
||||||
|
|
||||||
private fun LazyListScope.formatBody(
|
private fun LazyListScope.formatBody(
|
||||||
element: Element,
|
element: Element,
|
||||||
|
subheadUpperCase: Boolean = false,
|
||||||
@DrawableRes imagePlaceholder: Int,
|
@DrawableRes imagePlaceholder: Int,
|
||||||
onLinkClick: (String) -> Unit,
|
onLinkClick: (String) -> Unit,
|
||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
|
@ -98,7 +103,7 @@ private fun LazyListScope.formatBody(
|
||||||
text = paragraph,
|
text = paragraph,
|
||||||
style = bodyStyle(),
|
style = bodyStyle(),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = PADDING_HORIZONTAL.dp)
|
.padding(horizontal = textHorizontalPadding().dp)
|
||||||
.width(MAX_CONTENT_WIDTH.dp)
|
.width(MAX_CONTENT_WIDTH.dp)
|
||||||
) { offset ->
|
) { offset ->
|
||||||
paragraph.getStringAnnotations("URL", offset, offset)
|
paragraph.getStringAnnotations("URL", offset, offset)
|
||||||
|
@ -112,7 +117,7 @@ private fun LazyListScope.formatBody(
|
||||||
text = paragraph,
|
text = paragraph,
|
||||||
style = bodyStyle(),
|
style = bodyStyle(),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = PADDING_HORIZONTAL.dp)
|
.padding(horizontal = textHorizontalPadding().dp)
|
||||||
.width(MAX_CONTENT_WIDTH.dp)
|
.width(MAX_CONTENT_WIDTH.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -121,6 +126,7 @@ private fun LazyListScope.formatBody(
|
||||||
|
|
||||||
composer.appendTextChildren(
|
composer.appendTextChildren(
|
||||||
element.childNodes(),
|
element.childNodes(),
|
||||||
|
subheadUpperCase = subheadUpperCase,
|
||||||
lazyListScope = this,
|
lazyListScope = this,
|
||||||
imagePlaceholder = imagePlaceholder,
|
imagePlaceholder = imagePlaceholder,
|
||||||
onLinkClick = onLinkClick,
|
onLinkClick = onLinkClick,
|
||||||
|
@ -144,7 +150,7 @@ private fun LazyListScope.formatCodeBlock(
|
||||||
color = codeBlockBackground(),
|
color = codeBlockBackground(),
|
||||||
shape = RoundedCornerShape(8.dp),
|
shape = RoundedCornerShape(8.dp),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = PADDING_HORIZONTAL.dp),
|
.padding(horizontal = textHorizontalPadding().dp),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -179,6 +185,7 @@ private fun LazyListScope.formatCodeBlock(
|
||||||
private fun TextComposer.appendTextChildren(
|
private fun TextComposer.appendTextChildren(
|
||||||
nodes: List<Node>,
|
nodes: List<Node>,
|
||||||
preFormatted: Boolean = false,
|
preFormatted: Boolean = false,
|
||||||
|
subheadUpperCase: Boolean = false,
|
||||||
lazyListScope: LazyListScope,
|
lazyListScope: LazyListScope,
|
||||||
@DrawableRes imagePlaceholder: Int,
|
@DrawableRes imagePlaceholder: Int,
|
||||||
onLinkClick: (String) -> Unit,
|
onLinkClick: (String) -> Unit,
|
||||||
|
@ -238,9 +245,9 @@ private fun TextComposer.appendTextChildren(
|
||||||
"h1" -> {
|
"h1" -> {
|
||||||
withParagraph {
|
withParagraph {
|
||||||
withComposableStyle(
|
withComposableStyle(
|
||||||
style = { h5Style().toSpanStyle() }
|
style = { h1Style().toSpanStyle() }
|
||||||
) {
|
) {
|
||||||
append("\n${element.text()}")
|
append("\n${if (subheadUpperCase) element.text().uppercase() else element.text()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,9 +255,9 @@ private fun TextComposer.appendTextChildren(
|
||||||
"h2" -> {
|
"h2" -> {
|
||||||
withParagraph {
|
withParagraph {
|
||||||
withComposableStyle(
|
withComposableStyle(
|
||||||
style = { h5Style().toSpanStyle() }
|
style = { h2Style().toSpanStyle() }
|
||||||
) {
|
) {
|
||||||
append("\n${element.text()}")
|
append("\n${if (subheadUpperCase) element.text().uppercase() else element.text()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,9 +265,9 @@ private fun TextComposer.appendTextChildren(
|
||||||
"h3" -> {
|
"h3" -> {
|
||||||
withParagraph {
|
withParagraph {
|
||||||
withComposableStyle(
|
withComposableStyle(
|
||||||
style = { h5Style().toSpanStyle() }
|
style = { h3Style().toSpanStyle() }
|
||||||
) {
|
) {
|
||||||
append("\n${element.text()}")
|
append("\n${if (subheadUpperCase) element.text().uppercase() else element.text()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,9 +275,9 @@ private fun TextComposer.appendTextChildren(
|
||||||
"h4" -> {
|
"h4" -> {
|
||||||
withParagraph {
|
withParagraph {
|
||||||
withComposableStyle(
|
withComposableStyle(
|
||||||
style = { h5Style().toSpanStyle() }
|
style = { h4Style().toSpanStyle() }
|
||||||
) {
|
) {
|
||||||
append("\n${element.text()}")
|
append("\n${if (subheadUpperCase) element.text().uppercase() else element.text()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,7 +287,7 @@ private fun TextComposer.appendTextChildren(
|
||||||
withComposableStyle(
|
withComposableStyle(
|
||||||
style = { h5Style().toSpanStyle() }
|
style = { h5Style().toSpanStyle() }
|
||||||
) {
|
) {
|
||||||
append("\n${element.text()}")
|
append("\n${if (subheadUpperCase) element.text().uppercase() else element.text()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,15 +295,17 @@ private fun TextComposer.appendTextChildren(
|
||||||
"h6" -> {
|
"h6" -> {
|
||||||
withParagraph {
|
withParagraph {
|
||||||
withComposableStyle(
|
withComposableStyle(
|
||||||
style = { h5Style().toSpanStyle() }
|
style = { h6Style().toSpanStyle() }
|
||||||
) {
|
) {
|
||||||
append("\n${element.text()}")
|
append("\n${if (subheadUpperCase) element.text().uppercase() else element.text()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"strong", "b" -> {
|
"strong", "b" -> {
|
||||||
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
|
withComposableStyle(
|
||||||
|
style = { boldStyle().toSpanStyle() }
|
||||||
|
) {
|
||||||
appendTextChildren(
|
appendTextChildren(
|
||||||
element.childNodes(),
|
element.childNodes(),
|
||||||
lazyListScope = lazyListScope,
|
lazyListScope = lazyListScope,
|
||||||
|
@ -419,8 +428,11 @@ private fun TextComposer.appendTextChildren(
|
||||||
|
|
||||||
"blockquote" -> {
|
"blockquote" -> {
|
||||||
withParagraph {
|
withParagraph {
|
||||||
withComposableStyle(
|
withStyle(
|
||||||
style = { blockQuoteStyle() }
|
SpanStyle(
|
||||||
|
fontStyle = FontStyle.Italic,
|
||||||
|
fontWeight = FontWeight.Light,
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
appendTextChildren(
|
appendTextChildren(
|
||||||
element.childNodes(),
|
element.childNodes(),
|
||||||
|
@ -458,10 +470,10 @@ private fun TextComposer.appendTextChildren(
|
||||||
// val scale = remember { mutableStateOf(1f) }
|
// val scale = remember { mutableStateOf(1f) }
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
// .padding(horizontal = PADDING_HORIZONTAL.dp)
|
// .padding(horizontal = horizontalPadding().dp)
|
||||||
.width(MAX_CONTENT_WIDTH.dp)
|
.width(MAX_CONTENT_WIDTH.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(PADDING_HORIZONTAL.dp))
|
Spacer(modifier = Modifier.height(textHorizontalPadding().dp))
|
||||||
DisableSelection {
|
DisableSelection {
|
||||||
BoxWithConstraints(
|
BoxWithConstraints(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -487,9 +499,10 @@ private fun TextComposer.appendTextChildren(
|
||||||
val imageSize = maxImageSize()
|
val imageSize = maxImageSize()
|
||||||
RYAsyncImage(
|
RYAsyncImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = PADDING_HORIZONTAL.dp)
|
.padding(horizontal = imageHorizontalPadding().dp)
|
||||||
.clip(IMAGE_SHAPE)
|
.clip(imageShape())
|
||||||
.clickable { },
|
.clickable { },
|
||||||
data = imageCandidates.getBestImageForMaxSize(
|
data = imageCandidates.getBestImageForMaxSize(
|
||||||
pixelDensity = pixelDensity(),
|
pixelDensity = pixelDensity(),
|
||||||
|
@ -498,24 +511,24 @@ private fun TextComposer.appendTextChildren(
|
||||||
contentDescription = alt,
|
contentDescription = alt,
|
||||||
size = imageSize,
|
size = imageSize,
|
||||||
precision = Precision.INEXACT,
|
precision = Precision.INEXACT,
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = if (LocalReadingImageMaximize.current.value) ContentScale.FillWidth else ContentScale.Inside,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alt.isNotBlank()) {
|
if (alt.isNotBlank()) {
|
||||||
Spacer(modifier = Modifier.height(PADDING_HORIZONTAL.dp / 2))
|
Spacer(modifier = Modifier.height(textHorizontalPadding().dp / 2))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = PADDING_HORIZONTAL.dp),
|
.padding(horizontal = textHorizontalPadding().dp),
|
||||||
text = alt,
|
text = alt,
|
||||||
style = captionStyle(),
|
style = captionStyle(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(PADDING_HORIZONTAL.dp))
|
Spacer(modifier = Modifier.height(textHorizontalPadding().dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -612,7 +625,7 @@ private fun TextComposer.appendTextChildren(
|
||||||
lazyListScope.item {
|
lazyListScope.item {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = PADDING_HORIZONTAL.dp)
|
.padding(horizontal = textHorizontalPadding().dp)
|
||||||
.width(MAX_CONTENT_WIDTH.dp)
|
.width(MAX_CONTENT_WIDTH.dp)
|
||||||
) {
|
) {
|
||||||
DisableSelection {
|
DisableSelection {
|
||||||
|
@ -622,8 +635,8 @@ private fun TextComposer.appendTextChildren(
|
||||||
RYAsyncImage(
|
RYAsyncImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = PADDING_HORIZONTAL.dp)
|
.padding(horizontal = imageHorizontalPadding().dp)
|
||||||
.clip(IMAGE_SHAPE)
|
.clip(imageShape())
|
||||||
.clickable {
|
.clickable {
|
||||||
onLinkClick(video.link)
|
onLinkClick(video.link)
|
||||||
},
|
},
|
||||||
|
@ -636,17 +649,17 @@ private fun TextComposer.appendTextChildren(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(PADDING_HORIZONTAL.dp / 2))
|
Spacer(modifier = Modifier.height(textHorizontalPadding().dp / 2))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = PADDING_HORIZONTAL.dp),
|
.padding(horizontal = textHorizontalPadding().dp),
|
||||||
text = stringResource(R.string.touch_to_play_video),
|
text = stringResource(R.string.touch_to_play_video),
|
||||||
style = captionStyle(),
|
style = captionStyle(),
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(PADDING_HORIZONTAL.dp))
|
Spacer(modifier = Modifier.height(textHorizontalPadding().dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -661,6 +674,7 @@ private fun TextComposer.appendTextChildren(
|
||||||
appendTextChildren(
|
appendTextChildren(
|
||||||
nodes = element.childNodes(),
|
nodes = element.childNodes(),
|
||||||
preFormatted = preFormatted,
|
preFormatted = preFormatted,
|
||||||
|
subheadUpperCase = subheadUpperCase,
|
||||||
lazyListScope = lazyListScope,
|
lazyListScope = lazyListScope,
|
||||||
imagePlaceholder = imagePlaceholder,
|
imagePlaceholder = imagePlaceholder,
|
||||||
onLinkClick = onLinkClick,
|
onLinkClick = onLinkClick,
|
||||||
|
|
|
@ -30,12 +30,14 @@ import me.ash.reader.R
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
fun LazyListScope.Reader(
|
fun LazyListScope.Reader(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
subheadUpperCase: Boolean = false,
|
||||||
link: String,
|
link: String,
|
||||||
content: String,
|
content: String,
|
||||||
) {
|
) {
|
||||||
Log.i("RLog", "Reader: ")
|
Log.i("RLog", "Reader: ")
|
||||||
htmlFormattedText(
|
htmlFormattedText(
|
||||||
inputStream = content.byteInputStream(),
|
inputStream = content.byteInputStream(),
|
||||||
|
subheadUpperCase = subheadUpperCase,
|
||||||
baseUrl = link,
|
baseUrl = link,
|
||||||
imagePlaceholder = R.drawable.ic_launcher_foreground,
|
imagePlaceholder = R.drawable.ic_launcher_foreground,
|
||||||
onLinkClick = {
|
onLinkClick = {
|
||||||
|
|
|
@ -23,6 +23,8 @@ package me.ash.reader.ui.component.reader
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
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.graphics.Color
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
@ -31,79 +33,162 @@ import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextDecoration
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import me.ash.reader.data.model.preference.*
|
||||||
import me.ash.reader.ui.ext.alphaLN
|
import me.ash.reader.ui.ext.alphaLN
|
||||||
|
|
||||||
const val PADDING_HORIZONTAL = 24.0
|
|
||||||
const val MAX_CONTENT_WIDTH = 840.0
|
const val MAX_CONTENT_WIDTH = 840.0
|
||||||
val IMAGE_SHAPE = RoundedCornerShape(32.dp)
|
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
fun bodyForeground(): Color =
|
@ReadOnlyComposable
|
||||||
|
fun imageHorizontalPadding(): Int =
|
||||||
|
LocalReadingImageHorizontalPadding.current
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
fun imageShape(): RoundedCornerShape =
|
||||||
|
RoundedCornerShape(LocalReadingImageRoundedCorners.current.dp)
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
fun onSurfaceColor(): Color =
|
||||||
|
MaterialTheme.colorScheme.onSurface
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
fun onSurfaceVariantColor(): Color =
|
||||||
MaterialTheme.colorScheme.onSurfaceVariant
|
MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
fun textHorizontalPadding(): Int =
|
||||||
|
LocalReadingTextHorizontalPadding.current
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
fun bodyForeground(): Color = onSurfaceVariantColor()
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
fun bodyStyle(): TextStyle =
|
fun bodyStyle(): TextStyle =
|
||||||
MaterialTheme.typography.bodyLarge.copy(
|
TextStyle(
|
||||||
|
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||||
|
fontWeight = if (LocalReadingTextBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
fontSize = LocalReadingTextFontSize.current.sp,
|
||||||
|
letterSpacing = LocalReadingLetterSpacing.current.sp,
|
||||||
color = bodyForeground(),
|
color = bodyForeground(),
|
||||||
textAlign = TextAlign.Start,
|
textAlign = LocalReadingTextAlign.current.toTextAlign(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
fun h1Style(): TextStyle =
|
fun h1Style(): TextStyle =
|
||||||
MaterialTheme.typography.displayMedium.copy(
|
TextStyle(
|
||||||
color = bodyForeground(),
|
fontFamily = LocalReadingFonts.current.asFontFamily(isDisplay = true),
|
||||||
textAlign = TextAlign.Start,
|
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
fontSize = 28.sp,
|
||||||
|
letterSpacing = 0.sp,
|
||||||
|
color = onSurfaceColor(),
|
||||||
|
textAlign = LocalReadingSubheadAlign.current.toTextAlign(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
fun h2Style(): TextStyle =
|
fun h2Style(): TextStyle =
|
||||||
MaterialTheme.typography.displaySmall.copy(
|
TextStyle(
|
||||||
color = bodyForeground(),
|
fontFamily = LocalReadingFonts.current.asFontFamily(isDisplay = true),
|
||||||
textAlign = TextAlign.Start,
|
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
fontSize = 28.sp,
|
||||||
|
letterSpacing = 0.sp,
|
||||||
|
color = onSurfaceColor(),
|
||||||
|
textAlign = LocalReadingSubheadAlign.current.toTextAlign(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
fun h3Style(): TextStyle =
|
fun h3Style(): TextStyle =
|
||||||
MaterialTheme.typography.headlineLarge.copy(
|
TextStyle(
|
||||||
color = bodyForeground(),
|
fontFamily = LocalReadingFonts.current.asFontFamily(isDisplay = true),
|
||||||
textAlign = TextAlign.Start,
|
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
fontSize = 19.sp,
|
||||||
|
letterSpacing = 0.sp,
|
||||||
|
color = onSurfaceColor(),
|
||||||
|
textAlign = LocalReadingSubheadAlign.current.toTextAlign(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
fun h4Style(): TextStyle =
|
fun h4Style(): TextStyle =
|
||||||
MaterialTheme.typography.headlineMedium.copy(
|
TextStyle(
|
||||||
color = bodyForeground(),
|
fontFamily = LocalReadingFonts.current.asFontFamily(isDisplay = true),
|
||||||
textAlign = TextAlign.Start,
|
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
fontSize = 17.sp,
|
||||||
|
letterSpacing = 0.sp,
|
||||||
|
color = onSurfaceColor(),
|
||||||
|
textAlign = LocalReadingSubheadAlign.current.toTextAlign(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
fun h5Style(): TextStyle =
|
fun h5Style(): TextStyle =
|
||||||
MaterialTheme.typography.headlineSmall.copy(
|
TextStyle(
|
||||||
color = bodyForeground(),
|
fontFamily = LocalReadingFonts.current.asFontFamily(isDisplay = true),
|
||||||
textAlign = TextAlign.Start,
|
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
fontSize = 17.sp,
|
||||||
|
letterSpacing = 0.sp,
|
||||||
|
color = onSurfaceColor(),
|
||||||
|
textAlign = LocalReadingSubheadAlign.current.toTextAlign(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
fun h6Style(): TextStyle =
|
fun h6Style(): TextStyle =
|
||||||
MaterialTheme.typography.titleLarge.copy(
|
TextStyle(
|
||||||
color = bodyForeground(),
|
fontFamily = LocalReadingFonts.current.asFontFamily(isDisplay = true),
|
||||||
textAlign = TextAlign.Start,
|
fontWeight = if (LocalReadingSubheadBold.current.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
fontSize = 17.sp,
|
||||||
|
letterSpacing = 0.sp,
|
||||||
|
color = onSurfaceColor(),
|
||||||
|
textAlign = LocalReadingSubheadAlign.current.toTextAlign(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
fun captionStyle(): TextStyle =
|
fun captionStyle(): TextStyle =
|
||||||
MaterialTheme.typography.bodySmall.copy(
|
MaterialTheme.typography.bodySmall.merge(
|
||||||
|
TextStyle(
|
||||||
|
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||||
color = bodyForeground().copy(alpha = 0.6f),
|
color = bodyForeground().copy(alpha = 0.6f),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun linkTextStyle(): TextStyle =
|
|
||||||
TextStyle(
|
|
||||||
color = MaterialTheme.colorScheme.secondary,
|
|
||||||
textDecoration = TextDecoration.Underline
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
fun linkTextStyle(): TextStyle =
|
||||||
|
TextStyle(
|
||||||
|
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||||
|
fontSize = LocalReadingTextFontSize.current.sp,
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
textDecoration = TextDecoration.Underline,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
fun codeBlockStyle(): TextStyle =
|
fun codeBlockStyle(): TextStyle =
|
||||||
MaterialTheme.typography.titleSmall.merge(
|
MaterialTheme.typography.titleSmall.merge(
|
||||||
|
@ -113,21 +198,27 @@ fun codeBlockStyle(): TextStyle =
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
fun codeBlockBackground(): Color =
|
fun codeBlockBackground(): Color =
|
||||||
MaterialTheme.colorScheme.secondary.copy(alpha = (0.dp).alphaLN(weight = 3.2f))
|
MaterialTheme.colorScheme.secondary.copy(alpha = (0.dp).alphaLN(weight = 3.2f))
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
fun blockQuoteStyle(): SpanStyle =
|
fun boldStyle(): TextStyle =
|
||||||
MaterialTheme.typography.titleSmall.toSpanStyle().merge(
|
bodyStyle().merge(
|
||||||
SpanStyle(
|
SpanStyle(
|
||||||
fontWeight = FontWeight.Light
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
color = onSurfaceColor(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
fun codeInlineStyle(): SpanStyle =
|
fun codeInlineStyle(): SpanStyle =
|
||||||
MaterialTheme.typography.titleSmall.toSpanStyle().copy(
|
MaterialTheme.typography.titleSmall.toSpanStyle().merge(
|
||||||
|
SpanStyle(
|
||||||
color = bodyForeground(),
|
color = bodyForeground(),
|
||||||
fontFamily = FontFamily.Monospace,
|
fontFamily = FontFamily.Monospace,
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -69,6 +69,7 @@ sealed class DataStoreKeys<T> {
|
||||||
|
|
||||||
abstract val key: Preferences.Key<T>
|
abstract val key: Preferences.Key<T>
|
||||||
|
|
||||||
|
// Version
|
||||||
object IsFirstLaunch : DataStoreKeys<Boolean>() {
|
object IsFirstLaunch : DataStoreKeys<Boolean>() {
|
||||||
|
|
||||||
override val key: Preferences.Key<Boolean>
|
override val key: Preferences.Key<Boolean>
|
||||||
|
@ -147,6 +148,7 @@ sealed class DataStoreKeys<T> {
|
||||||
get() = booleanPreferencesKey("amoledDarkTheme")
|
get() = booleanPreferencesKey("amoledDarkTheme")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Feeds page
|
||||||
object FeedsFilterBarStyle : DataStoreKeys<Int>() {
|
object FeedsFilterBarStyle : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
override val key: Preferences.Key<Int>
|
override val key: Preferences.Key<Int>
|
||||||
|
@ -189,6 +191,7 @@ sealed class DataStoreKeys<T> {
|
||||||
get() = intPreferencesKey("feedsGroupListTonalElevation")
|
get() = intPreferencesKey("feedsGroupListTonalElevation")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flow page
|
||||||
object FlowFilterBarStyle : DataStoreKeys<Int>() {
|
object FlowFilterBarStyle : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
override val key: Preferences.Key<Int>
|
override val key: Preferences.Key<Int>
|
||||||
|
@ -261,6 +264,122 @@ sealed class DataStoreKeys<T> {
|
||||||
get() = intPreferencesKey("flowArticleListTonalElevation")
|
get() = intPreferencesKey("flowArticleListTonalElevation")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reading page
|
||||||
|
object ReadingDarkTheme : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingDarkTheme")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingPageTonalElevation : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("ReadingPageTonalElevation")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingTextFontSize : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingTextFontSize")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingLetterSpacing : DataStoreKeys<Double>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Double>
|
||||||
|
get() = doublePreferencesKey("readingLetterSpacing")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingTextHorizontalPadding : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingTextHorizontalPadding")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingTextBold : DataStoreKeys<Boolean>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Boolean>
|
||||||
|
get() = booleanPreferencesKey("readingTextBold")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingTextAlign : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingTextAlign")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingTitleAlign : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingTitleAlign")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingSubheadAlign : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingSubheadAlign")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingTheme : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingTheme")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingFonts : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingFonts")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingAutoHideToolbar : DataStoreKeys<Boolean>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Boolean>
|
||||||
|
get() = booleanPreferencesKey("readingAutoHideToolbar")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingTitleBold : DataStoreKeys<Boolean>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Boolean>
|
||||||
|
get() = booleanPreferencesKey("readingTitleBold")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingSubheadBold : DataStoreKeys<Boolean>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Boolean>
|
||||||
|
get() = booleanPreferencesKey("ReadingSubheadBold")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingTitleUpperCase : DataStoreKeys<Boolean>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Boolean>
|
||||||
|
get() = booleanPreferencesKey("readingTitleUpperCase")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingSubheadUpperCase : DataStoreKeys<Boolean>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Boolean>
|
||||||
|
get() = booleanPreferencesKey("ReadingSubheadUpperCase")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingImageMaximize : DataStoreKeys<Boolean>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Boolean>
|
||||||
|
get() = booleanPreferencesKey("readingImageMaximize")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingImageHorizontalPadding : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingImageHorizontalPadding")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReadingImageRoundedCorners : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
|
override val key: Preferences.Key<Int>
|
||||||
|
get() = intPreferencesKey("readingImageRoundedCorners")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interaction
|
||||||
object InitialPage : DataStoreKeys<Int>() {
|
object InitialPage : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
override val key: Preferences.Key<Int>
|
override val key: Preferences.Key<Int>
|
||||||
|
@ -273,6 +392,7 @@ sealed class DataStoreKeys<T> {
|
||||||
get() = intPreferencesKey("initialFilter")
|
get() = intPreferencesKey("initialFilter")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Languages
|
||||||
object Languages : DataStoreKeys<Int>() {
|
object Languages : DataStoreKeys<Int>() {
|
||||||
|
|
||||||
override val key: Preferences.Key<Int>
|
override val key: Preferences.Key<Int>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package me.ash.reader.ui.page.common
|
package me.ash.reader.ui.page.common
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
@ -12,8 +13,11 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import com.google.accompanist.navigation.animation.AnimatedNavHost
|
import com.google.accompanist.navigation.animation.AnimatedNavHost
|
||||||
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import me.ash.reader.data.model.general.Filter
|
import me.ash.reader.data.model.general.Filter
|
||||||
import me.ash.reader.data.model.preference.LocalDarkTheme
|
import me.ash.reader.data.model.preference.LocalDarkTheme
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingDarkTheme
|
||||||
import me.ash.reader.ui.ext.*
|
import me.ash.reader.ui.ext.*
|
||||||
import me.ash.reader.ui.page.home.HomeViewModel
|
import me.ash.reader.ui.page.home.HomeViewModel
|
||||||
import me.ash.reader.ui.page.home.feeds.FeedsPage
|
import me.ash.reader.ui.page.home.feeds.FeedsPage
|
||||||
|
@ -24,6 +28,7 @@ import me.ash.reader.ui.page.settings.color.ColorAndStylePage
|
||||||
import me.ash.reader.ui.page.settings.color.DarkThemePage
|
import me.ash.reader.ui.page.settings.color.DarkThemePage
|
||||||
import me.ash.reader.ui.page.settings.color.feeds.FeedsPageStylePage
|
import me.ash.reader.ui.page.settings.color.feeds.FeedsPageStylePage
|
||||||
import me.ash.reader.ui.page.settings.color.flow.FlowPageStylePage
|
import me.ash.reader.ui.page.settings.color.flow.FlowPageStylePage
|
||||||
|
import me.ash.reader.ui.page.settings.color.reading.*
|
||||||
import me.ash.reader.ui.page.settings.interaction.InteractionPage
|
import me.ash.reader.ui.page.settings.interaction.InteractionPage
|
||||||
import me.ash.reader.ui.page.settings.languages.LanguagesPage
|
import me.ash.reader.ui.page.settings.languages.LanguagesPage
|
||||||
import me.ash.reader.ui.page.settings.tips.TipsAndSupportPage
|
import me.ash.reader.ui.page.settings.tips.TipsAndSupportPage
|
||||||
|
@ -36,6 +41,7 @@ fun HomeEntry(
|
||||||
homeViewModel: HomeViewModel = hiltViewModel(),
|
homeViewModel: HomeViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
var isReadingPage by rememberSaveable { mutableStateOf(false) }
|
||||||
val filterUiState = homeViewModel.filterUiState.collectAsStateValue()
|
val filterUiState = homeViewModel.filterUiState.collectAsStateValue()
|
||||||
val navController = rememberAnimatedNavController()
|
val navController = rememberAnimatedNavController()
|
||||||
|
|
||||||
|
@ -47,6 +53,11 @@ fun HomeEntry(
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
navController.currentBackStackEntryFlow.collectLatest {
|
||||||
|
Log.i("RLog", "isReadingPage: ${navController.currentDestination?.route}")
|
||||||
|
delay(310L)
|
||||||
|
isReadingPage = navController.currentDestination?.route == "${RouteName.READING}/{articleId}"
|
||||||
|
}
|
||||||
when (context.initialPage) {
|
when (context.initialPage) {
|
||||||
1 -> {
|
1 -> {
|
||||||
navController.navigate(RouteName.FLOW) {
|
navController.navigate(RouteName.FLOW) {
|
||||||
|
@ -80,9 +91,16 @@ fun HomeEntry(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val useDarkTheme = LocalDarkTheme.current.isDarkTheme()
|
val useDarkTheme = if (isReadingPage) {
|
||||||
|
LocalReadingDarkTheme.current.isDarkTheme()
|
||||||
|
} else {
|
||||||
|
LocalDarkTheme.current.isDarkTheme()
|
||||||
|
}
|
||||||
|
|
||||||
AppTheme(useDarkTheme = useDarkTheme) {
|
AppTheme(
|
||||||
|
useDarkTheme = if (isReadingPage) LocalReadingDarkTheme.current.isDarkTheme()
|
||||||
|
else LocalDarkTheme.current.isDarkTheme()
|
||||||
|
) {
|
||||||
|
|
||||||
rememberSystemUiController().run {
|
rememberSystemUiController().run {
|
||||||
setStatusBarColor(Color.Transparent, !useDarkTheme)
|
setStatusBarColor(Color.Transparent, !useDarkTheme)
|
||||||
|
@ -132,6 +150,24 @@ fun HomeEntry(
|
||||||
animatedComposable(route = RouteName.FLOW_PAGE_STYLE) {
|
animatedComposable(route = RouteName.FLOW_PAGE_STYLE) {
|
||||||
FlowPageStylePage(navController)
|
FlowPageStylePage(navController)
|
||||||
}
|
}
|
||||||
|
animatedComposable(route = RouteName.READING_PAGE_STYLE) {
|
||||||
|
ReadingStylePage(navController)
|
||||||
|
}
|
||||||
|
animatedComposable(route = RouteName.READING_DARK_THEME) {
|
||||||
|
ReadingDarkThemePage(navController)
|
||||||
|
}
|
||||||
|
animatedComposable(route = RouteName.READING_PAGE_TITLE) {
|
||||||
|
ReadingTitlePage(navController)
|
||||||
|
}
|
||||||
|
animatedComposable(route = RouteName.READING_PAGE_TEXT) {
|
||||||
|
ReadingTextPage(navController)
|
||||||
|
}
|
||||||
|
animatedComposable(route = RouteName.READING_PAGE_IMAGE) {
|
||||||
|
ReadingImagePage(navController)
|
||||||
|
}
|
||||||
|
animatedComposable(route = RouteName.READING_PAGE_VIDEO) {
|
||||||
|
ReadingVideoPage(navController)
|
||||||
|
}
|
||||||
|
|
||||||
// Interaction
|
// Interaction
|
||||||
animatedComposable(route = RouteName.INTERACTION) {
|
animatedComposable(route = RouteName.INTERACTION) {
|
||||||
|
|
|
@ -18,6 +18,12 @@ object RouteName {
|
||||||
const val DARK_THEME = "dark_theme"
|
const val DARK_THEME = "dark_theme"
|
||||||
const val FEEDS_PAGE_STYLE = "feeds_page_style"
|
const val FEEDS_PAGE_STYLE = "feeds_page_style"
|
||||||
const val FLOW_PAGE_STYLE = "flow_page_style"
|
const val FLOW_PAGE_STYLE = "flow_page_style"
|
||||||
|
const val READING_PAGE_STYLE = "reading_page_style"
|
||||||
|
const val READING_DARK_THEME = "reading_dark_theme"
|
||||||
|
const val READING_PAGE_TITLE = "reading_page_title"
|
||||||
|
const val READING_PAGE_TEXT = "reading_page_text"
|
||||||
|
const val READING_PAGE_IMAGE = "reading_page_image"
|
||||||
|
const val READING_PAGE_VIDEO = "reading_page_video"
|
||||||
|
|
||||||
// Interaction
|
// Interaction
|
||||||
const val INTERACTION = "interaction"
|
const val INTERACTION = "interaction"
|
||||||
|
|
|
@ -22,6 +22,7 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.zIndex
|
import androidx.compose.ui.zIndex
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingPageTonalElevation
|
||||||
import me.ash.reader.ui.component.base.CanBeDisabledIconButton
|
import me.ash.reader.ui.component.base.CanBeDisabledIconButton
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -34,6 +35,8 @@ fun BottomBar(
|
||||||
onStarred: (isStarred: Boolean) -> Unit = {},
|
onStarred: (isStarred: Boolean) -> Unit = {},
|
||||||
onFullContent: (isFullContent: Boolean) -> Unit = {},
|
onFullContent: (isFullContent: Boolean) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
|
val tonalElevation = LocalReadingPageTonalElevation.current
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
@ -43,7 +46,10 @@ fun BottomBar(
|
||||||
RYExtensibleVisibility(visible = isShow) {
|
RYExtensibleVisibility(visible = isShow) {
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
|
|
||||||
Surface(modifier = Modifier.navigationBarsPadding()) {
|
Surface(
|
||||||
|
modifier = Modifier.navigationBarsPadding(),
|
||||||
|
tonalElevation = tonalElevation.value.dp,
|
||||||
|
) {
|
||||||
// TODO: Component styles await refactoring
|
// TODO: Component styles await refactoring
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
|
@ -13,6 +13,7 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingSubheadUpperCase
|
||||||
import me.ash.reader.ui.component.reader.Reader
|
import me.ash.reader.ui.component.reader.Reader
|
||||||
import me.ash.reader.ui.ext.drawVerticalScrollbar
|
import me.ash.reader.ui.ext.drawVerticalScrollbar
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -30,6 +31,7 @@ fun Content(
|
||||||
isShowToolBar: Boolean,
|
isShowToolBar: Boolean,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val subheadUpperCase = LocalReadingSubheadUpperCase.current
|
||||||
|
|
||||||
SelectionContainer {
|
SelectionContainer {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
|
@ -56,7 +58,7 @@ fun Content(
|
||||||
.padding(horizontal = 12.dp)
|
.padding(horizontal = 12.dp)
|
||||||
) {
|
) {
|
||||||
DisableSelection {
|
DisableSelection {
|
||||||
Header(
|
Metadata(
|
||||||
feedName = feedName,
|
feedName = feedName,
|
||||||
title = title,
|
title = title,
|
||||||
author = author,
|
author = author,
|
||||||
|
@ -88,6 +90,7 @@ fun Content(
|
||||||
if (!isLoading) {
|
if (!isLoading) {
|
||||||
Reader(
|
Reader(
|
||||||
context = context,
|
context = context,
|
||||||
|
subheadUpperCase = subheadUpperCase.value,
|
||||||
link = link ?: "",
|
link = link ?: "",
|
||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
package me.ash.reader.ui.page.home.reading
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.*
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import me.ash.reader.ui.ext.formatAsString
|
|
||||||
import me.ash.reader.ui.ext.openURL
|
|
||||||
import me.ash.reader.ui.ext.roundClick
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Header(
|
|
||||||
feedName: String,
|
|
||||||
title: String,
|
|
||||||
author: String? = null,
|
|
||||||
link: String? = null,
|
|
||||||
publishedDate: Date,
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
val dateString = remember(publishedDate) {
|
|
||||||
publishedDate.formatAsString(context, atHourMinute = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.roundClick {
|
|
||||||
context.openURL(link)
|
|
||||||
}
|
|
||||||
.padding(12.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
modifier = Modifier.alpha(0.7f),
|
|
||||||
text = dateString,
|
|
||||||
color = MaterialTheme.colorScheme.outline,
|
|
||||||
style = MaterialTheme.typography.labelMedium,
|
|
||||||
textAlign = TextAlign.Start,
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
Text(
|
|
||||||
text = title,
|
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
|
||||||
style = MaterialTheme.typography.headlineLarge,
|
|
||||||
textAlign = TextAlign.Start,
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
author?.let {
|
|
||||||
if (it.isNotEmpty()) {
|
|
||||||
Text(
|
|
||||||
modifier = Modifier.alpha(0.7f),
|
|
||||||
text = it,
|
|
||||||
color = MaterialTheme.colorScheme.outline,
|
|
||||||
style = MaterialTheme.typography.labelMedium,
|
|
||||||
textAlign = TextAlign.Start,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
modifier = Modifier.alpha(0.7f),
|
|
||||||
text = feedName,
|
|
||||||
color = MaterialTheme.colorScheme.outline,
|
|
||||||
style = MaterialTheme.typography.labelMedium,
|
|
||||||
textAlign = TextAlign.Start,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
100
app/src/main/java/me/ash/reader/ui/page/home/reading/Metadata.kt
Normal file
100
app/src/main/java/me/ash/reader/ui/page/home/reading/Metadata.kt
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
package me.ash.reader.ui.page.home.reading
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingFonts
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingTitleAlign
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingTitleBold
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingTitleUpperCase
|
||||||
|
import me.ash.reader.ui.ext.formatAsString
|
||||||
|
import me.ash.reader.ui.ext.openURL
|
||||||
|
import me.ash.reader.ui.ext.roundClick
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Metadata(
|
||||||
|
feedName: String,
|
||||||
|
title: String,
|
||||||
|
author: String? = null,
|
||||||
|
link: String? = null,
|
||||||
|
publishedDate: Date,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val titleBold = LocalReadingTitleBold.current
|
||||||
|
val titleUpperCase = LocalReadingTitleUpperCase.current
|
||||||
|
val titleAlign = LocalReadingTitleAlign.current
|
||||||
|
val dateString = remember(publishedDate) {
|
||||||
|
publishedDate.formatAsString(context, atHourMinute = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
val titleUpperCaseString by remember { derivedStateOf { title.uppercase() } }
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.roundClick {
|
||||||
|
context.openURL(link)
|
||||||
|
}
|
||||||
|
.padding(12.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.alpha(0.7f)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
text = dateString,
|
||||||
|
color = MaterialTheme.colorScheme.outline,
|
||||||
|
style = MaterialTheme.typography.labelMedium.copy(
|
||||||
|
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||||
|
),
|
||||||
|
textAlign = titleAlign.toTextAlign(),
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
text = if (titleUpperCase.value) titleUpperCaseString else title,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
style = MaterialTheme.typography.headlineLarge.copy(
|
||||||
|
fontFamily = LocalReadingFonts.current.asFontFamily(isDisplay = true),
|
||||||
|
fontWeight = if (titleBold.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
),
|
||||||
|
textAlign = titleAlign.toTextAlign(),
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
author?.let {
|
||||||
|
if (it.isNotEmpty()) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.alpha(0.7f)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
text = it,
|
||||||
|
color = MaterialTheme.colorScheme.outline,
|
||||||
|
style = MaterialTheme.typography.labelMedium.copy(
|
||||||
|
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||||
|
),
|
||||||
|
textAlign = titleAlign.toTextAlign(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.alpha(0.7f)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
text = feedName,
|
||||||
|
color = MaterialTheme.colorScheme.outline,
|
||||||
|
style = MaterialTheme.typography.labelMedium.copy(
|
||||||
|
fontFamily = LocalReadingFonts.current.asFontFamily(),
|
||||||
|
),
|
||||||
|
textAlign = titleAlign.toTextAlign(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,8 +6,11 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingAutoHideToolbar
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingPageTonalElevation
|
||||||
import me.ash.reader.ui.component.base.RYScaffold
|
import me.ash.reader.ui.component.base.RYScaffold
|
||||||
import me.ash.reader.ui.ext.collectAsStateValue
|
import me.ash.reader.ui.ext.collectAsStateValue
|
||||||
import me.ash.reader.ui.ext.isScrollDown
|
import me.ash.reader.ui.ext.isScrollDown
|
||||||
|
@ -17,9 +20,13 @@ fun ReadingPage(
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
readingViewModel: ReadingViewModel = hiltViewModel(),
|
readingViewModel: ReadingViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
|
val tonalElevation = LocalReadingPageTonalElevation.current
|
||||||
val readingUiState = readingViewModel.readingUiState.collectAsStateValue()
|
val readingUiState = readingViewModel.readingUiState.collectAsStateValue()
|
||||||
val isShowToolBar =
|
val isShowToolBar = if (LocalReadingAutoHideToolbar.current.value) {
|
||||||
readingUiState.articleWithFeed != null && !readingUiState.listState.isScrollDown()
|
readingUiState.articleWithFeed != null && !readingUiState.listState.isScrollDown()
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
navController.currentBackStackEntryFlow.collect {
|
navController.currentBackStackEntryFlow.collect {
|
||||||
|
@ -39,12 +46,15 @@ fun ReadingPage(
|
||||||
}
|
}
|
||||||
|
|
||||||
RYScaffold(
|
RYScaffold(
|
||||||
|
topBarTonalElevation = tonalElevation.value.dp,
|
||||||
|
containerTonalElevation = tonalElevation.value.dp,
|
||||||
content = {
|
content = {
|
||||||
Log.i("RLog", "TopBar: recomposition")
|
Log.i("RLog", "TopBar: recomposition")
|
||||||
|
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
// Top Bar
|
// Top Bar
|
||||||
TopBar(
|
TopBar(
|
||||||
|
navController = navController,
|
||||||
isShow = isShowToolBar,
|
isShow = isShowToolBar,
|
||||||
title = readingUiState.articleWithFeed?.article?.title,
|
title = readingUiState.articleWithFeed?.article?.title,
|
||||||
link = readingUiState.articleWithFeed?.article?.link,
|
link = readingUiState.articleWithFeed?.article?.link,
|
||||||
|
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Palette
|
||||||
import androidx.compose.material.icons.outlined.Share
|
import androidx.compose.material.icons.outlined.Share
|
||||||
import androidx.compose.material.icons.rounded.Close
|
import androidx.compose.material.icons.rounded.Close
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
@ -18,18 +19,24 @@ import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.zIndex
|
import androidx.compose.ui.zIndex
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingPageTonalElevation
|
||||||
import me.ash.reader.ui.component.base.FeedbackIconButton
|
import me.ash.reader.ui.component.base.FeedbackIconButton
|
||||||
import me.ash.reader.ui.ext.share
|
import me.ash.reader.ui.ext.share
|
||||||
|
import me.ash.reader.ui.ext.surfaceColorAtElevation
|
||||||
|
import me.ash.reader.ui.page.common.RouteName
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TopBar(
|
fun TopBar(
|
||||||
|
navController: NavHostController,
|
||||||
isShow: Boolean,
|
isShow: Boolean,
|
||||||
title: String? = "",
|
title: String? = "",
|
||||||
link: String? = "",
|
link: String? = "",
|
||||||
onClose: () -> Unit = {},
|
onClose: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val tonalElevation = LocalReadingPageTonalElevation.current
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -41,7 +48,9 @@ fun TopBar(
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
modifier = Modifier.statusBarsPadding(),
|
modifier = Modifier.statusBarsPadding(),
|
||||||
colors = TopAppBarDefaults.smallTopAppBarColors(
|
colors = TopAppBarDefaults.smallTopAppBarColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
|
||||||
|
elevation = tonalElevation.value.dp
|
||||||
|
),
|
||||||
),
|
),
|
||||||
title = {},
|
title = {},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
@ -54,6 +63,16 @@ fun TopBar(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
|
FeedbackIconButton(
|
||||||
|
modifier = Modifier.size(22.dp),
|
||||||
|
imageVector = Icons.Outlined.Palette,
|
||||||
|
contentDescription = stringResource(R.string.style),
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface
|
||||||
|
) {
|
||||||
|
navController.navigate(RouteName.READING_PAGE_STYLE) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
}
|
||||||
FeedbackIconButton(
|
FeedbackIconButton(
|
||||||
modifier = Modifier.size(20.dp),
|
modifier = Modifier.size(20.dp),
|
||||||
imageVector = Icons.Outlined.Share,
|
imageVector = Icons.Outlined.Share,
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package me.ash.reader.ui.page.home.reading.drawer
|
||||||
|
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material3.Tab
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.ui.component.base.BottomDrawer
|
||||||
|
import me.ash.reader.ui.ext.collectAsStateValue
|
||||||
|
import me.ash.reader.ui.page.home.feeds.drawer.feed.FeedOptionViewModel
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
|
@Composable
|
||||||
|
fun StyleOptionDrawer(
|
||||||
|
feedOptionViewModel: FeedOptionViewModel = hiltViewModel(),
|
||||||
|
content: @Composable () -> Unit = {},
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val view = LocalView.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val feedOptionUiState = feedOptionViewModel.feedOptionUiState.collectAsStateValue()
|
||||||
|
val feed = feedOptionUiState.feed
|
||||||
|
val toastString = stringResource(R.string.rename_toast, feedOptionUiState.newName)
|
||||||
|
|
||||||
|
BackHandler(feedOptionUiState.drawerState.isVisible) {
|
||||||
|
scope.launch {
|
||||||
|
feedOptionUiState.drawerState.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BottomDrawer(
|
||||||
|
drawerState = feedOptionUiState.drawerState,
|
||||||
|
sheetContent = {
|
||||||
|
Info()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Info() {
|
||||||
|
Column(modifier = Modifier.navigationBarsPadding()) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Tab(selected = true, onClick = { /*TODO*/ })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun Prev() {
|
||||||
|
Tab(selected = true, onClick = { /*TODO*/ })
|
||||||
|
}
|
|
@ -140,6 +140,7 @@ fun SettingsPage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,11 +181,15 @@ fun ColorAndStylePage(
|
||||||
) {}
|
) {}
|
||||||
SettingItem(
|
SettingItem(
|
||||||
title = stringResource(R.string.reading_page),
|
title = stringResource(R.string.reading_page),
|
||||||
enable = false,
|
onClick = {
|
||||||
onClick = {},
|
navController.navigate(RouteName.READING_PAGE_STYLE) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ fun DarkThemePage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ fun FeedsPageStylePage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SettingItem(
|
SettingItem(
|
||||||
title = stringResource(R.string.padding_on_both_ends),
|
title = stringResource(R.string.horizontal_padding),
|
||||||
desc = "${filterBarPadding}dp",
|
desc = "${filterBarPadding}dp",
|
||||||
onClick = {
|
onClick = {
|
||||||
filterBarPaddingValue = filterBarPadding
|
filterBarPaddingValue = filterBarPadding
|
||||||
|
@ -197,7 +197,7 @@ fun FeedsPageStylePage(
|
||||||
|
|
||||||
TextFieldDialog(
|
TextFieldDialog(
|
||||||
visible = filterBarPaddingDialogVisible,
|
visible = filterBarPaddingDialogVisible,
|
||||||
title = stringResource(R.string.padding_on_both_ends),
|
title = stringResource(R.string.horizontal_padding),
|
||||||
value = (filterBarPaddingValue ?: "").toString(),
|
value = (filterBarPaddingValue ?: "").toString(),
|
||||||
placeholder = stringResource(R.string.value),
|
placeholder = stringResource(R.string.value),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
|
|
|
@ -218,7 +218,7 @@ fun FlowPageStylePage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SettingItem(
|
SettingItem(
|
||||||
title = stringResource(R.string.padding_on_both_ends),
|
title = stringResource(R.string.horizontal_padding),
|
||||||
desc = "${filterBarPadding}dp",
|
desc = "${filterBarPadding}dp",
|
||||||
onClick = {
|
onClick = {
|
||||||
filterBarPaddingValue = filterBarPadding
|
filterBarPaddingValue = filterBarPadding
|
||||||
|
@ -234,6 +234,7 @@ fun FlowPageStylePage(
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,7 +258,7 @@ fun FlowPageStylePage(
|
||||||
|
|
||||||
TextFieldDialog(
|
TextFieldDialog(
|
||||||
visible = filterBarPaddingDialogVisible,
|
visible = filterBarPaddingDialogVisible,
|
||||||
title = stringResource(R.string.padding_on_both_ends),
|
title = stringResource(R.string.horizontal_padding),
|
||||||
value = (filterBarPaddingValue ?: "").toString(),
|
value = (filterBarPaddingValue ?: "").toString(),
|
||||||
placeholder = stringResource(R.string.value),
|
placeholder = stringResource(R.string.value),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package me.ash.reader.ui.page.settings.color.reading
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.ArrowBack
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.RadioButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.model.preference.LocalReadingDarkTheme
|
||||||
|
import me.ash.reader.data.model.preference.ReadingDarkThemePreference
|
||||||
|
import me.ash.reader.ui.component.base.DisplayText
|
||||||
|
import me.ash.reader.ui.component.base.FeedbackIconButton
|
||||||
|
import me.ash.reader.ui.component.base.RYScaffold
|
||||||
|
import me.ash.reader.ui.page.settings.SettingItem
|
||||||
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ReadingDarkThemePage(
|
||||||
|
navController: NavHostController,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val darkTheme = LocalReadingDarkTheme.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
RYScaffold(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
|
||||||
|
navigationIcon = {
|
||||||
|
FeedbackIconButton(
|
||||||
|
imageVector = Icons.Rounded.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.back),
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface
|
||||||
|
) {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content = {
|
||||||
|
LazyColumn {
|
||||||
|
item {
|
||||||
|
DisplayText(text = stringResource(R.string.dark_theme), desc = "")
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
ReadingDarkThemePreference.values.map {
|
||||||
|
SettingItem(
|
||||||
|
title = it.toDesc(context),
|
||||||
|
onClick = {
|
||||||
|
it.put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RadioButton(selected = it == darkTheme, onClick = {
|
||||||
|
it.put(context, scope)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
package me.ash.reader.ui.page.settings.color.reading
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.ArrowBack
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
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.page.settings.SettingItem
|
||||||
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingImagePage(
|
||||||
|
navController: NavHostController,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val readingTheme = LocalReadingTheme.current
|
||||||
|
val roundedCorners = LocalReadingImageRoundedCorners.current
|
||||||
|
val horizontalPadding = LocalReadingImageHorizontalPadding.current
|
||||||
|
val maximize = LocalReadingImageMaximize.current
|
||||||
|
|
||||||
|
var roundedCornersDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
var horizontalPaddingDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
var roundedCornersValue: Int? by remember { mutableStateOf(roundedCorners) }
|
||||||
|
var horizontalPaddingValue: Int? by remember { mutableStateOf(horizontalPadding) }
|
||||||
|
|
||||||
|
RYScaffold(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
|
||||||
|
navigationIcon = {
|
||||||
|
FeedbackIconButton(
|
||||||
|
imageVector = Icons.Rounded.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.back),
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface
|
||||||
|
) {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content = {
|
||||||
|
LazyColumn {
|
||||||
|
item {
|
||||||
|
DisplayText(text = stringResource(R.string.images), desc = "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview
|
||||||
|
item {
|
||||||
|
// Row(
|
||||||
|
// modifier = Modifier
|
||||||
|
// .fillMaxWidth()
|
||||||
|
// .padding(horizontal = 24.dp)
|
||||||
|
// .clip(RoundedCornerShape(24.dp))
|
||||||
|
// .background(
|
||||||
|
// MaterialTheme.colorScheme.inverseOnSurface
|
||||||
|
// onLight MaterialTheme.colorScheme.surface.copy(0.7f)
|
||||||
|
// )
|
||||||
|
// .clickable { },
|
||||||
|
// horizontalArrangement = Arrangement.Center,
|
||||||
|
// verticalAlignment = Alignment.CenterVertically
|
||||||
|
// ) {
|
||||||
|
// RYAsyncImage(
|
||||||
|
// modifier = Modifier
|
||||||
|
// .fillMaxSize()
|
||||||
|
// .padding(24.dp)
|
||||||
|
// .padding(imageHorizontalPadding().dp)
|
||||||
|
// .clip(imageShape()),
|
||||||
|
// data = "https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDJ8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=800&q=60",
|
||||||
|
// contentDescription = stringResource(R.string.images),
|
||||||
|
// contentScale = ContentScale.Inside,
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Images
|
||||||
|
item {
|
||||||
|
Subtitle(
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
text = stringResource(R.string.images)
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.rounded_corners),
|
||||||
|
desc = "${roundedCorners}dp",
|
||||||
|
onClick = { roundedCornersDialogVisible = true },
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.horizontal_padding),
|
||||||
|
desc = "${horizontalPadding}dp",
|
||||||
|
onClick = { horizontalPaddingDialogVisible = true },
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.maximize),
|
||||||
|
onClick = {
|
||||||
|
(!maximize).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(activated = maximize.value) {
|
||||||
|
(!maximize).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
TextFieldDialog(
|
||||||
|
visible = roundedCornersDialogVisible,
|
||||||
|
title = stringResource(R.string.rounded_corners),
|
||||||
|
value = (roundedCornersValue ?: "").toString(),
|
||||||
|
placeholder = stringResource(R.string.value),
|
||||||
|
onValueChange = {
|
||||||
|
roundedCornersValue = it.filter { it.isDigit() }.toIntOrNull()
|
||||||
|
},
|
||||||
|
onDismissRequest = {
|
||||||
|
roundedCornersDialogVisible = false
|
||||||
|
},
|
||||||
|
onConfirm = {
|
||||||
|
ReadingImageRoundedCornersPreference.put(context, scope, roundedCornersValue ?: 0)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
roundedCornersDialogVisible = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
TextFieldDialog(
|
||||||
|
visible = horizontalPaddingDialogVisible,
|
||||||
|
title = stringResource(R.string.horizontal_padding),
|
||||||
|
value = (horizontalPaddingValue ?: "").toString(),
|
||||||
|
placeholder = stringResource(R.string.value),
|
||||||
|
onValueChange = {
|
||||||
|
horizontalPaddingValue = it.filter { it.isDigit() }.toIntOrNull()
|
||||||
|
},
|
||||||
|
onDismissRequest = {
|
||||||
|
horizontalPaddingDialogVisible = false
|
||||||
|
},
|
||||||
|
onConfirm = {
|
||||||
|
ReadingImageHorizontalPaddingPreference.put(context, scope, horizontalPaddingValue ?: 0)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
horizontalPaddingDialogVisible = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,259 @@
|
||||||
|
package me.ash.reader.ui.page.settings.color.reading
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.horizontalScroll
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Image
|
||||||
|
import androidx.compose.material.icons.outlined.Movie
|
||||||
|
import androidx.compose.material.icons.rounded.ArrowBack
|
||||||
|
import androidx.compose.material.icons.rounded.Segment
|
||||||
|
import androidx.compose.material.icons.rounded.Title
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
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.ReadingThemePrev
|
||||||
|
import me.ash.reader.ui.component.base.*
|
||||||
|
import me.ash.reader.ui.page.common.RouteName
|
||||||
|
import me.ash.reader.ui.page.settings.SettingItem
|
||||||
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingStylePage(
|
||||||
|
navController: NavHostController,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val readingTheme = LocalReadingTheme.current
|
||||||
|
val darkTheme = LocalReadingDarkTheme.current
|
||||||
|
val darkThemeNot = !darkTheme
|
||||||
|
val tonalElevation = LocalReadingPageTonalElevation.current
|
||||||
|
val fonts = LocalReadingFonts.current
|
||||||
|
val autoHideToolbar = LocalReadingAutoHideToolbar.current
|
||||||
|
|
||||||
|
var tonalElevationDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
var fontsDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
RYScaffold(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
|
||||||
|
navigationIcon = {
|
||||||
|
FeedbackIconButton(
|
||||||
|
imageVector = Icons.Rounded.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.back),
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface
|
||||||
|
) {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content = {
|
||||||
|
LazyColumn {
|
||||||
|
item {
|
||||||
|
DisplayText(text = stringResource(R.string.reading_page), desc = "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview
|
||||||
|
item {
|
||||||
|
Row(modifier = Modifier.horizontalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
ReadingThemePreference.values.map {
|
||||||
|
if (readingTheme == ReadingThemePreference.Custom || it != ReadingThemePreference.Custom) {
|
||||||
|
ReadingThemePrev(selected = readingTheme, theme = it) {
|
||||||
|
it.put(context, scope)
|
||||||
|
it.applyTheme(context, scope)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Spacer(modifier = Modifier.width(150.dp))
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.width((24 - 8).dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 24.dp)
|
||||||
|
.clip(RoundedCornerShape(24.dp))
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.inverseOnSurface
|
||||||
|
onLight MaterialTheme.colorScheme.surface.copy(0.7f)
|
||||||
|
)
|
||||||
|
.clickable { },
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// General
|
||||||
|
item {
|
||||||
|
Subtitle(
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
text = stringResource(R.string.general)
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.reading_fonts),
|
||||||
|
desc = fonts.toDesc(context),
|
||||||
|
onClick = { fontsDialogVisible = true },
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.dark_reading_theme),
|
||||||
|
desc = darkTheme.toDesc(context),
|
||||||
|
separatedActions = true,
|
||||||
|
onClick = {
|
||||||
|
navController.navigate(RouteName.READING_DARK_THEME) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(
|
||||||
|
activated = darkTheme.isDarkTheme()
|
||||||
|
) {
|
||||||
|
darkThemeNot.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.bionic_reading),
|
||||||
|
separatedActions = true,
|
||||||
|
enable = false,
|
||||||
|
onClick = {
|
||||||
|
// (!articleListDesc).put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(
|
||||||
|
activated = false,
|
||||||
|
enable = false,
|
||||||
|
) {
|
||||||
|
// (!articleListDesc).put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.auto_hide_toolbars),
|
||||||
|
onClick = {
|
||||||
|
(!autoHideToolbar).put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(activated = autoHideToolbar.value) {
|
||||||
|
(!autoHideToolbar).put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.rearrange_buttons),
|
||||||
|
enable = false,
|
||||||
|
onClick = {},
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.tonal_elevation),
|
||||||
|
desc = "${tonalElevation.value}dp",
|
||||||
|
onClick = {
|
||||||
|
tonalElevationDialogVisible = true
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advanced
|
||||||
|
item {
|
||||||
|
Subtitle(
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
text = stringResource(R.string.advanced)
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.title),
|
||||||
|
desc = stringResource(R.string.title_desc),
|
||||||
|
icon = Icons.Rounded.Title,
|
||||||
|
onClick = {
|
||||||
|
navController.navigate(RouteName.READING_PAGE_TITLE) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.text),
|
||||||
|
desc = stringResource(R.string.text_desc),
|
||||||
|
icon = Icons.Rounded.Segment,
|
||||||
|
onClick = {
|
||||||
|
navController.navigate(RouteName.READING_PAGE_TEXT) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.images),
|
||||||
|
desc = stringResource(R.string.images_desc),
|
||||||
|
icon = Icons.Outlined.Image,
|
||||||
|
onClick = {
|
||||||
|
navController.navigate(RouteName.READING_PAGE_IMAGE) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.videos),
|
||||||
|
desc = stringResource(R.string.videos_desc),
|
||||||
|
icon = Icons.Outlined.Movie,
|
||||||
|
enable = false,
|
||||||
|
onClick = {
|
||||||
|
// navController.navigate(RouteName.READING_PAGE_VIDEO) {
|
||||||
|
// launchSingleTop = true
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
RadioDialog(
|
||||||
|
visible = tonalElevationDialogVisible,
|
||||||
|
title = stringResource(R.string.tonal_elevation),
|
||||||
|
options = ReadingPageTonalElevationPreference.values.map {
|
||||||
|
RadioDialogOption(
|
||||||
|
text = it.toDesc(context),
|
||||||
|
selected = it == tonalElevation,
|
||||||
|
) {
|
||||||
|
it.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
tonalElevationDialogVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
RadioDialog(
|
||||||
|
visible = fontsDialogVisible,
|
||||||
|
title = stringResource(R.string.reading_fonts),
|
||||||
|
options = ReadingFontsPreference.values.map {
|
||||||
|
RadioDialogOption(
|
||||||
|
text = it.toDesc(context),
|
||||||
|
style = TextStyle(fontFamily = it.asFontFamily()),
|
||||||
|
selected = it == fonts,
|
||||||
|
) {
|
||||||
|
it.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
fontsDialogVisible = false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,202 @@
|
||||||
|
package me.ash.reader.ui.page.settings.color.reading
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.ArrowBack
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
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.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.page.settings.SettingItem
|
||||||
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingTextPage(
|
||||||
|
navController: NavHostController,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val readingTheme = LocalReadingTheme.current
|
||||||
|
val fontSize = LocalReadingTextFontSize.current
|
||||||
|
val letterSpacing = LocalReadingLetterSpacing.current
|
||||||
|
val horizontalPadding = LocalReadingTextHorizontalPadding.current
|
||||||
|
val align = LocalReadingTextAlign.current
|
||||||
|
val bold = LocalReadingTextBold.current
|
||||||
|
|
||||||
|
var fontSizeDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
var letterSpacingDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
var horizontalPaddingDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
var alignDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
var fontSizeValue: Int? by remember { mutableStateOf(fontSize) }
|
||||||
|
var letterSpacingValue: String? by remember { mutableStateOf(letterSpacing.toString()) }
|
||||||
|
var horizontalPaddingValue: Int? by remember { mutableStateOf(horizontalPadding) }
|
||||||
|
|
||||||
|
RYScaffold(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
|
||||||
|
navigationIcon = {
|
||||||
|
FeedbackIconButton(
|
||||||
|
imageVector = Icons.Rounded.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.back),
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface
|
||||||
|
) {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content = {
|
||||||
|
LazyColumn {
|
||||||
|
item {
|
||||||
|
DisplayText(text = stringResource(R.string.text), desc = "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 24.dp)
|
||||||
|
.clip(RoundedCornerShape(24.dp))
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.inverseOnSurface
|
||||||
|
onLight MaterialTheme.colorScheme.surface.copy(0.7f)
|
||||||
|
)
|
||||||
|
.clickable { },
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
TitleAndTextPreview()
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text
|
||||||
|
item {
|
||||||
|
Subtitle(
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
text = stringResource(R.string.text)
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.font_size),
|
||||||
|
desc = "${fontSize}sp",
|
||||||
|
onClick = { fontSizeDialogVisible = true },
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.bold),
|
||||||
|
onClick = {
|
||||||
|
(!bold).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(activated = bold.value) {
|
||||||
|
(!bold).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.letter_spacing),
|
||||||
|
desc = "${letterSpacing}sp",
|
||||||
|
onClick = { letterSpacingDialogVisible = true },
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.horizontal_padding),
|
||||||
|
desc = "${horizontalPadding}dp",
|
||||||
|
onClick = { horizontalPaddingDialogVisible = true },
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.alignment),
|
||||||
|
desc = align.toDesc(context),
|
||||||
|
onClick = { alignDialogVisible = true },
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
TextFieldDialog(
|
||||||
|
visible = fontSizeDialogVisible,
|
||||||
|
title = stringResource(R.string.font_size),
|
||||||
|
value = (fontSizeValue ?: "").toString(),
|
||||||
|
placeholder = stringResource(R.string.value),
|
||||||
|
onValueChange = {
|
||||||
|
fontSizeValue = it.filter { it.isDigit() }.toIntOrNull()
|
||||||
|
},
|
||||||
|
onDismissRequest = {
|
||||||
|
fontSizeDialogVisible = false
|
||||||
|
},
|
||||||
|
onConfirm = {
|
||||||
|
ReadingTextFontSizePreference.put(context, scope, fontSizeValue ?: 0)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
fontSizeDialogVisible = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
TextFieldDialog(
|
||||||
|
visible = letterSpacingDialogVisible,
|
||||||
|
title = stringResource(R.string.letter_spacing),
|
||||||
|
value = (letterSpacingValue ?: "").toString(),
|
||||||
|
placeholder = stringResource(R.string.value),
|
||||||
|
onValueChange = {
|
||||||
|
letterSpacingValue = it
|
||||||
|
},
|
||||||
|
onDismissRequest = {
|
||||||
|
letterSpacingDialogVisible = false
|
||||||
|
},
|
||||||
|
onConfirm = {
|
||||||
|
ReadingLetterSpacingPreference.put(context, scope, letterSpacingValue?.toDoubleOrNull() ?: 0.0)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
letterSpacingDialogVisible = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
TextFieldDialog(
|
||||||
|
visible = horizontalPaddingDialogVisible,
|
||||||
|
title = stringResource(R.string.horizontal_padding),
|
||||||
|
value = (horizontalPaddingValue ?: "").toString(),
|
||||||
|
placeholder = stringResource(R.string.value),
|
||||||
|
onValueChange = {
|
||||||
|
horizontalPaddingValue = it.filter { it.isDigit() }.toIntOrNull()
|
||||||
|
},
|
||||||
|
onDismissRequest = {
|
||||||
|
horizontalPaddingDialogVisible = false
|
||||||
|
},
|
||||||
|
onConfirm = {
|
||||||
|
ReadingTextHorizontalPaddingPreference.put(context, scope, horizontalPaddingValue ?: 0)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
horizontalPaddingDialogVisible = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
RadioDialog(
|
||||||
|
visible = alignDialogVisible,
|
||||||
|
title = stringResource(R.string.alignment),
|
||||||
|
options = ReadingTextAlignPreference.values.map {
|
||||||
|
RadioDialogOption(
|
||||||
|
text = it.toDesc(context),
|
||||||
|
selected = it == align,
|
||||||
|
) {
|
||||||
|
it.put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
alignDialogVisible = false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
package me.ash.reader.ui.page.settings.color.reading
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.ArrowBack
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
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.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.page.settings.SettingItem
|
||||||
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingTitlePage(
|
||||||
|
navController: NavHostController,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val titleBold = LocalReadingTitleBold.current
|
||||||
|
val subtitleBold = LocalReadingSubheadBold.current
|
||||||
|
val titleAlign = LocalReadingTitleAlign.current
|
||||||
|
val subtitleAlign = LocalReadingSubheadAlign.current
|
||||||
|
val titleUpperCase = LocalReadingTitleUpperCase.current
|
||||||
|
val subheadUpperCase = LocalReadingSubheadUpperCase.current
|
||||||
|
|
||||||
|
var titleAlignDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
var subtitleAlignDialogVisible by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
RYScaffold(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
|
||||||
|
navigationIcon = {
|
||||||
|
FeedbackIconButton(
|
||||||
|
imageVector = Icons.Rounded.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.back),
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface
|
||||||
|
) {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content = {
|
||||||
|
LazyColumn {
|
||||||
|
item {
|
||||||
|
DisplayText(text = stringResource(R.string.title), desc = "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 24.dp)
|
||||||
|
.clip(RoundedCornerShape(24.dp))
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.inverseOnSurface
|
||||||
|
onLight MaterialTheme.colorScheme.surface.copy(0.7f)
|
||||||
|
)
|
||||||
|
.clickable { },
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
TitleAndTextPreview()
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Title
|
||||||
|
item {
|
||||||
|
Subtitle(
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
text = stringResource(R.string.title)
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.bold),
|
||||||
|
onClick = {
|
||||||
|
(!titleBold).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(activated = titleBold.value) {
|
||||||
|
(!titleBold).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.upper_case),
|
||||||
|
onClick = {
|
||||||
|
(!titleUpperCase).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(activated = titleUpperCase.value) {
|
||||||
|
(!titleUpperCase).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.alignment),
|
||||||
|
desc = titleAlign.toDesc(context),
|
||||||
|
onClick = { titleAlignDialogVisible = true },
|
||||||
|
) {}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subhead
|
||||||
|
item {
|
||||||
|
Subtitle(
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
text = stringResource(R.string.subhead)
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.bold),
|
||||||
|
onClick = {
|
||||||
|
(!subtitleBold).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(activated = subtitleBold.value) {
|
||||||
|
(!subtitleBold).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.upper_case),
|
||||||
|
onClick = {
|
||||||
|
(!subheadUpperCase).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
RYSwitch(activated = subheadUpperCase.value) {
|
||||||
|
(!subheadUpperCase).put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.alignment),
|
||||||
|
desc = subtitleAlign.toDesc(context),
|
||||||
|
enable = false,
|
||||||
|
onClick = {
|
||||||
|
// subtitleAlignDialogVisible = true
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
RadioDialog(
|
||||||
|
visible = titleAlignDialogVisible,
|
||||||
|
title = stringResource(R.string.alignment),
|
||||||
|
options = ReadingTitleAlignPreference.values.map {
|
||||||
|
RadioDialogOption(
|
||||||
|
text = it.toDesc(context),
|
||||||
|
selected = it == titleAlign,
|
||||||
|
) {
|
||||||
|
it.put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
titleAlignDialogVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
RadioDialog(
|
||||||
|
visible = subtitleAlignDialogVisible,
|
||||||
|
title = stringResource(R.string.alignment),
|
||||||
|
options = ReadingSubheadAlignPreference.values.map {
|
||||||
|
RadioDialogOption(
|
||||||
|
text = it.toDesc(context),
|
||||||
|
selected = it == subtitleAlign,
|
||||||
|
) {
|
||||||
|
it.put(context, scope)
|
||||||
|
ReadingThemePreference.Custom.put(context, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
subtitleAlignDialogVisible = false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
package me.ash.reader.ui.page.settings.color.reading
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.horizontalScroll
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.ArrowBack
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
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.unit.dp
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.ui.component.base.DisplayText
|
||||||
|
import me.ash.reader.ui.component.base.FeedbackIconButton
|
||||||
|
import me.ash.reader.ui.component.base.RYScaffold
|
||||||
|
import me.ash.reader.ui.component.base.Subtitle
|
||||||
|
import me.ash.reader.ui.page.settings.SettingItem
|
||||||
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingVideoPage(
|
||||||
|
navController: NavHostController,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
RYScaffold(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
|
||||||
|
navigationIcon = {
|
||||||
|
FeedbackIconButton(
|
||||||
|
imageVector = Icons.Rounded.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.back),
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface
|
||||||
|
) {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
content = {
|
||||||
|
LazyColumn {
|
||||||
|
item {
|
||||||
|
DisplayText(text = stringResource(R.string.videos), desc = "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview
|
||||||
|
item {
|
||||||
|
Row(modifier = Modifier.horizontalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 24.dp)
|
||||||
|
.clip(RoundedCornerShape(24.dp))
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.inverseOnSurface
|
||||||
|
onLight MaterialTheme.colorScheme.surface.copy(0.7f)
|
||||||
|
)
|
||||||
|
.clickable { },
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Videos
|
||||||
|
item {
|
||||||
|
Subtitle(
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
text = stringResource(R.string.videos)
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.rounded_corners),
|
||||||
|
onClick = {},
|
||||||
|
) {}
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.horizontal_padding),
|
||||||
|
desc = "dp",
|
||||||
|
onClick = {},
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package me.ash.reader.ui.page.settings.color.reading
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.model.preference.*
|
||||||
|
import me.ash.reader.ui.component.reader.bodyStyle
|
||||||
|
import me.ash.reader.ui.component.reader.h3Style
|
||||||
|
import me.ash.reader.ui.component.reader.textHorizontalPadding
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TitleAndTextPreview() {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val titleBold = LocalReadingTitleBold.current
|
||||||
|
val subtitleBold = LocalReadingSubheadBold.current
|
||||||
|
val titleUpperCase = LocalReadingTitleUpperCase.current
|
||||||
|
val subheadUpperCase = LocalReadingSubheadUpperCase.current
|
||||||
|
val titleAlign = LocalReadingTitleAlign.current
|
||||||
|
val subtitleAlign = LocalReadingSubheadAlign.current
|
||||||
|
|
||||||
|
|
||||||
|
val titleUpperCaseString by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
context.getString(R.string.title).uppercase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val subheadUpperCaseString by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
context.getString(R.string.subhead).uppercase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column(modifier = Modifier.padding(24.dp)) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = textHorizontalPadding().dp),
|
||||||
|
text = if (titleUpperCase.value) titleUpperCaseString else stringResource(id = R.string.title),
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
style = MaterialTheme.typography.headlineLarge.copy(
|
||||||
|
fontFamily = LocalReadingFonts.current.asFontFamily(isDisplay = true),
|
||||||
|
fontWeight = if (titleBold.value) FontWeight.SemiBold else FontWeight.Normal,
|
||||||
|
),
|
||||||
|
textAlign = titleAlign.toTextAlign(),
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
Text(
|
||||||
|
text = if (subheadUpperCase.value) subheadUpperCaseString else stringResource(id = R.string.subhead),
|
||||||
|
style = h3Style().copy(textAlign = bodyStyle().textAlign),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = textHorizontalPadding().dp)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.preview_article_desc),
|
||||||
|
style = bodyStyle(),
|
||||||
|
modifier = Modifier.padding(horizontal = textHorizontalPadding().dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,6 +69,7 @@ fun InteractionPage(
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,7 @@ fun LanguagesPage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@ val Shapes = Shapes(
|
||||||
@Stable
|
@Stable
|
||||||
val Shape20 = RoundedCornerShape(20.0.dp)
|
val Shape20 = RoundedCornerShape(20.0.dp)
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
val Shape24 = RoundedCornerShape(24.0.dp)
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
val Shape32 = RoundedCornerShape(32.0.dp)
|
val Shape32 = RoundedCornerShape(32.0.dp)
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.darkColorScheme
|
import androidx.compose.material3.darkColorScheme
|
||||||
import androidx.compose.material3.lightColorScheme
|
import androidx.compose.material3.lightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import me.ash.reader.data.model.preference.LocalAmoledDarkTheme
|
import me.ash.reader.data.model.preference.LocalAmoledDarkTheme
|
||||||
|
@ -80,7 +81,9 @@ infix fun Color.onLight(lightColor: Color): Color =
|
||||||
infix fun Color.onDark(darkColor: Color): Color =
|
infix fun Color.onDark(darkColor: Color): Color =
|
||||||
if (LocalDarkTheme.current.isDarkTheme()) darkColor else this
|
if (LocalDarkTheme.current.isDarkTheme()) darkColor else this
|
||||||
|
|
||||||
|
@Stable
|
||||||
@Composable
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
infix fun Color.alwaysLight(isAlways: Boolean): Color {
|
infix fun Color.alwaysLight(isAlways: Boolean): Color {
|
||||||
val colorScheme = MaterialTheme.colorScheme
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
return if (isAlways && LocalDarkTheme.current.isDarkTheme()) {
|
return if (isAlways && LocalDarkTheme.current.isDarkTheme()) {
|
||||||
|
@ -120,6 +123,48 @@ infix fun Color.alwaysLight(isAlways: Boolean): Color {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
infix fun Color.alwaysDark(isAlways: Boolean): Color {
|
||||||
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
|
return if (isAlways && !LocalDarkTheme.current.isDarkTheme()) {
|
||||||
|
when (this) {
|
||||||
|
colorScheme.primary -> colorScheme.onPrimary
|
||||||
|
colorScheme.secondary -> colorScheme.onSecondary
|
||||||
|
colorScheme.tertiary -> colorScheme.onTertiary
|
||||||
|
colorScheme.background -> colorScheme.onBackground
|
||||||
|
colorScheme.error -> colorScheme.onError
|
||||||
|
colorScheme.surface -> colorScheme.onSurface
|
||||||
|
colorScheme.surfaceVariant -> colorScheme.onSurfaceVariant
|
||||||
|
colorScheme.error -> colorScheme.onError
|
||||||
|
colorScheme.primaryContainer -> colorScheme.onPrimaryContainer
|
||||||
|
colorScheme.secondaryContainer -> colorScheme.onSecondaryContainer
|
||||||
|
colorScheme.tertiaryContainer -> colorScheme.onTertiaryContainer
|
||||||
|
colorScheme.errorContainer -> colorScheme.onErrorContainer
|
||||||
|
colorScheme.inverseSurface -> colorScheme.inverseOnSurface
|
||||||
|
|
||||||
|
colorScheme.onPrimary -> colorScheme.primary
|
||||||
|
colorScheme.onSecondary -> colorScheme.secondary
|
||||||
|
colorScheme.onTertiary -> colorScheme.tertiary
|
||||||
|
colorScheme.onBackground -> colorScheme.background
|
||||||
|
colorScheme.onError -> colorScheme.error
|
||||||
|
colorScheme.onSurface -> colorScheme.surface
|
||||||
|
colorScheme.onSurfaceVariant -> colorScheme.surfaceVariant
|
||||||
|
colorScheme.onError -> colorScheme.error
|
||||||
|
colorScheme.onPrimaryContainer -> colorScheme.primaryContainer
|
||||||
|
colorScheme.onSecondaryContainer -> colorScheme.secondaryContainer
|
||||||
|
colorScheme.onTertiaryContainer -> colorScheme.tertiaryContainer
|
||||||
|
colorScheme.onErrorContainer -> colorScheme.errorContainer
|
||||||
|
colorScheme.inverseOnSurface -> colorScheme.inverseSurface
|
||||||
|
|
||||||
|
else -> Color.Unspecified
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun String.checkColorHex(): String? {
|
fun String.checkColorHex(): String? {
|
||||||
var s = this.trim()
|
var s = this.trim()
|
||||||
if (s.length > 6) {
|
if (s.length > 6) {
|
||||||
|
|
|
@ -239,7 +239,7 @@
|
||||||
<string name="other">Ostatní</string>
|
<string name="other">Ostatní</string>
|
||||||
<string name="amoled_dark_theme">Tmavé téma AMOLED</string>
|
<string name="amoled_dark_theme">Tmavé téma AMOLED</string>
|
||||||
<string name="tonal_elevation">Zvýraznění tónů</string>
|
<string name="tonal_elevation">Zvýraznění tónů</string>
|
||||||
<string name="fonts">Písma</string>
|
<string name="reading_fonts">Přečtení písma</string>
|
||||||
<string name="basic_fonts">Základní písma</string>
|
<string name="basic_fonts">Základní písma</string>
|
||||||
<string name="feeds_page">Stránka se zdroji</string>
|
<string name="feeds_page">Stránka se zdroji</string>
|
||||||
<string name="flow_page">Stránka Flow</string>
|
<string name="flow_page">Stránka Flow</string>
|
||||||
|
@ -263,7 +263,7 @@
|
||||||
<string name="preview_article_desc">Blázen je osmým a závěrečným dílem série Pán záhad, jehož autorem je sépie, která se ráda potápí.</string>
|
<string name="preview_article_desc">Blázen je osmým a závěrečným dílem série Pán záhad, jehož autorem je sépie, která se ráda potápí.</string>
|
||||||
<string name="preview_feed_name">Reddit</string>
|
<string name="preview_feed_name">Reddit</string>
|
||||||
<string name="value">value</string>
|
<string name="value">value</string>
|
||||||
<string name="padding_on_both_ends">Odsazení na obou koncích</string>
|
<string name="horizontal_padding">Horizontální polstrování</string>
|
||||||
<string name="article_date">Čas zveřejnění článku</string>
|
<string name="article_date">Čas zveřejnění článku</string>
|
||||||
<string name="article_desc">Popis článku</string>
|
<string name="article_desc">Popis článku</string>
|
||||||
<string name="article_images">Obrázky článku</string>
|
<string name="article_images">Obrázky článku</string>
|
||||||
|
@ -286,4 +286,33 @@
|
||||||
<string name="tips_group_list_tonal_elevation">Zvýšení tónu seznamu skupin je dostupné pouze ve světlém režimu.</string>
|
<string name="tips_group_list_tonal_elevation">Zvýšení tónu seznamu skupin je dostupné pouze ve světlém režimu.</string>
|
||||||
<string name="share">Sdílet</string>
|
<string name="share">Sdílet</string>
|
||||||
<string name="touch_to_play_video">Klepněte pro přehráníé videa</string>
|
<string name="touch_to_play_video">Klepněte pro přehráníé videa</string>
|
||||||
|
<string name="text">Text</string>
|
||||||
|
<string name="font_size">Font size</string>
|
||||||
|
<string name="letter_spacing">Letter spacing</string>
|
||||||
|
<string name="line_spacing">Line spacing</string>
|
||||||
|
<string name="alignment">Alignment</string>
|
||||||
|
<string name="general">General</string>
|
||||||
|
<string name="auto_hide_toolbars">Auto hide toolbars</string>
|
||||||
|
<string name="rearrange_buttons">Rearrange buttons</string>
|
||||||
|
<string name="bionic_reading">Bionic Reading</string>
|
||||||
|
<string name="images">Images</string>
|
||||||
|
<string name="rounded_corners">Rounded corners</string>
|
||||||
|
<string name="videos">Videos</string>
|
||||||
|
<string name="align_left">Align left</string>
|
||||||
|
<string name="align_right">Align right</string>
|
||||||
|
<string name="center_text">Center text</string>
|
||||||
|
<string name="justify">Justify</string>
|
||||||
|
<string name="external_fonts">External fonts</string>
|
||||||
|
<string name="title">Title</string>
|
||||||
|
<string name="bold">Bold</string>
|
||||||
|
<string name="upper_case">Upper case</string>
|
||||||
|
<string name="subhead">Subhead</string>
|
||||||
|
<string name="use_app_theme">Use app theme</string>
|
||||||
|
<string name="advanced">Advanced</string>
|
||||||
|
<string name="dark_reading_theme">Dark reading theme</string>
|
||||||
|
<string name="title_desc">Bold, upper case, alignment</string>
|
||||||
|
<string name="text_desc">Font size, letter spacing, alignment</string>
|
||||||
|
<string name="images_desc">Rounded corners, horizontal padding</string>
|
||||||
|
<string name="videos_desc">Rounded corners, horizontal padding</string>
|
||||||
|
<string name="maximize">Maximize</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
<string name="interaction">Interaktion</string>
|
<string name="interaction">Interaktion</string>
|
||||||
<string name="interaction_desc">Beim Start, haptisches Feedback</string>
|
<string name="interaction_desc">Beim Start, haptisches Feedback</string>
|
||||||
<string name="languages">Sprachen</string>
|
<string name="languages">Sprachen</string>
|
||||||
<string name="languages_desc">English, Deutsch, mehr</string>
|
<string name="languages_desc">Deutsch, Englisch, andere</string>
|
||||||
<string name="help_translate">Hilf uns beim Übersetzen</string>
|
<string name="help_translate">Hilf uns beim Übersetzen</string>
|
||||||
<string name="use_device_languages">Gerätesprache verwenden</string>
|
<string name="use_device_languages">Gerätesprache verwenden</string>
|
||||||
<string name="tips_and_support">Tipps & Support</string>
|
<string name="tips_and_support">Tipps & Support</string>
|
||||||
|
@ -233,7 +233,7 @@
|
||||||
<string name="other">Sonstiges</string>
|
<string name="other">Sonstiges</string>
|
||||||
<string name="amoled_dark_theme">AMOLED Dunkles Design</string>
|
<string name="amoled_dark_theme">AMOLED Dunkles Design</string>
|
||||||
<string name="tonal_elevation">Farbliches Hervorheben</string>
|
<string name="tonal_elevation">Farbliches Hervorheben</string>
|
||||||
<string name="fonts">Schriftarten</string>
|
<string name="reading_fonts">Leseschriftarten</string>
|
||||||
<string name="basic_fonts">Grundschriftarten</string>
|
<string name="basic_fonts">Grundschriftarten</string>
|
||||||
<string name="feeds_page">Feeds Seite</string>
|
<string name="feeds_page">Feeds Seite</string>
|
||||||
<string name="flow_page">Flow Seite</string>
|
<string name="flow_page">Flow Seite</string>
|
||||||
|
@ -257,7 +257,7 @@
|
||||||
<string name="preview_article_desc">The Fool ist der achte und letzte Band der Lord of the Mysteries Reihe, geschrieben von Cuttlefish That Loves Diving.</string>
|
<string name="preview_article_desc">The Fool ist der achte und letzte Band der Lord of the Mysteries Reihe, geschrieben von Cuttlefish That Loves Diving.</string>
|
||||||
<string name="preview_feed_name">Reddit</string>
|
<string name="preview_feed_name">Reddit</string>
|
||||||
<string name="value">Wert</string>
|
<string name="value">Wert</string>
|
||||||
<string name="padding_on_both_ends">Rand an beiden Enden</string>
|
<string name="horizontal_padding">Horizontaler Rand</string>
|
||||||
<string name="article_date">Artikel Veröffentlichungszeit</string>
|
<string name="article_date">Artikel Veröffentlichungszeit</string>
|
||||||
<string name="article_desc">Artikel Beschreibungen</string>
|
<string name="article_desc">Artikel Beschreibungen</string>
|
||||||
<string name="article_images">Artikel Bilder</string>
|
<string name="article_images">Artikel Bilder</string>
|
||||||
|
@ -278,6 +278,35 @@
|
||||||
<string name="tips_top_bar_tonal_elevation">Das farbliche Hervorheben der oberen Leiste ist nur beim Scrollen verfügbar.</string>
|
<string name="tips_top_bar_tonal_elevation">Das farbliche Hervorheben der oberen Leiste ist nur beim Scrollen verfügbar.</string>
|
||||||
<string name="tips_article_list_tonal_elevation">Das farbliche Hervorheben der Artikelliste ist nur für das helle Design verfügbar.</string>
|
<string name="tips_article_list_tonal_elevation">Das farbliche Hervorheben der Artikelliste ist nur für das helle Design verfügbar.</string>
|
||||||
<string name="tips_group_list_tonal_elevation">Das farbliche Hervorheben der Gruppenliste ist nur für das helle Design verfügbar.</string>
|
<string name="tips_group_list_tonal_elevation">Das farbliche Hervorheben der Gruppenliste ist nur für das helle Design verfügbar.</string>
|
||||||
<string name="share">Aktie</string>
|
<string name="share">Teilen</string>
|
||||||
<string name="touch_to_play_video">Berühren, um Video abzuspielen</string>
|
<string name="touch_to_play_video">Berühren, um Video abzuspielen</string>
|
||||||
|
<string name="text">Text</string>
|
||||||
|
<string name="font_size">Schriftgröße</string>
|
||||||
|
<string name="letter_spacing">Zeichenabstand</string>
|
||||||
|
<string name="line_spacing">Zeilenabstand</string>
|
||||||
|
<string name="alignment">Ausrichtung</string>
|
||||||
|
<string name="general">Allgemein</string>
|
||||||
|
<string name="auto_hide_toolbars">Leisten automatisch ausblenden</string>
|
||||||
|
<string name="rearrange_buttons">Schaltflächen umpositionieren</string>
|
||||||
|
<string name="bionic_reading">Bionic Reading</string>
|
||||||
|
<string name="images">Bilder</string>
|
||||||
|
<string name="rounded_corners">Abgerundete Ecken</string>
|
||||||
|
<string name="videos">Videos</string>
|
||||||
|
<string name="align_left">Linksbündig</string>
|
||||||
|
<string name="align_right">Rechtsbündig</string>
|
||||||
|
<string name="center_text">Zentriert</string>
|
||||||
|
<string name="justify">Blocksatz</string>
|
||||||
|
<string name="external_fonts">Externe Schriftart</string>
|
||||||
|
<string name="title">Titel</string>
|
||||||
|
<string name="bold">Fettgedruckt</string>
|
||||||
|
<string name="upper_case">Großbuchstaben</string>
|
||||||
|
<string name="subhead">Untertitel</string>
|
||||||
|
<string name="use_app_theme">Appdesign verwenden</string>
|
||||||
|
<string name="advanced">Erweitert</string>
|
||||||
|
<string name="dark_reading_theme">Dunkles Lesedesign</string>
|
||||||
|
<string name="title_desc">Fettgedruckt, Großbuchstaben, Ausrichtung</string>
|
||||||
|
<string name="text_desc">Schriftgröße, Zeichenabstand, Ausrichtung</string>
|
||||||
|
<string name="images_desc">Abgerundete Ecken, Horizontaler Rand</string>
|
||||||
|
<string name="videos_desc">Abgerundete Ecken, Horizontaler Rand</string>
|
||||||
|
<string name="maximize">Maximieren</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -236,7 +236,7 @@
|
||||||
<string name="other">Autres options</string>
|
<string name="other">Autres options</string>
|
||||||
<string name="amoled_dark_theme">Thème sombre AMOLED</string>
|
<string name="amoled_dark_theme">Thème sombre AMOLED</string>
|
||||||
<string name="tonal_elevation">Intensité</string>
|
<string name="tonal_elevation">Intensité</string>
|
||||||
<string name="fonts">Polices</string>
|
<string name="reading_fonts">Polices de lecture</string>
|
||||||
<string name="basic_fonts">Polices de base</string>
|
<string name="basic_fonts">Polices de base</string>
|
||||||
<string name="feeds_page">Page des flux</string>
|
<string name="feeds_page">Page des flux</string>
|
||||||
<string name="flow_page">Page des articles</string>
|
<string name="flow_page">Page des articles</string>
|
||||||
|
@ -260,7 +260,7 @@
|
||||||
<string name="preview_article_desc">Le Fou est le huitième et dernier volume de la série Le Seigneur des Mystères écrite par Cuttlefish That Loves Diving.</string>
|
<string name="preview_article_desc">Le Fou est le huitième et dernier volume de la série Le Seigneur des Mystères écrite par Cuttlefish That Loves Diving.</string>
|
||||||
<string name="preview_feed_name">Reddit</string>
|
<string name="preview_feed_name">Reddit</string>
|
||||||
<string name="value">Valeur</string>
|
<string name="value">Valeur</string>
|
||||||
<string name="padding_on_both_ends">Espacement des deux côtés</string>
|
<string name="horizontal_padding">Rembourrage Horizontal</string>
|
||||||
<string name="article_date">Heure de publication des articles</string>
|
<string name="article_date">Heure de publication des articles</string>
|
||||||
<string name="article_desc">Descriptions des articles</string>
|
<string name="article_desc">Descriptions des articles</string>
|
||||||
<string name="article_images">Images des articles</string>
|
<string name="article_images">Images des articles</string>
|
||||||
|
@ -283,4 +283,33 @@
|
||||||
<string name="tips_group_list_tonal_elevation">L\'intensité de la liste des groupes est uniquement disponible pour le thème clair.</string>
|
<string name="tips_group_list_tonal_elevation">L\'intensité de la liste des groupes est uniquement disponible pour le thème clair.</string>
|
||||||
<string name="share">Partager</string>
|
<string name="share">Partager</string>
|
||||||
<string name="touch_to_play_video">Appuyer pour lancer la lecture</string>
|
<string name="touch_to_play_video">Appuyer pour lancer la lecture</string>
|
||||||
|
<string name="text">Text</string>
|
||||||
|
<string name="font_size">Font size</string>
|
||||||
|
<string name="letter_spacing">Letter spacing</string>
|
||||||
|
<string name="line_spacing">Line spacing</string>
|
||||||
|
<string name="alignment">Alignment</string>
|
||||||
|
<string name="general">General</string>
|
||||||
|
<string name="auto_hide_toolbars">Auto hide toolbars</string>
|
||||||
|
<string name="rearrange_buttons">Rearrange buttons</string>
|
||||||
|
<string name="bionic_reading">Bionic Reading</string>
|
||||||
|
<string name="images">Images</string>
|
||||||
|
<string name="rounded_corners">Rounded corners</string>
|
||||||
|
<string name="videos">Videos</string>
|
||||||
|
<string name="align_left">Align left</string>
|
||||||
|
<string name="align_right">Align right</string>
|
||||||
|
<string name="center_text">Center text</string>
|
||||||
|
<string name="justify">Justify</string>
|
||||||
|
<string name="external_fonts">External fonts</string>
|
||||||
|
<string name="title">Title</string>
|
||||||
|
<string name="bold">Bold</string>
|
||||||
|
<string name="upper_case">Upper case</string>
|
||||||
|
<string name="subhead">Subhead</string>
|
||||||
|
<string name="use_app_theme">Use app theme</string>
|
||||||
|
<string name="advanced">Advanced</string>
|
||||||
|
<string name="dark_reading_theme">Dark reading theme</string>
|
||||||
|
<string name="title_desc">Bold, upper case, alignment</string>
|
||||||
|
<string name="text_desc">Font size, letter spacing, alignment</string>
|
||||||
|
<string name="images_desc">Rounded corners, horizontal padding</string>
|
||||||
|
<string name="videos_desc">Rounded corners, horizontal padding</string>
|
||||||
|
<string name="maximize">Maximize</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
311
app/src/main/res/values-hi-rIN/strings.xml
Normal file
311
app/src/main/res/values-hi-rIN/strings.xml
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
<resources>
|
||||||
|
<string name="all">सभी</string>
|
||||||
|
<plurals name="all_desc">
|
||||||
|
<item quantity="one">%1$d संग्रहित पाठ </item>
|
||||||
|
<item quantity="other">%1$d संग्रहित पाठ</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="unread">अपठित पाठ </string>
|
||||||
|
<plurals name="unread_desc">
|
||||||
|
<item quantity="one">%1$d अपठित पाठ </item>
|
||||||
|
<item quantity="other">%1$d अपठित पाठ </item>
|
||||||
|
</plurals>
|
||||||
|
<string name="starred">चिन्हित</string>
|
||||||
|
<plurals name="starred_desc">
|
||||||
|
<item quantity="one">%1$d चिन्हित पाठ</item>
|
||||||
|
<item quantity="other">%1$d चिन्हित पाठ</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="feeds">फीड </string>
|
||||||
|
<string name="syncing">सिंक्रनाइज़ किए जा रहे…</string>
|
||||||
|
<string name="loading">लोड हो रहा है…</string>
|
||||||
|
<string name="expand_less">समेटे</string>
|
||||||
|
<string name="expand_more">विस्तृत करें</string>
|
||||||
|
<string name="confirm">पुष्टि करें</string>
|
||||||
|
<string name="cancel">रद्द करें</string>
|
||||||
|
<string name="allow">अनुमति </string>
|
||||||
|
<string name="deny">अस्वीकार </string>
|
||||||
|
<string name="defaults">सामान्य विकल्प </string>
|
||||||
|
<string name="unknown">अज्ञात</string>
|
||||||
|
<string name="back">पीछे </string>
|
||||||
|
<string name="go_to"> गो टू</string>
|
||||||
|
<string name="settings">सेटिंग्स</string>
|
||||||
|
<string name="refresh">रिफ्रेश</string>
|
||||||
|
<string name="search">खोजो</string>
|
||||||
|
<string name="searching">खोज रहे है …</string>
|
||||||
|
<string name="subscribe">सदस्यता लें </string>
|
||||||
|
<string name="already_subscribed">सदस्यता ले ली है </string>
|
||||||
|
<string name="clear">क्लिअर</string>
|
||||||
|
<string name="paste">पेस्ट</string>
|
||||||
|
<string name="feed_or_site_url">यु अरे एल अथवा फ़ीड्स </string>
|
||||||
|
<string name="import_from_opml">ओ पी एम् एल से आयात करें </string>
|
||||||
|
<string name="preset">प्रीसेट</string>
|
||||||
|
<string name="selected">चयनित</string>
|
||||||
|
<string name="allow_notification">नोटिफिकेशन की अनुमति दें</string>
|
||||||
|
<string name="all_allow_notification_tips"> \"%1$s\" ग्रुप के सभी फ़ीड्स को नोटीफिकेशन की स्वीकृति दें </string>
|
||||||
|
<string name="all_allow_notification_toast">\"%1$s\" ग्रुप के सभी नोटीफिकेशन स्वीकृत है </string>
|
||||||
|
<string name="all_deny_notification_toast"> \"%1$s\" ग्रुप के सभी नोटीफिकेशन अस्वीकृत है </string>
|
||||||
|
<string name="parse_full_content">पूरा पाठ दिखाएँ </string>
|
||||||
|
<string name="all_parse_full_content_tips"> \"%1$s\" ग्रुप के सभी पाठ पूरे दिखाएँ </string>
|
||||||
|
<string name="all_parse_full_content_toast"> \"%1$s\" ग्रुप के सभी पाठ पूरे दिखाएँ</string>
|
||||||
|
<string name="all_deny_parse_full_content_toast"> \"%1$s\" ग्रुप के सभी पाठ पूरे ना दिखाएँ</string>
|
||||||
|
<string name="clear_articles">पाठ हटाएँ </string>
|
||||||
|
<string name="clear_articles_in_feed_toast">\"%1$s\" फीड के सभी संग्रहित पाठो को हटाएँ </string>
|
||||||
|
<string name="clear_articles_in_group_toast"> \"%1$s\"फीड के सभी संग्रहित पाठ हटा दिए है </string>
|
||||||
|
<string name="clear_articles_feed_tips"> \"%1$s\" फीड के सभी संग्रहित पाठ हटाएँ .</string>
|
||||||
|
<string name="clear_articles_group_tips">\"%1$s\" ग्रुप के सभी संग्रहित पाठो को हटाएँ.</string>
|
||||||
|
<string name="add_to_group">ग्रुप में जोड़ें </string>
|
||||||
|
<string name="move_to_group">ग्रुप में स्तानान्तरित करें </string>
|
||||||
|
<string name="all_move_to_group_tips">\"%1$s\" ग्रुप के सभी पाठो को \"%2$s\" में स्थानांतरित करें .</string>
|
||||||
|
<string name="all_move_to_group_toast">\"%1$s\" ग्रुप में स्थानांतरण पूरा हुआ </string>
|
||||||
|
<string name="rename">नाम बदलें </string>
|
||||||
|
<string name="change_url">यु आर एल बदलें </string>
|
||||||
|
<string name="rename_toast">नया नाम \"%1$s\"</string>
|
||||||
|
<string name="create_new_group">नया ग्रुप बनाएँ </string>
|
||||||
|
<string name="name">नाम </string>
|
||||||
|
<string name="open_with">खोलें %1$s</string>
|
||||||
|
<string name="options">विकल्प </string>
|
||||||
|
<string name="delete">मिटाएं </string>
|
||||||
|
<string name="delete_toast">मिट गया \"%1$s\"</string>
|
||||||
|
<string name="unsubscribe">सदस्यता छोडें</string>
|
||||||
|
<string name="unsubscribe_tips"> \"%1$s\" से सदस्यता छोडें और सभी संग्रहित पाठों को मिटाएं </string>
|
||||||
|
<string name="delete_group">ग्रुप को मिटाएँ </string>
|
||||||
|
<string name="delete_group_tips"> \"%1$s\" ग्रुप के सभी फ़ीड्स अथवा संग्रहित पाठों को मिटाएँ </string>
|
||||||
|
<string name="group_option_tips">निम्नलिखित विकल्प ग्रुप के सभी फ़ीडस् पर लागू होंगे</string>
|
||||||
|
<string name="today">आज </string>
|
||||||
|
<string name="yesterday">कल </string>
|
||||||
|
<string name="date_at_time">तिथि %1$s समय %2$s</string>
|
||||||
|
<string name="search_for_in"> %1$s के लिए \"%2$s\ में खोजें "</string>
|
||||||
|
<string name="search_for">पाठों में %1$s खोजें </string>
|
||||||
|
<string name="mark_as_read">पढ़ा हुआ चिन्हित करें </string>
|
||||||
|
<string name="mark_all_as_read">सभी को पढ़ा हुआ चिन्हित करें</string>
|
||||||
|
<string name="mark_as_unread">अपठित के रूप में चिह्नित करें</string>
|
||||||
|
<string name="mark_as_starred">तारांकित के रूप में चिह्नित करें</string>
|
||||||
|
<string name="mark_as_unstar">अतारांकित के रूप में चिह्नित करें</string>
|
||||||
|
<string name="mark_as_read_one_day">1 दिन से अधिक पढ़ें के रूप में चिह्नित करें</string>
|
||||||
|
<string name="mark_as_read_three_days">3 दिन से अधिक पढ़ें के रूप में चिह्नित करें</string>
|
||||||
|
<string name="mark_as_read_seven_days">7 दिन से अधिक पढ़ें के रूप में चिह्नित करें</string>
|
||||||
|
<string name="one_day">1 दिन </string>
|
||||||
|
<string name="three_days">3 दिन </string>
|
||||||
|
<string name="seven_days">7 दिन </string>
|
||||||
|
<string name="close">बंद करें </string>
|
||||||
|
<string name="get_new_updates">नया अपडेट प्राप्त करें</string>
|
||||||
|
<string name="get_new_updates_desc"> %1$s वर्ज़न उपलब्ध है </string>
|
||||||
|
<string name="in_coding">कोडिंग चल रही है....</string>
|
||||||
|
<string name="coming_soon">जल्द आ रहा है...</string>
|
||||||
|
<string name="accounts">खाते</string>
|
||||||
|
<string name="accounts_desc">लोकल, नया आर एस एस </string>
|
||||||
|
<string name="color_and_style">रंग अथवा शैली </string>
|
||||||
|
<string name="color_and_style_desc">थीम , रंग शैली , लिपि आकार </string>
|
||||||
|
<string name="interaction">Interaction</string>
|
||||||
|
<string name="interaction_desc">शुरू होने पे , हैप्टिक फीडबैक </string>
|
||||||
|
<string name="languages">भाषाएँ </string>
|
||||||
|
<string name="languages_desc">अंग्रेजी , चाइनीज, और..</string>
|
||||||
|
<string name="help_translate">अनुवाद में मदद करें</string>
|
||||||
|
<string name="use_device_languages">डिवाइस भाषा का उपयोग करें</string>
|
||||||
|
<string name="tips_and_support">सुझाव और सहायता</string>
|
||||||
|
<string name="tips_and_support_desc">परिचय, ओपन सोर्स लाइसेंस</string>
|
||||||
|
<string name="welcome">स्वागत है </string>
|
||||||
|
<string name="tos_tips">आगे बढ़ने के लिए Read Youकी सेवा शर्तें और गोपनीयता नीति को पढ़े और स्वीकार करें </string>
|
||||||
|
<string name="browse_tos_tips">यहाँ <i><u>सेवा शर्तें और गोपनीयता नीति पढ़े </u></i>
|
||||||
|
</string>
|
||||||
|
<string name="terms_of_service">सेवा की शर्तें</string>
|
||||||
|
<string name="tos_content">
|
||||||
|
<h5>
|
||||||
|
|
||||||
|
गोपनीयता नीति
|
||||||
|
|
||||||
|
</h5>
|
||||||
|
<br/>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
मैं आपकी गोपनीयता को बहुत गंभीरता से लेता हूं
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<p>
|
||||||
|
<b>Read You</b>
|
||||||
|
|
||||||
|
कोई उपयोगकर्ता डेटा एकत्र नहीं करता है, और सभी संवेदनशील जानकारी (पासवर्ड और अन्य खाता जानकारी)
|
||||||
|
आपके डिवाइस पर स्थानीय एप्लिकेशन डेटाबेस में सुरक्षित रूप से संग्रहीत है|
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<p>
|
||||||
|
<b>Read You</b>
|
||||||
|
|
||||||
|
आपको सेवा प्रदान करने के लिए निम्नलिखित अनुमतियों का उपयोग किया जाएगा।
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
- एक्सेस नेटवर्क अनुमति (आपके द्वारा निर्देशित ऑनलाइन सामग्री तक पहुँचने के लिए)
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
- नेटवर्क स्थिति की अनुमति (यह जानने करने के लिए कि क्या डिवाइस में वर्तमान में नेटवर्क की स्थिति उपलब्ध है)
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
-पृष्ठभूमिक सेवा अनुमति (नियमित रूप से अपने पसंदीदार पाठों को स्वचालित रूप से नियमित सिंक करने के लिए आधार)
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<h5>
|
||||||
|
|
||||||
|
तृतीय पक्ष सेवाएं
|
||||||
|
|
||||||
|
</h5>
|
||||||
|
<br/>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
यह नीति आपके द्वारा <b>Read You</b>के साथ उपयोग की जाने वाली तृतीय-पक्ष सेवाओं पर लागू नहीं होती है. आप उन वेबसाइटों की गोपनीयता नीतियों की समीक्षा
|
||||||
|
करने हेतु स्वतंत्र है|
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<h5>
|
||||||
|
|
||||||
|
अस्वीकरण
|
||||||
|
|
||||||
|
</h5>
|
||||||
|
<br/>
|
||||||
|
<p>
|
||||||
|
<b>Read You</b>
|
||||||
|
|
||||||
|
केवल एक सामग्री संग्रह उपकरण है।. आपके द्वारा <b>Read You</b> का उपयोग आपके देश/राष्ट्र और क्षेत्र के नियम ऐवं कानून के अंतर्गत है
|
||||||
|
और आपके कार्यों से उत्पन्न होने वाले किसी भी दायित्व का वहन आपके द्वारा ही किया जाएगा |
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<h5>
|
||||||
|
|
||||||
|
ओपन सोर्स लाइसेंस
|
||||||
|
|
||||||
|
</h5>
|
||||||
|
<br/>
|
||||||
|
<p>
|
||||||
|
<b>Read You</b>
|
||||||
|
|
||||||
|
GNU GPL 3.0 Open Source License[1] के अंतर्गत एक ओपन सौरसे प्रोजेक्ट है, जो आपको <b>Read You</b> के सोर्स कोड को उपयोग,
|
||||||
|
प्रासंगिक सन्दर्भ और मुफ्त में संशोधित करेने के अनुमति देता है, परन्तु संशोधित और व्युत्पन्न कोड को क्लोज्ड-सोर्स वाणिज्यिक सॉफ्टवेयर के रूप में वितरित और बेचा जाने की अनुमति नहीं देता ।
|
||||||
|
पूर्ण जानकारी हेतु GNU GPL 3.0 Open Source License[2]. देखें।
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<h5>
|
||||||
|
|
||||||
|
शेषसंग्रह
|
||||||
|
|
||||||
|
</h5>
|
||||||
|
<br/>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
- [1] https://github.com/Ashinch/ReadYou
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
- [2] https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</string>
|
||||||
|
<string name="agree">स्वीकृत करें </string>
|
||||||
|
<string name="wallpaper_colors">वॉलपेपर रंग</string>
|
||||||
|
<string name="no_palettes">कोई पैलेट नहीं</string>
|
||||||
|
<string name="only_android_8.1_plus">केवल Android 8.1+ हेतु </string>
|
||||||
|
<string name="basic_colors">मूल रंग</string>
|
||||||
|
<string name="primary_color">प्राथमिक रंग</string>
|
||||||
|
<string name="primary_color_hint">जैसे #666666 या 666666</string>
|
||||||
|
<string name="appearance">रूप </string>
|
||||||
|
<string name="style">शैली</string>
|
||||||
|
<string name="dark_theme">डार्क थीम </string>
|
||||||
|
<string name="use_device_theme"> डिवाइस थीम का उपयोग करें </string>
|
||||||
|
<string name="on">ओन</string>
|
||||||
|
<string name="off">ऑफ</string>
|
||||||
|
<string name="other">अन्य </string>
|
||||||
|
<string name="amoled_dark_theme">अमोलेड डार्क थीम</string>
|
||||||
|
<string name="tonal_elevation">टोनल एलिवेशन</string>
|
||||||
|
<string name="reading_fonts">रीडिंग फोंट</string>
|
||||||
|
<string name="basic_fonts">बेसिक फोंट </string>
|
||||||
|
<string name="feeds_page">फ़ीड्स पेज </string>
|
||||||
|
<string name="flow_page">फ्लो पेज </string>
|
||||||
|
<string name="reading_page">रीडिंग पेज </string>
|
||||||
|
<string name="sponsor">प्रायोजक</string>
|
||||||
|
<string name="open_source_licenses">Open source licenses</string>
|
||||||
|
<string name="update_link">https://api.github.com/repos/Ashinch/ReadYou/releases/latest</string>
|
||||||
|
<string name="change_log">बदलाव सूचि </string>
|
||||||
|
<string name="update">अपडेट</string>
|
||||||
|
<string name="skip_this_version">इस वर्जन को छोडें </string>
|
||||||
|
<string name="checking_updates">अपडेट के लिए जाँच कर रहा है</string>
|
||||||
|
<string name="is_latest_version">यह लेटेस्ट अपडेट है </string>
|
||||||
|
<string name="check_failure">अपडेट की जाँच नहीं कर पाए </string>
|
||||||
|
<string name="download_failure">अपडेट डाउनलोड नहीं कर पाए </string>
|
||||||
|
<string name="rate_limit">अनुरोध दर सीमित है</string>
|
||||||
|
<string name="help">सहायता </string>
|
||||||
|
<string name="on_start">चालू होने पर</string>
|
||||||
|
<string name="initial_page">प्रारंभिक पृष्ठ</string>
|
||||||
|
<string name="initial_filter">प्रारंभिक फ़िल्टर</string>
|
||||||
|
<string name="preview_article_title">"रेत-समाधि" उपन्यास अंततः समाप्त हो गई </string>
|
||||||
|
<string name="preview_article_desc">रेत-समाधि गीतांजलि श्री की लिखी हुए उत्तम श्रेष्ट अथवा पहली हिंदी उपन्यास है जिसे अंतर्राष्ट्रीय बुकर प्रिज़े से सम्मानित किया गया है
|
||||||
|
</string>
|
||||||
|
<string name="preview_feed_name">रेडइट</string>
|
||||||
|
<string name="value">अंक</string>
|
||||||
|
<string name="horizontal_padding">दोनों सिरों पर पैडिंग</string>
|
||||||
|
<string name="article_date">पाठ प्रकाशन दिनांक </string>
|
||||||
|
<string name="article_desc">पाठ विवरण </string>
|
||||||
|
<string name="article_images">पाठ चित्र कलाएँ</string>
|
||||||
|
<string name="feed_names">फीड के नाम </string>
|
||||||
|
<string name="feed_favicons">फीड फविकों </string>
|
||||||
|
<string name="article_date_sticky_header">प्रकाशन तिथि के लिए स्टिकी हेडर (प्रयोगात्मक)</string>
|
||||||
|
<string name="article_list">पाठों की सूचि </string>
|
||||||
|
<string name="group_list">ग्रुप की सूचि </string>
|
||||||
|
<string name="always_expand">हमेशा विस्तृत रखें </string>
|
||||||
|
<string name="top">टॉप </string>
|
||||||
|
<string name="mark_as_read_button_position">\"पढ़ा हुआ चिन्हित करें " \बटन का स्थान </string>
|
||||||
|
<string name="top_bar">टॉप बार </string>
|
||||||
|
<string name="fill_selected_icon">चयनित आइकन भरें</string>
|
||||||
|
<string name="filter_bar">फ़िल्टर बार</string>
|
||||||
|
<string name="icons">चिह्न</string>
|
||||||
|
<string name="icons_and_labels">चिह्न ऐवं लेबल</string>
|
||||||
|
<string name="icons_and_label_only_selected">चिह्न ऐवं लेबल (केवल चयनित)</string>
|
||||||
|
<string name="tips_top_bar_tonal_elevation">यह टूल एलिवेशन केवल स्क्रॉल करते समय उपलब्ध है </string>
|
||||||
|
<string name="tips_article_list_tonal_elevation">यह टोनल एलिवेशन केवल लाइट थीम में उपलब्ध है</string>
|
||||||
|
<string name="tips_group_list_tonal_elevation">यह टोनल एलिवेशन केवल लाइट थीम में उपलब्ध है</string>
|
||||||
|
<string name="share">साँझा करें </string>
|
||||||
|
<string name="touch_to_play_video">विडियो चलने हेतु टच करें </string>
|
||||||
|
<string name="text">पाठा </string>
|
||||||
|
<string name="font_size">फोंट साइज</string>
|
||||||
|
<string name="letter_spacing">लैटर स्पेसिंग</string>
|
||||||
|
<string name="line_spacing">लाइन स्पेसिंग </string>
|
||||||
|
<string name="alignment">संरेखण</string>
|
||||||
|
<string name="general">सामान्य </string>
|
||||||
|
<string name="auto_hide_toolbars">टूलबार स्वतः छुपाएँ </string>
|
||||||
|
<string name="rearrange_buttons">बटन पुनर्व्यवस्थित करें </string>
|
||||||
|
<string name="bionic_reading">बैओनिक पाठन</string>
|
||||||
|
<string name="images">चित्र</string>
|
||||||
|
<string name="rounded_corners">गोल कोने </string>
|
||||||
|
<string name="videos">चलचित्र</string>
|
||||||
|
<string name="align_left">बाये संरेखित करें </string>
|
||||||
|
<string name="align_right">दाएँ संरेखित करें </string>
|
||||||
|
<string name="center_text">पाठ मध्य संरेखित करें </string>
|
||||||
|
<string name="justify">संयोजिक करें </string>
|
||||||
|
<string name="external_fonts">बाहरी फोंट</string>
|
||||||
|
<string name="title">शीर्षक</string>
|
||||||
|
<string name="bold">बोल्ड</string>
|
||||||
|
<string name="upper_case">अपरकेस</string>
|
||||||
|
<string name="subhead">उप शीर्षक</string>
|
||||||
|
<string name="use_app_theme">एप की थीम लगाएं </string>
|
||||||
|
<string name="advanced">एडवांस </string>
|
||||||
|
<string name="dark_reading_theme">डार्क रीडर थीम</string>
|
||||||
|
<string name="title_desc">बोल्ड, उपरेखा, संरेखित </string>
|
||||||
|
<string name="text_desc">फोंट साईज, पंक्ति और अनुछेद रिक्त , संरेख</string>
|
||||||
|
<string name="images_desc">गोल कोण ,क्षैतिज पेडिंग </string>
|
||||||
|
<string name="videos_desc">गोल कोण ,क्षैतिज पेडिंग</string>
|
||||||
|
<string name="maximize">बड़ा करें</string>
|
||||||
|
</resources>
|
|
@ -233,7 +233,7 @@
|
||||||
<string name="other">Altro</string>
|
<string name="other">Altro</string>
|
||||||
<string name="amoled_dark_theme">Tema scuro AMOLED</string>
|
<string name="amoled_dark_theme">Tema scuro AMOLED</string>
|
||||||
<string name="tonal_elevation">Elevazione tonale</string>
|
<string name="tonal_elevation">Elevazione tonale</string>
|
||||||
<string name="fonts">Font</string>
|
<string name="reading_fonts">Font di lettura</string>
|
||||||
<string name="basic_fonts">Font di base</string>
|
<string name="basic_fonts">Font di base</string>
|
||||||
<string name="feeds_page">Pagina dei feed</string>
|
<string name="feeds_page">Pagina dei feed</string>
|
||||||
<string name="flow_page">Pagina dei flow</string>
|
<string name="flow_page">Pagina dei flow</string>
|
||||||
|
@ -257,7 +257,7 @@
|
||||||
<string name="preview_article_desc">Lo Sciocco è l\'ottavo e ultimo volume della serie Il Signore dei Misteri, scritta da Seppia Che Ama Le Immersioni.</string>
|
<string name="preview_article_desc">Lo Sciocco è l\'ottavo e ultimo volume della serie Il Signore dei Misteri, scritta da Seppia Che Ama Le Immersioni.</string>
|
||||||
<string name="preview_feed_name">Reddit</string>
|
<string name="preview_feed_name">Reddit</string>
|
||||||
<string name="value">valore</string>
|
<string name="value">valore</string>
|
||||||
<string name="padding_on_both_ends">Padding su entrambe le estremità</string>
|
<string name="horizontal_padding">Imbottitura orizzontale</string>
|
||||||
<string name="article_date">Tempo di pubblicazione dell\'articolo</string>
|
<string name="article_date">Tempo di pubblicazione dell\'articolo</string>
|
||||||
<string name="article_desc">Descrizione dell\'articolo</string>
|
<string name="article_desc">Descrizione dell\'articolo</string>
|
||||||
<string name="article_images">Immagini dell\'articolo</string>
|
<string name="article_images">Immagini dell\'articolo</string>
|
||||||
|
@ -280,4 +280,33 @@
|
||||||
<string name="tips_group_list_tonal_elevation">Questa elevazione tonale è disponibile solo con il tema chiaro.</string>
|
<string name="tips_group_list_tonal_elevation">Questa elevazione tonale è disponibile solo con il tema chiaro.</string>
|
||||||
<string name="share">Condividi</string>
|
<string name="share">Condividi</string>
|
||||||
<string name="touch_to_play_video">Tocca per riprodurre il video</string>
|
<string name="touch_to_play_video">Tocca per riprodurre il video</string>
|
||||||
|
<string name="text">Text</string>
|
||||||
|
<string name="font_size">Font size</string>
|
||||||
|
<string name="letter_spacing">Letter spacing</string>
|
||||||
|
<string name="line_spacing">Line spacing</string>
|
||||||
|
<string name="alignment">Alignment</string>
|
||||||
|
<string name="general">General</string>
|
||||||
|
<string name="auto_hide_toolbars">Auto hide toolbars</string>
|
||||||
|
<string name="rearrange_buttons">Rearrange buttons</string>
|
||||||
|
<string name="bionic_reading">Bionic Reading</string>
|
||||||
|
<string name="images">Images</string>
|
||||||
|
<string name="rounded_corners">Rounded corners</string>
|
||||||
|
<string name="videos">Videos</string>
|
||||||
|
<string name="align_left">Align left</string>
|
||||||
|
<string name="align_right">Align right</string>
|
||||||
|
<string name="center_text">Center text</string>
|
||||||
|
<string name="justify">Justify</string>
|
||||||
|
<string name="external_fonts">External fonts</string>
|
||||||
|
<string name="title">Title</string>
|
||||||
|
<string name="bold">Bold</string>
|
||||||
|
<string name="upper_case">Upper case</string>
|
||||||
|
<string name="subhead">Subhead</string>
|
||||||
|
<string name="use_app_theme">Use app theme</string>
|
||||||
|
<string name="advanced">Advanced</string>
|
||||||
|
<string name="dark_reading_theme">Dark reading theme</string>
|
||||||
|
<string name="title_desc">Bold, upper case, alignment</string>
|
||||||
|
<string name="text_desc">Font size, letter spacing, alignment</string>
|
||||||
|
<string name="images_desc">Rounded corners, horizontal padding</string>
|
||||||
|
<string name="videos_desc">Rounded corners, horizontal padding</string>
|
||||||
|
<string name="maximize">Maximize</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -224,7 +224,7 @@
|
||||||
<string name="amoled_dark_theme">AMOLED 深色主题</string>
|
<string name="amoled_dark_theme">AMOLED 深色主题</string>
|
||||||
<string name="other">其他</string>
|
<string name="other">其他</string>
|
||||||
<string name="tonal_elevation">色调海拔</string>
|
<string name="tonal_elevation">色调海拔</string>
|
||||||
<string name="fonts">字体</string>
|
<string name="reading_fonts">阅读字体</string>
|
||||||
<string name="basic_fonts">基本字体</string>
|
<string name="basic_fonts">基本字体</string>
|
||||||
<string name="feeds_page">订阅源页面</string>
|
<string name="feeds_page">订阅源页面</string>
|
||||||
<string name="flow_page">信息流页面</string>
|
<string name="flow_page">信息流页面</string>
|
||||||
|
@ -245,10 +245,12 @@
|
||||||
<string name="initial_page">起始页面</string>
|
<string name="initial_page">起始页面</string>
|
||||||
<string name="initial_filter">起始过滤条件</string>
|
<string name="initial_filter">起始过滤条件</string>
|
||||||
<string name="preview_article_title">呜呜呜,黎明之剑完结了</string>
|
<string name="preview_article_title">呜呜呜,黎明之剑完结了</string>
|
||||||
<string name="preview_article_desc">是宴席,就有结束的时候,但这本书真的陪了我好久啊,好舍不得,而且主线结束了坑却没填完,不知道啥时候才有番外啊</string>
|
<string name="preview_article_desc">
|
||||||
|
是宴席,就有结束的时候,但这本书真的陪了我好久啊,好舍不得,而且主线结束了坑却没填完,不知道啥时候才有番外啊
|
||||||
|
</string>
|
||||||
<string name="preview_feed_name">漩涡书院</string>
|
<string name="preview_feed_name">漩涡书院</string>
|
||||||
<string name="value">值</string>
|
<string name="value">值</string>
|
||||||
<string name="padding_on_both_ends">两端边距</string>
|
<string name="horizontal_padding">水平填充</string>
|
||||||
<string name="article_date">文章发布时间</string>
|
<string name="article_date">文章发布时间</string>
|
||||||
<string name="article_desc">文章描述</string>
|
<string name="article_desc">文章描述</string>
|
||||||
<string name="article_images">文章插图</string>
|
<string name="article_images">文章插图</string>
|
||||||
|
@ -271,4 +273,33 @@
|
||||||
<string name="tips_group_list_tonal_elevation">分组列表的色调海拔仅在亮色主题时可用。</string>
|
<string name="tips_group_list_tonal_elevation">分组列表的色调海拔仅在亮色主题时可用。</string>
|
||||||
<string name="share">分享</string>
|
<string name="share">分享</string>
|
||||||
<string name="touch_to_play_video">轻触播放视频</string>
|
<string name="touch_to_play_video">轻触播放视频</string>
|
||||||
|
<string name="text">文本</string>
|
||||||
|
<string name="font_size">字体大小</string>
|
||||||
|
<string name="letter_spacing">字符间距</string>
|
||||||
|
<string name="line_spacing">行间距</string>
|
||||||
|
<string name="alignment">对齐</string>
|
||||||
|
<string name="general">通用</string>
|
||||||
|
<string name="auto_hide_toolbars">自动隐藏工具条</string>
|
||||||
|
<string name="rearrange_buttons">重新排列按钮</string>
|
||||||
|
<string name="bionic_reading">仿生阅读</string>
|
||||||
|
<string name="images">图片</string>
|
||||||
|
<string name="rounded_corners">圆角</string>
|
||||||
|
<string name="videos">视频</string>
|
||||||
|
<string name="align_left">左对齐</string>
|
||||||
|
<string name="align_right">右对齐</string>
|
||||||
|
<string name="center_text">居中对齐</string>
|
||||||
|
<string name="justify">两端对齐</string>
|
||||||
|
<string name="external_fonts">外部字体</string>
|
||||||
|
<string name="title">标题</string>
|
||||||
|
<string name="bold">加粗</string>
|
||||||
|
<string name="upper_case">大写字母</string>
|
||||||
|
<string name="subhead">子标题</string>
|
||||||
|
<string name="use_app_theme">跟随应用设置</string>
|
||||||
|
<string name="advanced">高级</string>
|
||||||
|
<string name="dark_reading_theme">深色阅读主题</string>
|
||||||
|
<string name="title_desc">加粗、大写字母、对齐</string>
|
||||||
|
<string name="text_desc">字体大小、字符间距、对齐</string>
|
||||||
|
<string name="images_desc">圆角、水平边距</string>
|
||||||
|
<string name="videos_desc">圆角、水平边距</string>
|
||||||
|
<string name="maximize">最大化</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
<string name="french" translatable="false">français</string>
|
<string name="french" translatable="false">français</string>
|
||||||
<string name="czech" translatable="false">Čeština</string>
|
<string name="czech" translatable="false">Čeština</string>
|
||||||
<string name="italian" translatable="false">italiano</string>
|
<string name="italian" translatable="false">italiano</string>
|
||||||
|
<string name="hindi" translatable="false">हिंदी</string>
|
||||||
<string name="tips_and_support">Tips & support</string>
|
<string name="tips_and_support">Tips & support</string>
|
||||||
<string name="tips_and_support_desc">About, open source licenses</string>
|
<string name="tips_and_support_desc">About, open source licenses</string>
|
||||||
<string name="welcome">Welcome</string>
|
<string name="welcome">Welcome</string>
|
||||||
|
@ -244,7 +245,7 @@
|
||||||
<string name="other">Other</string>
|
<string name="other">Other</string>
|
||||||
<string name="amoled_dark_theme">AMOLED dark theme</string>
|
<string name="amoled_dark_theme">AMOLED dark theme</string>
|
||||||
<string name="tonal_elevation">Tonal elevation</string>
|
<string name="tonal_elevation">Tonal elevation</string>
|
||||||
<string name="fonts">Fonts</string>
|
<string name="reading_fonts">Reading fonts</string>
|
||||||
<string name="basic_fonts">Basic fonts</string>
|
<string name="basic_fonts">Basic fonts</string>
|
||||||
<string name="feeds_page">Feeds page</string>
|
<string name="feeds_page">Feeds page</string>
|
||||||
<string name="flow_page">Flow page</string>
|
<string name="flow_page">Flow page</string>
|
||||||
|
@ -272,7 +273,7 @@
|
||||||
</string>
|
</string>
|
||||||
<string name="preview_feed_name">Reddit</string>
|
<string name="preview_feed_name">Reddit</string>
|
||||||
<string name="value">value</string>
|
<string name="value">value</string>
|
||||||
<string name="padding_on_both_ends">Padding on both ends</string>
|
<string name="horizontal_padding">Horizontal padding</string>
|
||||||
<string name="article_date">Article publication time</string>
|
<string name="article_date">Article publication time</string>
|
||||||
<string name="article_desc">Article descriptions</string>
|
<string name="article_desc">Article descriptions</string>
|
||||||
<string name="article_images">Article images</string>
|
<string name="article_images">Article images</string>
|
||||||
|
@ -295,4 +296,33 @@
|
||||||
<string name="tips_group_list_tonal_elevation">This tonal elevation is only available in the light theme.</string>
|
<string name="tips_group_list_tonal_elevation">This tonal elevation is only available in the light theme.</string>
|
||||||
<string name="share">Share</string>
|
<string name="share">Share</string>
|
||||||
<string name="touch_to_play_video">Touch to play video</string>
|
<string name="touch_to_play_video">Touch to play video</string>
|
||||||
|
<string name="text">Text</string>
|
||||||
|
<string name="font_size">Font size</string>
|
||||||
|
<string name="letter_spacing">Letter spacing</string>
|
||||||
|
<string name="line_spacing">Line spacing</string>
|
||||||
|
<string name="alignment">Alignment</string>
|
||||||
|
<string name="general">General</string>
|
||||||
|
<string name="auto_hide_toolbars">Auto hide toolbars</string>
|
||||||
|
<string name="rearrange_buttons">Rearrange buttons</string>
|
||||||
|
<string name="bionic_reading">Bionic Reading</string>
|
||||||
|
<string name="images">Images</string>
|
||||||
|
<string name="rounded_corners">Rounded corners</string>
|
||||||
|
<string name="videos">Videos</string>
|
||||||
|
<string name="align_left">Align left</string>
|
||||||
|
<string name="align_right">Align right</string>
|
||||||
|
<string name="center_text">Center text</string>
|
||||||
|
<string name="justify">Justify</string>
|
||||||
|
<string name="external_fonts">External fonts</string>
|
||||||
|
<string name="title">Title</string>
|
||||||
|
<string name="bold">Bold</string>
|
||||||
|
<string name="upper_case">Upper case</string>
|
||||||
|
<string name="subhead">Subhead</string>
|
||||||
|
<string name="use_app_theme">Use app theme</string>
|
||||||
|
<string name="advanced">Advanced</string>
|
||||||
|
<string name="dark_reading_theme">Dark reading theme</string>
|
||||||
|
<string name="title_desc">Bold, upper case, alignment</string>
|
||||||
|
<string name="text_desc">Font size, letter spacing, alignment</string>
|
||||||
|
<string name="images_desc">Rounded corners, horizontal padding</string>
|
||||||
|
<string name="videos_desc">Rounded corners, horizontal padding</string>
|
||||||
|
<string name="maximize">Maximize</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
17
fastlane/metadata/android/de-DE/changelogs/12.txt
Normal file
17
fastlane/metadata/android/de-DE/changelogs/12.txt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
## 0.8.1
|
||||||
|
|
||||||
|
1. Französische Sprache hinzugefügt (Dank an DodoLeDev).
|
||||||
|
|
||||||
|
2. Tschechische Sprache hinzugefügt (Dank an Fjuro).
|
||||||
|
|
||||||
|
3. Einige übersetzte Texte geändert (Dank an comradekingu).
|
||||||
|
|
||||||
|
4. Behebung des Problems, das nach dem Import einer OPML-Datei aus Version 0.8.0 nicht synchronisiert werden kann.
|
||||||
|
|
||||||
|
5. Behebung eines Absturzes beim Laden sehr großer Bilder (50 MB+) (Dank an Feeder).
|
||||||
|
|
||||||
|
6. Behebung des Problems, dass einige Feeds nicht abonniert werden konnten (Dank an kzaemrio).
|
||||||
|
|
||||||
|
7. Optimierung im Falle von zu vielen Feeds (100+).
|
||||||
|
|
||||||
|
8. Einige Leistungsoptimierungen und Detailänderungen.
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user