From fa3c5e3601ce3e40919a693c104950ff844c4c36 Mon Sep 17 00:00:00 2001 From: Ash Date: Mon, 2 May 2022 13:52:08 +0800 Subject: [PATCH] Add FeedsPage style settings --- .../preference/ArticleListImagePreference.kt | 45 --- .../FeedsFilterBarFilledPreference.kt | 45 +++ .../FeedsFilterBarPaddingPreference.kt | 28 ++ .../FeedsFilterBarStylePreference.kt | 49 +++ .../FeedsFilterBarTonalElevationPreference.kt | 57 +++ ...e.kt => FeedsGroupListExpandPreference.kt} | 18 +- .../FeedsGroupListTonalElevationPreference.kt | 57 +++ ...=> FeedsTopBarTonalElevationPreference.kt} | 20 +- ...ce.kt => FlowArticleListDatePreference.kt} | 18 +- ...ce.kt => FlowArticleListDescPreference.kt} | 18 +- .../FlowArticleListFeedIconPreference.kt | 45 +++ .../FlowArticleListFeedNamePreference.kt | 45 +++ ...e.kt => FlowArticleListImagePreference.kt} | 18 +- ...FlowArticleListTonalElevationPreference.kt | 57 +++ ...ce.kt => FlowFilterBarFilledPreference.kt} | 18 +- ...e.kt => FlowFilterBarPaddingPreference.kt} | 9 +- ...nce.kt => FlowFilterBarStylePreference.kt} | 21 +- .../FlowFilterBarTonalElevationPreference.kt | 57 +++ ... => FlowTopBarTonalElevationPreference.kt} | 20 +- .../reader/data/preference/ThemePreference.kt | 28 ++ .../java/me/ash/reader/ui/component/Tips.kt | 38 ++ .../java/me/ash/reader/ui/ext/ColorScheme.kt | 16 +- .../java/me/ash/reader/ui/ext/DataStoreExt.kt | 112 ++++-- .../me/ash/reader/ui/page/common/HomeEntry.kt | 4 + .../me/ash/reader/ui/page/common/RouteName.kt | 1 + .../me/ash/reader/ui/page/home/FilterBar.kt | 43 +- .../ash/reader/ui/page/home/HomeViewModel.kt | 2 +- .../ash/reader/ui/page/home/feeds/FeedItem.kt | 27 +- .../reader/ui/page/home/feeds/FeedsPage.kt | 43 +- .../reader/ui/page/home/feeds/GroupItem.kt | 14 +- .../reader/ui/page/home/flow/ArticleItem.kt | 41 +- .../ash/reader/ui/page/home/flow/FlowPage.kt | 47 ++- .../reader/ui/page/home/flow/StickyHeader.kt | 12 +- .../ui/page/settings/color/ColorAndStyle.kt | 24 +- .../settings/color/feeds/FeedsPageStyle.kt | 379 ++++++++++++++++++ .../{feedsPageStyle.kt => FlowPageStyle.kt} | 264 ++++++++---- .../ash/reader/ui/page/startup/StartupPage.kt | 32 +- .../java/me/ash/reader/ui/svg/SVGString.kt | 2 + .../main/java/me/ash/reader/ui/theme/Theme.kt | 124 +++++- .../ui/theme/palette/DynamicTonalPalette.kt | 2 + app/src/main/res/values-zh-rCN/strings.xml | 26 +- app/src/main/res/values/strings.xml | 30 +- 42 files changed, 1550 insertions(+), 406 deletions(-) delete mode 100644 app/src/main/java/me/ash/reader/data/preference/ArticleListImagePreference.kt create mode 100644 app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarFilledPreference.kt create mode 100644 app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarPaddingPreference.kt create mode 100644 app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarStylePreference.kt create mode 100644 app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarTonalElevationPreference.kt rename app/src/main/java/me/ash/reader/data/preference/{ArticleListDatePreference.kt => FeedsGroupListExpandPreference.kt} (59%) create mode 100644 app/src/main/java/me/ash/reader/data/preference/FeedsGroupListTonalElevationPreference.kt rename app/src/main/java/me/ash/reader/data/preference/{ArticleListTonalElevationPreference.kt => FeedsTopBarTonalElevationPreference.kt} (69%) rename app/src/main/java/me/ash/reader/data/preference/{ArticleListFeedNamePreference.kt => FlowArticleListDatePreference.kt} (62%) rename app/src/main/java/me/ash/reader/data/preference/{ArticleListFeedIconPreference.kt => FlowArticleListDescPreference.kt} (61%) create mode 100644 app/src/main/java/me/ash/reader/data/preference/FlowArticleListFeedIconPreference.kt create mode 100644 app/src/main/java/me/ash/reader/data/preference/FlowArticleListFeedNamePreference.kt rename app/src/main/java/me/ash/reader/data/preference/{ArticleListDescPreference.kt => FlowArticleListImagePreference.kt} (59%) create mode 100644 app/src/main/java/me/ash/reader/data/preference/FlowArticleListTonalElevationPreference.kt rename app/src/main/java/me/ash/reader/data/preference/{FilterBarFilledPreference.kt => FlowFilterBarFilledPreference.kt} (59%) rename app/src/main/java/me/ash/reader/data/preference/{FilterBarPaddingPreference.kt => FlowFilterBarPaddingPreference.kt} (72%) rename app/src/main/java/me/ash/reader/data/preference/{FilterBarStylePreference.kt => FlowFilterBarStylePreference.kt} (59%) create mode 100644 app/src/main/java/me/ash/reader/data/preference/FlowFilterBarTonalElevationPreference.kt rename app/src/main/java/me/ash/reader/data/preference/{FilterBarTonalElevationPreference.kt => FlowTopBarTonalElevationPreference.kt} (66%) create mode 100644 app/src/main/java/me/ash/reader/data/preference/ThemePreference.kt create mode 100644 app/src/main/java/me/ash/reader/ui/component/Tips.kt create mode 100644 app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPageStyle.kt rename app/src/main/java/me/ash/reader/ui/page/settings/color/flow/{feedsPageStyle.kt => FlowPageStyle.kt} (56%) diff --git a/app/src/main/java/me/ash/reader/data/preference/ArticleListImagePreference.kt b/app/src/main/java/me/ash/reader/data/preference/ArticleListImagePreference.kt deleted file mode 100644 index 06bdde6..0000000 --- a/app/src/main/java/me/ash/reader/data/preference/ArticleListImagePreference.kt +++ /dev/null @@ -1,45 +0,0 @@ -package me.ash.reader.data.preference - -import android.content.Context -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -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 ArticleListImagePreference(val value: Boolean) : Preference() { - object ON : ArticleListImagePreference(true) - object OFF : ArticleListImagePreference(false) - - override fun put(context: Context, scope: CoroutineScope) { - scope.launch(Dispatchers.IO) { - context.dataStore.put( - DataStoreKeys.ArticleListImage, - value - ) - } - } - - companion object { - val default = ON - val values = listOf(ON, OFF) - - val Context.articleListImage: Flow - get() = this.dataStore.data.map { - when (it[DataStoreKeys.ArticleListImage.key]) { - true -> ON - false -> OFF - else -> default - } - } - } -} - -operator fun ArticleListImagePreference.not(): ArticleListImagePreference = - when (value) { - true -> ArticleListImagePreference.OFF - false -> ArticleListImagePreference.ON - } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarFilledPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarFilledPreference.kt new file mode 100644 index 0000000..73dcf13 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarFilledPreference.kt @@ -0,0 +1,45 @@ +package me.ash.reader.data.preference + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 FeedsFilterBarFilledPreference(val value: Boolean) : Preference() { + object ON : FeedsFilterBarFilledPreference(true) + object OFF : FeedsFilterBarFilledPreference(false) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch(Dispatchers.IO) { + context.dataStore.put( + DataStoreKeys.FeedsFilterBarFilled, + value + ) + } + } + + companion object { + val default = OFF + val values = listOf(ON, OFF) + + val Context.feedsFilterBarFilled: Flow + get() = this.dataStore.data.map { + when (it[DataStoreKeys.FeedsFilterBarFilled.key]) { + true -> ON + false -> OFF + else -> default + } + } + } +} + +operator fun FeedsFilterBarFilledPreference.not(): FeedsFilterBarFilledPreference = + when (value) { + true -> FeedsFilterBarFilledPreference.OFF + false -> FeedsFilterBarFilledPreference.ON + } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarPaddingPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarPaddingPreference.kt new file mode 100644 index 0000000..6f2bf15 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarPaddingPreference.kt @@ -0,0 +1,28 @@ +package me.ash.reader.data.preference + +import android.content.Context +import androidx.compose.runtime.Immutable +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 +object FeedsFilterBarPaddingPreference { + const val default = 0 + + val Context.feedsFilterBarPadding: Flow + get() = this.dataStore.data.map { + it[DataStoreKeys.FeedsFilterBarPadding.key] ?: default + } + + fun put(context: Context, scope: CoroutineScope, value: Int) { + scope.launch(Dispatchers.IO) { + context.dataStore.put(DataStoreKeys.FeedsFilterBarPadding, value) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarStylePreference.kt b/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarStylePreference.kt new file mode 100644 index 0000000..f7db9d3 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarStylePreference.kt @@ -0,0 +1,49 @@ +package me.ash.reader.data.preference + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 FeedsFilterBarStylePreference(val value: Int) : Preference() { + object Icon : FeedsFilterBarStylePreference(0) + object IconLabel : FeedsFilterBarStylePreference(1) + object IconLabelOnlySelected : FeedsFilterBarStylePreference(2) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch(Dispatchers.IO) { + context.dataStore.put( + DataStoreKeys.FeedsFilterBarStyle, + value + ) + } + } + + fun getDesc(context: Context): String = + when (this) { + Icon -> context.getString(R.string.icons) + IconLabel -> context.getString(R.string.icons_and_labels) + IconLabelOnlySelected -> context.getString(R.string.icons_and_label_only_selected) + } + + companion object { + val default = Icon + val values = listOf(Icon, IconLabel, IconLabelOnlySelected) + + val Context.feedsFilterBarStyle: Flow + get() = this.dataStore.data.map { + when (it[DataStoreKeys.FeedsFilterBarStyle.key]) { + 0 -> Icon + 1 -> IconLabel + 2 -> IconLabelOnlySelected + else -> default + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarTonalElevationPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarTonalElevationPreference.kt new file mode 100644 index 0000000..7afc42b --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FeedsFilterBarTonalElevationPreference.kt @@ -0,0 +1,57 @@ +package me.ash.reader.data.preference + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 FeedsFilterBarTonalElevationPreference(val value: Int) : Preference() { + object Level0 : FeedsFilterBarTonalElevationPreference(0) + object Level1 : FeedsFilterBarTonalElevationPreference(1) + object Level2 : FeedsFilterBarTonalElevationPreference(3) + object Level3 : FeedsFilterBarTonalElevationPreference(6) + object Level4 : FeedsFilterBarTonalElevationPreference(8) + object Level5 : FeedsFilterBarTonalElevationPreference(12) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch(Dispatchers.IO) { + context.dataStore.put( + DataStoreKeys.FeedsFilterBarTonalElevation, + value + ) + } + } + + fun getDesc(context: Context): String = + when (this) { + Level0 -> "Level 0 (0dp)" + Level1 -> "Level 1 (1dp)" + Level2 -> "Level 2 (3dp)" + Level3 -> "Level 3 (6dp)" + Level4 -> "Level 4 (8dp)" + Level5 -> "Level 5 (12dp)" + } + + companion object { + val default = Level0 + val values = listOf(Level0, Level1, Level2, Level3, Level4, Level5) + + val Context.feedsFilterBarTonalElevation: Flow + get() = this.dataStore.data.map { + when (it[DataStoreKeys.FeedsFilterBarTonalElevation.key]) { + 0 -> Level0 + 1 -> Level1 + 3 -> Level2 + 6 -> Level3 + 8 -> Level4 + 12 -> Level5 + else -> default + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/ArticleListDatePreference.kt b/app/src/main/java/me/ash/reader/data/preference/FeedsGroupListExpandPreference.kt similarity index 59% rename from app/src/main/java/me/ash/reader/data/preference/ArticleListDatePreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FeedsGroupListExpandPreference.kt index b89720a..bad79bd 100644 --- a/app/src/main/java/me/ash/reader/data/preference/ArticleListDatePreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FeedsGroupListExpandPreference.kt @@ -10,14 +10,14 @@ import me.ash.reader.ui.ext.DataStoreKeys import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put -sealed class ArticleListDatePreference(val value: Boolean) : Preference() { - object ON : ArticleListDatePreference(true) - object OFF : ArticleListDatePreference(false) +sealed class FeedsGroupListExpandPreference(val value: Boolean) : Preference() { + object ON : FeedsGroupListExpandPreference(true) + object OFF : FeedsGroupListExpandPreference(false) override fun put(context: Context, scope: CoroutineScope) { scope.launch(Dispatchers.IO) { context.dataStore.put( - DataStoreKeys.ArticleListDate, + DataStoreKeys.FeedsGroupListExpand, value ) } @@ -27,9 +27,9 @@ sealed class ArticleListDatePreference(val value: Boolean) : Preference() { val default = ON val values = listOf(ON, OFF) - val Context.articleListDate: Flow + val Context.feedsGroupListExpand: Flow get() = this.dataStore.data.map { - when (it[DataStoreKeys.ArticleListDate.key]) { + when (it[DataStoreKeys.FeedsGroupListExpand.key]) { true -> ON false -> OFF else -> default @@ -38,8 +38,8 @@ sealed class ArticleListDatePreference(val value: Boolean) : Preference() { } } -operator fun ArticleListDatePreference.not(): ArticleListDatePreference = +operator fun FeedsGroupListExpandPreference.not(): FeedsGroupListExpandPreference = when (value) { - true -> ArticleListDatePreference.OFF - false -> ArticleListDatePreference.ON + true -> FeedsGroupListExpandPreference.OFF + false -> FeedsGroupListExpandPreference.ON } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FeedsGroupListTonalElevationPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FeedsGroupListTonalElevationPreference.kt new file mode 100644 index 0000000..03148e5 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FeedsGroupListTonalElevationPreference.kt @@ -0,0 +1,57 @@ +package me.ash.reader.data.preference + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 FeedsGroupListTonalElevationPreference(val value: Int) : Preference() { + object Level0 : FeedsGroupListTonalElevationPreference(0) + object Level1 : FeedsGroupListTonalElevationPreference(1) + object Level2 : FeedsGroupListTonalElevationPreference(3) + object Level3 : FeedsGroupListTonalElevationPreference(6) + object Level4 : FeedsGroupListTonalElevationPreference(8) + object Level5 : FeedsGroupListTonalElevationPreference(12) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch(Dispatchers.IO) { + context.dataStore.put( + DataStoreKeys.FeedsGroupListTonalElevation, + value + ) + } + } + + fun getDesc(context: Context): String = + when (this) { + Level0 -> "Level 0 (0dp)" + Level1 -> "Level 1 (1dp)" + Level2 -> "Level 2 (3dp)" + Level3 -> "Level 3 (6dp)" + Level4 -> "Level 4 (8dp)" + Level5 -> "Level 5 (12dp)" + } + + companion object { + val default = Level0 + val values = listOf(Level0, Level1, Level2, Level3, Level4, Level5) + + val Context.feedsGroupListTonalElevation: Flow + get() = this.dataStore.data.map { + when (it[DataStoreKeys.FeedsGroupListTonalElevation.key]) { + 0 -> Level0 + 1 -> Level1 + 3 -> Level2 + 6 -> Level3 + 8 -> Level4 + 12 -> Level5 + else -> default + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/ArticleListTonalElevationPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FeedsTopBarTonalElevationPreference.kt similarity index 69% rename from app/src/main/java/me/ash/reader/data/preference/ArticleListTonalElevationPreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FeedsTopBarTonalElevationPreference.kt index 79a862a..c1e9e4c 100644 --- a/app/src/main/java/me/ash/reader/data/preference/ArticleListTonalElevationPreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FeedsTopBarTonalElevationPreference.kt @@ -10,18 +10,18 @@ import me.ash.reader.ui.ext.DataStoreKeys import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put -sealed class ArticleListTonalElevationPreference(val value: Int) : Preference() { - object Level0 : ArticleListTonalElevationPreference(0) - object Level1 : ArticleListTonalElevationPreference(1) - object Level2 : ArticleListTonalElevationPreference(3) - object Level3 : ArticleListTonalElevationPreference(6) - object Level4 : ArticleListTonalElevationPreference(8) - object Level5 : ArticleListTonalElevationPreference(12) +sealed class FeedsTopBarTonalElevationPreference(val value: Int) : Preference() { + object Level0 : FeedsTopBarTonalElevationPreference(0) + object Level1 : FeedsTopBarTonalElevationPreference(1) + object Level2 : FeedsTopBarTonalElevationPreference(3) + object Level3 : FeedsTopBarTonalElevationPreference(6) + object Level4 : FeedsTopBarTonalElevationPreference(8) + object Level5 : FeedsTopBarTonalElevationPreference(12) override fun put(context: Context, scope: CoroutineScope) { scope.launch(Dispatchers.IO) { context.dataStore.put( - DataStoreKeys.ArticleListTonalElevation, + DataStoreKeys.FeedsTopBarTonalElevation, value ) } @@ -41,9 +41,9 @@ sealed class ArticleListTonalElevationPreference(val value: Int) : Preference() val default = Level0 val values = listOf(Level0, Level1, Level2, Level3, Level4, Level5) - val Context.articleListTonalElevation: Flow + val Context.feedsTopBarTonalElevation: Flow get() = this.dataStore.data.map { - when (it[DataStoreKeys.ArticleListTonalElevation.key]) { + when (it[DataStoreKeys.FeedsTopBarTonalElevation.key]) { 0 -> Level0 1 -> Level1 3 -> Level2 diff --git a/app/src/main/java/me/ash/reader/data/preference/ArticleListFeedNamePreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListDatePreference.kt similarity index 62% rename from app/src/main/java/me/ash/reader/data/preference/ArticleListFeedNamePreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FlowArticleListDatePreference.kt index 9269d4b..119096c 100644 --- a/app/src/main/java/me/ash/reader/data/preference/ArticleListFeedNamePreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListDatePreference.kt @@ -10,14 +10,14 @@ import me.ash.reader.ui.ext.DataStoreKeys import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put -sealed class ArticleListFeedNamePreference(val value: Boolean) : Preference() { - object ON : ArticleListFeedNamePreference(true) - object OFF : ArticleListFeedNamePreference(false) +sealed class FlowArticleListDatePreference(val value: Boolean) : Preference() { + object ON : FlowArticleListDatePreference(true) + object OFF : FlowArticleListDatePreference(false) override fun put(context: Context, scope: CoroutineScope) { scope.launch(Dispatchers.IO) { context.dataStore.put( - DataStoreKeys.ArticleListFeedName, + DataStoreKeys.FlowArticleListDate, value ) } @@ -27,9 +27,9 @@ sealed class ArticleListFeedNamePreference(val value: Boolean) : Preference() { val default = ON val values = listOf(ON, OFF) - val Context.articleListFeedName: Flow + val Context.flowArticleListDate: Flow get() = this.dataStore.data.map { - when (it[DataStoreKeys.ArticleListFeedName.key]) { + when (it[DataStoreKeys.FlowArticleListDate.key]) { true -> ON false -> OFF else -> default @@ -38,8 +38,8 @@ sealed class ArticleListFeedNamePreference(val value: Boolean) : Preference() { } } -operator fun ArticleListFeedNamePreference.not(): ArticleListFeedNamePreference = +operator fun FlowArticleListDatePreference.not(): FlowArticleListDatePreference = when (value) { - true -> ArticleListFeedNamePreference.OFF - false -> ArticleListFeedNamePreference.ON + true -> FlowArticleListDatePreference.OFF + false -> FlowArticleListDatePreference.ON } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/ArticleListFeedIconPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListDescPreference.kt similarity index 61% rename from app/src/main/java/me/ash/reader/data/preference/ArticleListFeedIconPreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FlowArticleListDescPreference.kt index 796aa61..a1f483f 100644 --- a/app/src/main/java/me/ash/reader/data/preference/ArticleListFeedIconPreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListDescPreference.kt @@ -10,14 +10,14 @@ import me.ash.reader.ui.ext.DataStoreKeys import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put -sealed class ArticleListFeedIconPreference(val value: Boolean) : Preference() { - object ON : ArticleListFeedIconPreference(true) - object OFF : ArticleListFeedIconPreference(false) +sealed class FlowArticleListDescPreference(val value: Boolean) : Preference() { + object ON : FlowArticleListDescPreference(true) + object OFF : FlowArticleListDescPreference(false) override fun put(context: Context, scope: CoroutineScope) { scope.launch(Dispatchers.IO) { context.dataStore.put( - DataStoreKeys.ArticleListFeedIcon, + DataStoreKeys.FlowArticleListDesc, value ) } @@ -27,9 +27,9 @@ sealed class ArticleListFeedIconPreference(val value: Boolean) : Preference() { val default = ON val values = listOf(ON, OFF) - val Context.articleListFeedIcon: Flow + val Context.flowArticleListDesc: Flow get() = this.dataStore.data.map { - when (it[DataStoreKeys.ArticleListFeedIcon.key]) { + when (it[DataStoreKeys.FlowArticleListDesc.key]) { true -> ON false -> OFF else -> default @@ -38,8 +38,8 @@ sealed class ArticleListFeedIconPreference(val value: Boolean) : Preference() { } } -operator fun ArticleListFeedIconPreference.not(): ArticleListFeedIconPreference = +operator fun FlowArticleListDescPreference.not(): FlowArticleListDescPreference = when (value) { - true -> ArticleListFeedIconPreference.OFF - false -> ArticleListFeedIconPreference.ON + true -> FlowArticleListDescPreference.OFF + false -> FlowArticleListDescPreference.ON } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FlowArticleListFeedIconPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListFeedIconPreference.kt new file mode 100644 index 0000000..f00e873 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListFeedIconPreference.kt @@ -0,0 +1,45 @@ +package me.ash.reader.data.preference + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 FlowArticleListFeedIconPreference(val value: Boolean) : Preference() { + object ON : FlowArticleListFeedIconPreference(true) + object OFF : FlowArticleListFeedIconPreference(false) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch(Dispatchers.IO) { + context.dataStore.put( + DataStoreKeys.FlowArticleListFeedIcon, + value + ) + } + } + + companion object { + val default = ON + val values = listOf(ON, OFF) + + val Context.flowArticleListFeedIcon: Flow + get() = this.dataStore.data.map { + when (it[DataStoreKeys.FlowArticleListFeedIcon.key]) { + true -> ON + false -> OFF + else -> default + } + } + } +} + +operator fun FlowArticleListFeedIconPreference.not(): FlowArticleListFeedIconPreference = + when (value) { + true -> FlowArticleListFeedIconPreference.OFF + false -> FlowArticleListFeedIconPreference.ON + } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FlowArticleListFeedNamePreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListFeedNamePreference.kt new file mode 100644 index 0000000..4fae700 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListFeedNamePreference.kt @@ -0,0 +1,45 @@ +package me.ash.reader.data.preference + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 FlowArticleListFeedNamePreference(val value: Boolean) : Preference() { + object ON : FlowArticleListFeedNamePreference(true) + object OFF : FlowArticleListFeedNamePreference(false) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch(Dispatchers.IO) { + context.dataStore.put( + DataStoreKeys.FlowArticleListFeedName, + value + ) + } + } + + companion object { + val default = ON + val values = listOf(ON, OFF) + + val Context.flowArticleListFeedName: Flow + get() = this.dataStore.data.map { + when (it[DataStoreKeys.FlowArticleListFeedName.key]) { + true -> ON + false -> OFF + else -> default + } + } + } +} + +operator fun FlowArticleListFeedNamePreference.not(): FlowArticleListFeedNamePreference = + when (value) { + true -> FlowArticleListFeedNamePreference.OFF + false -> FlowArticleListFeedNamePreference.ON + } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/ArticleListDescPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListImagePreference.kt similarity index 59% rename from app/src/main/java/me/ash/reader/data/preference/ArticleListDescPreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FlowArticleListImagePreference.kt index 10dc06a..ef7d776 100644 --- a/app/src/main/java/me/ash/reader/data/preference/ArticleListDescPreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListImagePreference.kt @@ -10,14 +10,14 @@ import me.ash.reader.ui.ext.DataStoreKeys import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put -sealed class ArticleListDescPreference(val value: Boolean) : Preference() { - object ON : ArticleListDescPreference(true) - object OFF : ArticleListDescPreference(false) +sealed class FlowArticleListImagePreference(val value: Boolean) : Preference() { + object ON : FlowArticleListImagePreference(true) + object OFF : FlowArticleListImagePreference(false) override fun put(context: Context, scope: CoroutineScope) { scope.launch(Dispatchers.IO) { context.dataStore.put( - DataStoreKeys.ArticleListDesc, + DataStoreKeys.FlowArticleListImage, value ) } @@ -27,9 +27,9 @@ sealed class ArticleListDescPreference(val value: Boolean) : Preference() { val default = ON val values = listOf(ON, OFF) - val Context.articleListDesc: Flow + val Context.flowArticleListImage: Flow get() = this.dataStore.data.map { - when (it[DataStoreKeys.ArticleListDesc.key]) { + when (it[DataStoreKeys.FlowArticleListImage.key]) { true -> ON false -> OFF else -> default @@ -38,8 +38,8 @@ sealed class ArticleListDescPreference(val value: Boolean) : Preference() { } } -operator fun ArticleListDescPreference.not(): ArticleListDescPreference = +operator fun FlowArticleListImagePreference.not(): FlowArticleListImagePreference = when (value) { - true -> ArticleListDescPreference.OFF - false -> ArticleListDescPreference.ON + true -> FlowArticleListImagePreference.OFF + false -> FlowArticleListImagePreference.ON } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FlowArticleListTonalElevationPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListTonalElevationPreference.kt new file mode 100644 index 0000000..e6febf7 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FlowArticleListTonalElevationPreference.kt @@ -0,0 +1,57 @@ +package me.ash.reader.data.preference + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 FlowArticleListTonalElevationPreference(val value: Int) : Preference() { + object Level0 : FlowArticleListTonalElevationPreference(0) + object Level1 : FlowArticleListTonalElevationPreference(1) + object Level2 : FlowArticleListTonalElevationPreference(3) + object Level3 : FlowArticleListTonalElevationPreference(6) + object Level4 : FlowArticleListTonalElevationPreference(8) + object Level5 : FlowArticleListTonalElevationPreference(12) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch(Dispatchers.IO) { + context.dataStore.put( + DataStoreKeys.FlowArticleListTonalElevation, + value + ) + } + } + + fun getDesc(context: Context): String = + when (this) { + Level0 -> "Level 0 (0dp)" + Level1 -> "Level 1 (1dp)" + Level2 -> "Level 2 (3dp)" + Level3 -> "Level 3 (6dp)" + Level4 -> "Level 4 (8dp)" + Level5 -> "Level 5 (12dp)" + } + + companion object { + val default = Level0 + val values = listOf(Level0, Level1, Level2, Level3, Level4, Level5) + + val Context.flowArticleListTonalElevation: Flow + get() = this.dataStore.data.map { + when (it[DataStoreKeys.FlowArticleListTonalElevation.key]) { + 0 -> Level0 + 1 -> Level1 + 3 -> Level2 + 6 -> Level3 + 8 -> Level4 + 12 -> Level5 + else -> default + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FilterBarFilledPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarFilledPreference.kt similarity index 59% rename from app/src/main/java/me/ash/reader/data/preference/FilterBarFilledPreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FlowFilterBarFilledPreference.kt index c6265da..367507d 100644 --- a/app/src/main/java/me/ash/reader/data/preference/FilterBarFilledPreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarFilledPreference.kt @@ -10,14 +10,14 @@ import me.ash.reader.ui.ext.DataStoreKeys import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put -sealed class FilterBarFilledPreference(val value: Boolean) : Preference() { - object ON : FilterBarFilledPreference(true) - object OFF : FilterBarFilledPreference(false) +sealed class FlowFilterBarFilledPreference(val value: Boolean) : Preference() { + object ON : FlowFilterBarFilledPreference(true) + object OFF : FlowFilterBarFilledPreference(false) override fun put(context: Context, scope: CoroutineScope) { scope.launch(Dispatchers.IO) { context.dataStore.put( - DataStoreKeys.FilterBarFilled, + DataStoreKeys.FlowFilterBarFilled, value ) } @@ -27,9 +27,9 @@ sealed class FilterBarFilledPreference(val value: Boolean) : Preference() { val default = OFF val values = listOf(ON, OFF) - val Context.filterBarFilled: Flow + val Context.flowFilterBarFilled: Flow get() = this.dataStore.data.map { - when (it[DataStoreKeys.FilterBarFilled.key]) { + when (it[DataStoreKeys.FlowFilterBarFilled.key]) { true -> ON false -> OFF else -> default @@ -38,8 +38,8 @@ sealed class FilterBarFilledPreference(val value: Boolean) : Preference() { } } -operator fun FilterBarFilledPreference.not(): FilterBarFilledPreference = +operator fun FlowFilterBarFilledPreference.not(): FlowFilterBarFilledPreference = when (value) { - true -> FilterBarFilledPreference.OFF - false -> FilterBarFilledPreference.ON + true -> FlowFilterBarFilledPreference.OFF + false -> FlowFilterBarFilledPreference.ON } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FilterBarPaddingPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarPaddingPreference.kt similarity index 72% rename from app/src/main/java/me/ash/reader/data/preference/FilterBarPaddingPreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FlowFilterBarPaddingPreference.kt index 516453f..b564ff3 100644 --- a/app/src/main/java/me/ash/reader/data/preference/FilterBarPaddingPreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarPaddingPreference.kt @@ -1,7 +1,6 @@ package me.ash.reader.data.preference import android.content.Context -import android.util.Log import androidx.compose.runtime.Immutable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -13,17 +12,17 @@ import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put @Immutable -object FilterBarPaddingPreference { +object FlowFilterBarPaddingPreference { const val default = 0 - val Context.filterBarPadding: Flow + val Context.flowFilterBarPadding: Flow get() = this.dataStore.data.map { - it[DataStoreKeys.FilterBarPadding.key] ?: 0 + it[DataStoreKeys.FlowFilterBarPadding.key] ?: default } fun put(context: Context, scope: CoroutineScope, value: Int) { scope.launch(Dispatchers.IO) { - context.dataStore.put(DataStoreKeys.FilterBarPadding, value) + context.dataStore.put(DataStoreKeys.FlowFilterBarPadding, value) } } } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FilterBarStylePreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarStylePreference.kt similarity index 59% rename from app/src/main/java/me/ash/reader/data/preference/FilterBarStylePreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FlowFilterBarStylePreference.kt index 50e6c7b..10a5c9c 100644 --- a/app/src/main/java/me/ash/reader/data/preference/FilterBarStylePreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarStylePreference.kt @@ -6,19 +6,20 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map 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 FilterBarStylePreference(val value: Int) : Preference() { - object Icon : FilterBarStylePreference(0) - object IconLabel : FilterBarStylePreference(1) - object IconLabelOnlySelected : FilterBarStylePreference(2) +sealed class FlowFilterBarStylePreference(val value: Int) : Preference() { + object Icon : FlowFilterBarStylePreference(0) + object IconLabel : FlowFilterBarStylePreference(1) + object IconLabelOnlySelected : FlowFilterBarStylePreference(2) override fun put(context: Context, scope: CoroutineScope) { scope.launch(Dispatchers.IO) { context.dataStore.put( - DataStoreKeys.FilterBarStyle, + DataStoreKeys.FlowFilterBarStyle, value ) } @@ -26,18 +27,18 @@ sealed class FilterBarStylePreference(val value: Int) : Preference() { fun getDesc(context: Context): String = when (this) { - Icon -> "图标" - IconLabel -> "图标 + 标签" - IconLabelOnlySelected -> "图标 + 标签(仅选中时)" + Icon -> context.getString(R.string.icons) + IconLabel -> context.getString(R.string.icons_and_labels) + IconLabelOnlySelected -> context.getString(R.string.icons_and_label_only_selected) } companion object { val default = Icon val values = listOf(Icon, IconLabel, IconLabelOnlySelected) - val Context.filterBarStyle: Flow + val Context.flowFilterBarStyle: Flow get() = this.dataStore.data.map { - when (it[DataStoreKeys.FilterBarStyle.key]) { + when (it[DataStoreKeys.FlowFilterBarStyle.key]) { 0 -> Icon 1 -> IconLabel 2 -> IconLabelOnlySelected diff --git a/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarTonalElevationPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarTonalElevationPreference.kt new file mode 100644 index 0000000..620b2f7 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/FlowFilterBarTonalElevationPreference.kt @@ -0,0 +1,57 @@ +package me.ash.reader.data.preference + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 FlowFilterBarTonalElevationPreference(val value: Int) : Preference() { + object Level0 : FlowFilterBarTonalElevationPreference(0) + object Level1 : FlowFilterBarTonalElevationPreference(1) + object Level2 : FlowFilterBarTonalElevationPreference(3) + object Level3 : FlowFilterBarTonalElevationPreference(6) + object Level4 : FlowFilterBarTonalElevationPreference(8) + object Level5 : FlowFilterBarTonalElevationPreference(12) + + override fun put(context: Context, scope: CoroutineScope) { + scope.launch(Dispatchers.IO) { + context.dataStore.put( + DataStoreKeys.FlowFilterBarTonalElevation, + value + ) + } + } + + fun getDesc(context: Context): String = + when (this) { + Level0 -> "Level 0 (0dp)" + Level1 -> "Level 1 (1dp)" + Level2 -> "Level 2 (3dp)" + Level3 -> "Level 3 (6dp)" + Level4 -> "Level 4 (8dp)" + Level5 -> "Level 5 (12dp)" + } + + companion object { + val default = Level0 + val values = listOf(Level0, Level1, Level2, Level3, Level4, Level5) + + val Context.flowFilterBarTonalElevation: Flow + get() = this.dataStore.data.map { + when (it[DataStoreKeys.FlowFilterBarTonalElevation.key]) { + 0 -> Level0 + 1 -> Level1 + 3 -> Level2 + 6 -> Level3 + 8 -> Level4 + 12 -> Level5 + else -> default + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/data/preference/FilterBarTonalElevationPreference.kt b/app/src/main/java/me/ash/reader/data/preference/FlowTopBarTonalElevationPreference.kt similarity index 66% rename from app/src/main/java/me/ash/reader/data/preference/FilterBarTonalElevationPreference.kt rename to app/src/main/java/me/ash/reader/data/preference/FlowTopBarTonalElevationPreference.kt index 6c6fced..a01e263 100644 --- a/app/src/main/java/me/ash/reader/data/preference/FilterBarTonalElevationPreference.kt +++ b/app/src/main/java/me/ash/reader/data/preference/FlowTopBarTonalElevationPreference.kt @@ -10,18 +10,18 @@ import me.ash.reader.ui.ext.DataStoreKeys import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put -sealed class FilterBarTonalElevationPreference(val value: Int) : Preference() { - object Level0 : FilterBarTonalElevationPreference(0) - object Level1 : FilterBarTonalElevationPreference(1) - object Level2 : FilterBarTonalElevationPreference(3) - object Level3 : FilterBarTonalElevationPreference(6) - object Level4 : FilterBarTonalElevationPreference(8) - object Level5 : FilterBarTonalElevationPreference(12) +sealed class FlowTopBarTonalElevationPreference(val value: Int) : Preference() { + object Level0 : FlowTopBarTonalElevationPreference(0) + object Level1 : FlowTopBarTonalElevationPreference(1) + object Level2 : FlowTopBarTonalElevationPreference(3) + object Level3 : FlowTopBarTonalElevationPreference(6) + object Level4 : FlowTopBarTonalElevationPreference(8) + object Level5 : FlowTopBarTonalElevationPreference(12) override fun put(context: Context, scope: CoroutineScope) { scope.launch(Dispatchers.IO) { context.dataStore.put( - DataStoreKeys.FilterBarTonalElevation, + DataStoreKeys.FlowTopBarTonalElevation, value ) } @@ -41,9 +41,9 @@ sealed class FilterBarTonalElevationPreference(val value: Int) : Preference() { val default = Level0 val values = listOf(Level0, Level1, Level2, Level3, Level4, Level5) - val Context.filterBarTonalElevation: Flow + val Context.flowTopBarTonalElevation: Flow get() = this.dataStore.data.map { - when (it[DataStoreKeys.FilterBarTonalElevation.key]) { + when (it[DataStoreKeys.FlowTopBarTonalElevation.key]) { 0 -> Level0 1 -> Level1 3 -> Level2 diff --git a/app/src/main/java/me/ash/reader/data/preference/ThemePreference.kt b/app/src/main/java/me/ash/reader/data/preference/ThemePreference.kt new file mode 100644 index 0000000..3f006a7 --- /dev/null +++ b/app/src/main/java/me/ash/reader/data/preference/ThemePreference.kt @@ -0,0 +1,28 @@ +package me.ash.reader.data.preference + +import android.content.Context +import androidx.compose.runtime.Immutable +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +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 +object ThemePreference { + const val default = 5 + + val Context.Theme: Flow + get() = this.dataStore.data.map { + it[DataStoreKeys.ThemeIndex.key] ?: default + } + + fun put(context: Context, scope: CoroutineScope, value: Int) { + scope.launch(Dispatchers.IO) { + context.dataStore.put(DataStoreKeys.ThemeIndex, value) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/component/Tips.kt b/app/src/main/java/me/ash/reader/ui/component/Tips.kt new file mode 100644 index 0000000..bab7833 --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/component/Tips.kt @@ -0,0 +1,38 @@ +package me.ash.reader.ui.component + +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import me.ash.reader.R + +@Composable +fun Tips( + modifier: Modifier = Modifier, + text: String, +) { + Column( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 24.dp, vertical = 16.dp), + ) { + Icon( + imageVector = Icons.Outlined.Info, + contentDescription = stringResource(R.string.tips_and_support), + tint = MaterialTheme.colorScheme.onSurfaceVariant, + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = text, + style = MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.Light), + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/ext/ColorScheme.kt b/app/src/main/java/me/ash/reader/ui/ext/ColorScheme.kt index d7fb5f5..1e2276f 100644 --- a/app/src/main/java/me/ash/reader/ui/ext/ColorScheme.kt +++ b/app/src/main/java/me/ash/reader/ui/ext/ColorScheme.kt @@ -9,8 +9,16 @@ import kotlin.math.ln fun ColorScheme.surfaceColorAtElevation( elevation: Dp, + color: Color = surface, +): Color = color.atElevation(surfaceTint, elevation) + +fun Color.atElevation( + sourceColor: Color, + elevation: Dp, ): Color { - if (elevation == 0.dp) return surface - val alpha = ((4.5f * ln(elevation.value + 1)) + 2f) / 100f - return primary.copy(alpha = alpha).compositeOver(surface) -} \ No newline at end of file + if (elevation == 0.dp) return this + return sourceColor.copy(alpha = elevation.alphaLN(constant = 4.5f)).compositeOver(this) +} + +fun Dp.alphaLN(constant: Float = 1f, weight: Float = 0f): Float = + ((constant * ln(value + 1) + weight) + 2f) / 100f diff --git a/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt b/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt index 0dd5463..687f4be 100644 --- a/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt +++ b/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt @@ -31,8 +31,6 @@ val Context.currentAccountId: Int get() = this.dataStore.get(DataStoreKeys.CurrentAccountId)!! val Context.currentAccountType: Int get() = this.dataStore.get(DataStoreKeys.CurrentAccountType)!! -val Context.themeIndex: Int - get() = this.dataStore.get(DataStoreKeys.ThemeIndex) ?: 5 val Context.customPrimaryColor: String get() = this.dataStore.get(DataStoreKeys.CustomPrimaryColor) ?: "" @@ -130,54 +128,94 @@ sealed class DataStoreKeys { get() = stringPreferencesKey("customPrimaryColor") } - object FilterBarStyle : DataStoreKeys() { + object FeedsFilterBarStyle : DataStoreKeys() { override val key: Preferences.Key - get() = intPreferencesKey("filterBarStyle") + get() = intPreferencesKey("feedsFilterBarStyle") } - object FilterBarFilled : DataStoreKeys() { + object FeedsFilterBarFilled : DataStoreKeys() { override val key: Preferences.Key - get() = booleanPreferencesKey("filterBarFilled") + get() = booleanPreferencesKey("feedsFilterBarFilled") } - object FilterBarPadding : DataStoreKeys() { + object FeedsFilterBarPadding : DataStoreKeys() { override val key: Preferences.Key - get() = intPreferencesKey("filterBarPadding") + get() = intPreferencesKey("feedsFilterBarPadding") } - object FilterBarTonalElevation : DataStoreKeys() { + object FeedsFilterBarTonalElevation : DataStoreKeys() { override val key: Preferences.Key - get() = intPreferencesKey("filterBarTonalElevation") + get() = intPreferencesKey("feedsFilterBarTonalElevation") } - object ArticleListFeedIcon : DataStoreKeys() { - override val key: Preferences.Key - get() = booleanPreferencesKey("articleListFeedIcon") - } - - object ArticleListFeedName : DataStoreKeys() { - override val key: Preferences.Key - get() = booleanPreferencesKey("articleListFeedName") - } - - object ArticleListImage : DataStoreKeys() { - override val key: Preferences.Key - get() = booleanPreferencesKey("articleListImage") - } - - object ArticleListDesc : DataStoreKeys() { - override val key: Preferences.Key - get() = booleanPreferencesKey("articleListDesc") - } - - object ArticleListDate : DataStoreKeys() { - override val key: Preferences.Key - get() = booleanPreferencesKey("articleListDate") - } - - object ArticleListTonalElevation : DataStoreKeys() { + object FeedsTopBarTonalElevation : DataStoreKeys() { override val key: Preferences.Key - get() = intPreferencesKey("articleListTonalElevation") + get() = intPreferencesKey("feedsTopBarTonalElevation") + } + + object FeedsGroupListExpand : DataStoreKeys() { + override val key: Preferences.Key + get() = booleanPreferencesKey("feedsGroupListExpand") + } + + object FeedsGroupListTonalElevation : DataStoreKeys() { + override val key: Preferences.Key + get() = intPreferencesKey("feedsGroupListTonalElevation") + } + + object FlowFilterBarStyle : DataStoreKeys() { + override val key: Preferences.Key + get() = intPreferencesKey("flowFilterBarStyle") + } + + object FlowFilterBarFilled : DataStoreKeys() { + override val key: Preferences.Key + get() = booleanPreferencesKey("flowFilterBarFilled") + } + + object FlowFilterBarPadding : DataStoreKeys() { + override val key: Preferences.Key + get() = intPreferencesKey("flowFilterBarPadding") + } + + object FlowFilterBarTonalElevation : DataStoreKeys() { + override val key: Preferences.Key + get() = intPreferencesKey("flowFilterBarTonalElevation") + } + + object FlowTopBarTonalElevation : DataStoreKeys() { + override val key: Preferences.Key + get() = intPreferencesKey("flowTopBarTonalElevation") + } + + object FlowArticleListFeedIcon : DataStoreKeys() { + override val key: Preferences.Key + get() = booleanPreferencesKey("flowArticleListFeedIcon") + } + + object FlowArticleListFeedName : DataStoreKeys() { + override val key: Preferences.Key + get() = booleanPreferencesKey("flowArticleListFeedName") + } + + object FlowArticleListImage : DataStoreKeys() { + override val key: Preferences.Key + get() = booleanPreferencesKey("flowArticleListImage") + } + + object FlowArticleListDesc : DataStoreKeys() { + override val key: Preferences.Key + get() = booleanPreferencesKey("flowArticleListDesc") + } + + object FlowArticleListDate : DataStoreKeys() { + override val key: Preferences.Key + get() = booleanPreferencesKey("flowArticleListDate") + } + + object FlowArticleListTonalElevation : DataStoreKeys() { + override val key: Preferences.Key + get() = intPreferencesKey("flowArticleListTonalElevation") } object InitialPage : DataStoreKeys() { diff --git a/app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt b/app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt index 8d8208e..76453a5 100644 --- a/app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt +++ b/app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt @@ -22,6 +22,7 @@ import me.ash.reader.ui.page.home.flow.FlowPage import me.ash.reader.ui.page.home.read.ReadPage import me.ash.reader.ui.page.settings.SettingsPage import me.ash.reader.ui.page.settings.color.ColorAndStyle +import me.ash.reader.ui.page.settings.color.feeds.FeedsPageStyle import me.ash.reader.ui.page.settings.color.flow.FlowPageStyle import me.ash.reader.ui.page.settings.interaction.Interaction import me.ash.reader.ui.page.settings.tips.TipsAndSupport @@ -127,6 +128,9 @@ fun HomeEntry( animatedComposable(route = RouteName.COLOR_AND_STYLE) { ColorAndStyle(navController) } + animatedComposable(route = RouteName.FEEDS_PAGE_STYLE) { + FeedsPageStyle(navController) + } animatedComposable(route = RouteName.FLOW_PAGE_STYLE) { FlowPageStyle(navController) } diff --git a/app/src/main/java/me/ash/reader/ui/page/common/RouteName.kt b/app/src/main/java/me/ash/reader/ui/page/common/RouteName.kt index 51aba6a..baf917a 100644 --- a/app/src/main/java/me/ash/reader/ui/page/common/RouteName.kt +++ b/app/src/main/java/me/ash/reader/ui/page/common/RouteName.kt @@ -14,6 +14,7 @@ object RouteName { // Color & Style const val COLOR_AND_STYLE = "color_and_style" + const val FEEDS_PAGE_STYLE = "feeds_page_style" const val FLOW_PAGE_STYLE = "flow_page_style" // Interaction diff --git a/app/src/main/java/me/ash/reader/ui/page/home/FilterBar.kt b/app/src/main/java/me/ash/reader/ui/page/home/FilterBar.kt index 341d4fb..75b517a 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/FilterBar.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/FilterBar.kt @@ -6,20 +6,11 @@ import androidx.compose.foundation.layout.width import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.Dp import com.google.accompanist.pager.ExperimentalPagerApi import me.ash.reader.data.entity.Filter -import me.ash.reader.data.preference.FilterBarFilledPreference -import me.ash.reader.data.preference.FilterBarFilledPreference.Companion.filterBarFilled -import me.ash.reader.data.preference.FilterBarPaddingPreference -import me.ash.reader.data.preference.FilterBarPaddingPreference.filterBarPadding -import me.ash.reader.data.preference.FilterBarStylePreference -import me.ash.reader.data.preference.FilterBarStylePreference.Companion.filterBarStyle -import me.ash.reader.data.preference.FilterBarTonalElevationPreference -import me.ash.reader.data.preference.FilterBarTonalElevationPreference.Companion.filterBarTonalElevation -import me.ash.reader.ui.ext.collectAsStateValue +import me.ash.reader.data.preference.FlowFilterBarStylePreference import me.ash.reader.ui.ext.getName import me.ash.reader.ui.theme.palette.onDark @@ -28,23 +19,18 @@ import me.ash.reader.ui.theme.palette.onDark fun FilterBar( modifier: Modifier = Modifier, filter: Filter, + filterBarStyle: Int, + filterBarFilled: Boolean, + filterBarPadding: Dp, + filterBarTonalElevation: Dp, filterOnClick: (Filter) -> Unit = {}, ) { val view = LocalView.current - val context = LocalContext.current - val filterBarStyle = - context.filterBarStyle.collectAsStateValue(initial = FilterBarStylePreference.default) - val filterBarFilled = - context.filterBarFilled.collectAsStateValue(initial = FilterBarFilledPreference.default) - val filterBarPadding = - context.filterBarPadding.collectAsStateValue(initial = FilterBarPaddingPreference.default) - val filterBarTonalElevation = - context.filterBarTonalElevation.collectAsStateValue(initial = FilterBarTonalElevationPreference.default) NavigationBar( - tonalElevation = filterBarTonalElevation.value.dp, + tonalElevation = filterBarTonalElevation, ) { - Spacer(modifier = Modifier.width(filterBarPadding.dp)) + Spacer(modifier = Modifier.width(filterBarPadding)) listOf( Filter.Starred, Filter.Unread, @@ -53,13 +39,14 @@ fun FilterBar( NavigationBarItem( // modifier = Modifier.height(60.dp), alwaysShowLabel = when (filterBarStyle) { - is FilterBarStylePreference.Icon -> false - is FilterBarStylePreference.IconLabel -> true - is FilterBarStylePreference.IconLabelOnlySelected -> false + FlowFilterBarStylePreference.Icon.value -> false + FlowFilterBarStylePreference.IconLabel.value -> true + FlowFilterBarStylePreference.IconLabelOnlySelected.value -> false + else -> false }, icon = { Icon( - imageVector = if (filter == item && filterBarFilled.value) { + imageVector = if (filter == item && filterBarFilled) { item.iconFilled } else { item.iconOutline @@ -67,7 +54,7 @@ fun FilterBar( contentDescription = item.getName() ) }, - label = if (filterBarStyle is FilterBarStylePreference.Icon) { + label = if (filterBarStyle == FlowFilterBarStylePreference.Icon.value) { null } else { { @@ -92,6 +79,6 @@ fun FilterBar( ) ) } - Spacer(modifier = Modifier.width(filterBarPadding.dp)) + Spacer(modifier = Modifier.width(filterBarPadding)) } } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/home/HomeViewModel.kt b/app/src/main/java/me/ash/reader/ui/page/home/HomeViewModel.kt index e2ea70b..e787100 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/HomeViewModel.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/HomeViewModel.kt @@ -62,7 +62,7 @@ class HomeViewModel @Inject constructor( private fun fetchArticles() { _viewState.update { it.copy( - pagingData = Pager(PagingConfig(pageSize = 10)) { + pagingData = Pager(PagingConfig(pageSize = 15)) { if (_viewState.value.searchContent.isNotBlank()) { rssRepository.get().searchArticles( content = _viewState.value.searchContent.trim(), diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedItem.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedItem.kt index db5c130..87284a2 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedItem.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedItem.kt @@ -16,11 +16,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalView import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import me.ash.reader.data.entity.Feed import me.ash.reader.ui.page.home.feeds.option.feed.FeedOptionViewAction import me.ash.reader.ui.page.home.feeds.option.feed.FeedOptionViewModel +import kotlin.math.ln @OptIn( androidx.compose.foundation.ExperimentalFoundationApi::class, @@ -31,6 +33,7 @@ fun FeedItem( modifier: Modifier = Modifier, feed: Feed, feedOptionViewModel: FeedOptionViewModel = hiltViewModel(), + tonalElevation: Dp, onClick: () -> Unit = {}, ) { val view = LocalView.current @@ -76,18 +79,18 @@ fun FeedItem( ) } if (feed.important ?: 0 != 0) { - Row() { - Badge( - containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.24f), - contentColor = MaterialTheme.colorScheme.outline, - content = { - Text( - text = feed.important.toString(), - style = MaterialTheme.typography.labelSmall - ) - }, - ) - } + Badge( + containerColor = MaterialTheme.colorScheme.surfaceTint.copy( + alpha = (ln(tonalElevation.value + 1.4f) + 2f) / 100f + ), + contentColor = MaterialTheme.colorScheme.outline, + content = { + Text( + text = feed.important.toString(), + style = MaterialTheme.typography.labelSmall + ) + }, + ) } } } diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt index e9bc7f0..db5ac4c 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt @@ -45,6 +45,8 @@ import me.ash.reader.ui.page.home.feeds.option.group.GroupOptionDrawer import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeDialog import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeViewAction import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeViewModel +import me.ash.reader.ui.theme.* +import me.ash.reader.ui.theme.palette.onDark @SuppressLint("FlowOperatorInvokedInComposition") @OptIn( @@ -59,6 +61,14 @@ fun FeedsPage( homeViewModel: HomeViewModel, ) { val context = LocalContext.current + val topBarTonalElevation = LocalFeedsTopBarTonalElevation.current + val groupListTonalElevation = LocalFeedsGroupListTonalElevation.current + val groupListExpand = LocalFeedsGroupListExpand.current + val filterBarStyle = LocalFeedsFilterBarStyle.current + val filterBarFilled = LocalFeedsFilterBarFilled.current + val filterBarPadding = LocalFeedsFilterBarPadding.current + val filterBarTonalElevation = LocalFeedsFilterBarTonalElevation.current + val feedsViewState = feedsViewModel.viewState.collectAsStateValue() val filterState = homeViewModel.filterState.collectAsStateValue() @@ -117,11 +127,19 @@ fun FeedsPage( Scaffold( modifier = Modifier - .background(MaterialTheme.colorScheme.surface) + .background(MaterialTheme.colorScheme.surfaceColorAtElevation(topBarTonalElevation.dp)) .statusBarsPadding() .navigationBarsPadding(), + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + groupListTonalElevation.dp + ) onDark MaterialTheme.colorScheme.surface, topBar = { SmallTopAppBar( + colors = TopAppBarDefaults.smallTopAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + topBarTonalElevation.dp + ), + ), title = {}, navigationIcon = { FeedbackIconButton( @@ -204,6 +222,8 @@ fun FeedsPage( // Crossfade(targetState = groupWithFeed) { groupWithFeed -> Column { GroupItem( + isExpanded = groupListExpand, + tonalElevation = groupListTonalElevation.dp, group = groupWithFeed.group, feeds = groupWithFeed.feeds, groupOnClick = { @@ -242,15 +262,18 @@ fun FeedsPage( bottomBar = { FilterBar( filter = filterState.filter, - filterOnClick = { - filterChange( - navController = navController, - homeViewModel = homeViewModel, - filterState = filterState.copy(filter = it), - isNavigate = false, - ) - }, - ) + filterBarStyle = filterBarStyle, + filterBarFilled = filterBarFilled, + filterBarPadding = filterBarPadding.dp, + filterBarTonalElevation = filterBarTonalElevation.dp, + ) { + filterChange( + navController = navController, + homeViewModel = homeViewModel, + filterState = filterState.copy(filter = it), + isNavigate = false, + ) + } } ) diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/GroupItem.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/GroupItem.kt index 3f32954..3563a00 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/GroupItem.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/GroupItem.kt @@ -22,11 +22,13 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import me.ash.reader.R import me.ash.reader.data.entity.Feed import me.ash.reader.data.entity.Group +import me.ash.reader.ui.ext.alphaLN import me.ash.reader.ui.page.home.feeds.option.group.GroupOptionViewAction import me.ash.reader.ui.page.home.feeds.option.group.GroupOptionViewModel @@ -34,6 +36,7 @@ import me.ash.reader.ui.page.home.feeds.option.group.GroupOptionViewModel @Composable fun GroupItem( modifier: Modifier = Modifier, + tonalElevation: Dp, group: Group, feeds: List, isExpanded: Boolean = true, @@ -50,7 +53,9 @@ fun GroupItem( .fillMaxWidth() .padding(horizontal = 16.dp) .clip(RoundedCornerShape(32.dp)) - .background(MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.14f)) + .background( + MaterialTheme.colorScheme.secondary.copy(alpha = tonalElevation.alphaLN(weight = 1.2f)) + ) .combinedClickable( onClick = { groupOnClick() @@ -82,7 +87,11 @@ fun GroupItem( .padding(end = 20.dp) .size(24.dp) .clip(CircleShape) - .background(MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.24f)) + .background( + MaterialTheme.colorScheme.surfaceTint.copy( + alpha = tonalElevation.alphaLN(weight = 1.4f) + ) + ) .clickable { expanded = !expanded }, @@ -107,6 +116,7 @@ fun GroupItem( FeedItem( modifier = Modifier.padding(horizontal = 20.dp), feed = feed, + tonalElevation = tonalElevation, ) { feedOnClick(feed) } diff --git a/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt b/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt index 640cb8d..c4e30f2 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt @@ -21,14 +21,8 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import me.ash.reader.R import me.ash.reader.data.entity.ArticleWithFeed -import me.ash.reader.data.preference.* -import me.ash.reader.data.preference.ArticleListDatePreference.Companion.articleListDate -import me.ash.reader.data.preference.ArticleListDescPreference.Companion.articleListDesc -import me.ash.reader.data.preference.ArticleListFeedIconPreference.Companion.articleListFeedIcon -import me.ash.reader.data.preference.ArticleListFeedNamePreference.Companion.articleListFeedName -import me.ash.reader.data.preference.ArticleListImagePreference.Companion.articleListImage -import me.ash.reader.ui.ext.collectAsStateValue import me.ash.reader.ui.ext.formatAsString +import me.ash.reader.ui.theme.* @Composable fun ArticleItem( @@ -37,16 +31,11 @@ fun ArticleItem( onClick: (ArticleWithFeed) -> Unit = {}, ) { val context = LocalContext.current - val articleListFeedIcon = - context.articleListFeedIcon.collectAsStateValue(initial = ArticleListFeedIconPreference.default) - val articleListFeedName = - context.articleListFeedName.collectAsStateValue(initial = ArticleListFeedNamePreference.default) - val articleListImage = - context.articleListImage.collectAsStateValue(initial = ArticleListImagePreference.default) - val articleListDesc = - context.articleListDesc.collectAsStateValue(initial = ArticleListDescPreference.default) - val articleListDate = - context.articleListDate.collectAsStateValue(initial = ArticleListDatePreference.default) + val articleListFeedIcon = LocalFlowArticleListFeedIcon.current + val articleListFeedName = LocalFlowArticleListFeedName.current + val articleListImage = LocalFlowArticleListImage.current + val articleListDesc = LocalFlowArticleListDesc.current + val articleListDate = LocalFlowArticleListDate.current Column( modifier = Modifier @@ -62,11 +51,11 @@ fun ArticleItem( verticalAlignment = Alignment.CenterVertically, ) { // Feed name - if (articleListFeedName.value) { + if (articleListFeedName) { Text( modifier = Modifier .weight(1f) - .padding(start = if (articleListFeedIcon.value) 30.dp else 0.dp), + .padding(start = if (articleListFeedIcon) 30.dp else 0.dp), text = articleWithFeed.feed.name, color = MaterialTheme.colorScheme.tertiary, style = MaterialTheme.typography.labelMedium, @@ -75,11 +64,13 @@ fun ArticleItem( ) } - if (articleListDate.value) { + if (articleListDate) { Row( - modifier = Modifier.padding(start = 6.dp), verticalAlignment = Alignment.CenterVertically, ) { + if (!articleListFeedName) { + Spacer(Modifier.width(if (articleListFeedIcon) 30.dp else 0.dp)) + } // Starred if (articleWithFeed.article.isStarred) { Icon( @@ -91,7 +82,7 @@ fun ArticleItem( tint = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f), ) } - + // Date Text( text = articleWithFeed.article.date.formatAsString( @@ -108,7 +99,7 @@ fun ArticleItem( modifier = Modifier.fillMaxWidth(), ) { // Feed icon - if (articleListFeedIcon.value) { + if (articleListFeedIcon) { Row( modifier = Modifier .size(20.dp) @@ -126,11 +117,11 @@ fun ArticleItem( text = articleWithFeed.article.title, color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.titleMedium, - maxLines = if (articleListDesc.value) 2 else 4, + maxLines = if (articleListDesc) 2 else 4, overflow = TextOverflow.Ellipsis, ) // Description - if (articleListDesc.value) { + if (articleListDesc) { Text( text = articleWithFeed.article.shortDescription, color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f), diff --git a/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt index 678cdbd..8ed73cb 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt @@ -27,10 +27,6 @@ import androidx.paging.compose.LazyPagingItems import kotlinx.coroutines.delay import kotlinx.coroutines.launch import me.ash.reader.R -import me.ash.reader.data.preference.ArticleListFeedIconPreference -import me.ash.reader.data.preference.ArticleListFeedIconPreference.Companion.articleListFeedIcon -import me.ash.reader.data.preference.ArticleListTonalElevationPreference -import me.ash.reader.data.preference.ArticleListTonalElevationPreference.Companion.articleListTonalElevation import me.ash.reader.data.repository.SyncWorker.Companion.getIsSyncing import me.ash.reader.ui.component.DisplayText import me.ash.reader.ui.component.FeedbackIconButton @@ -43,6 +39,8 @@ import me.ash.reader.ui.page.home.FilterBar import me.ash.reader.ui.page.home.FilterState import me.ash.reader.ui.page.home.HomeViewAction import me.ash.reader.ui.page.home.HomeViewModel +import me.ash.reader.ui.theme.* +import me.ash.reader.ui.theme.palette.onDark @OptIn( ExperimentalMaterial3Api::class, @@ -59,6 +57,13 @@ fun FlowPage( ) { val context = LocalContext.current val keyboardController = LocalSoftwareKeyboardController.current + val topBarTonalElevation = LocalFlowTopBarTonalElevation.current + val articleListTonalElevation = LocalFlowArticleListTonalElevation.current + val articleListFeedIcon = LocalFlowArticleListFeedIcon.current + val filterBarStyle = LocalFlowFilterBarStyle.current + val filterBarFilled = LocalFlowFilterBarFilled.current + val filterBarPadding = LocalFlowFilterBarPadding.current + val filterBarTonalElevation = LocalFlowFilterBarTonalElevation.current val scope = rememberCoroutineScope() val focusRequester = remember { FocusRequester() } @@ -70,11 +75,6 @@ fun FlowPage( val homeViewState = homeViewModel.viewState.collectAsStateValue() val listState = if (pagingItems.itemCount > 0) viewState.listState else rememberLazyListState() - val articleListTonalElevation = - context.articleListTonalElevation.collectAsStateValue(initial = ArticleListTonalElevationPreference.default) - val articleListFeedIcon = - context.articleListFeedIcon.collectAsStateValue(initial = ArticleListFeedIconPreference.default) - val owner = LocalLifecycleOwner.current var isSyncing by remember { mutableStateOf(false) } homeViewModel.syncWorkLiveData.observe(owner) { @@ -109,16 +109,18 @@ fun FlowPage( Scaffold( modifier = Modifier - .background(MaterialTheme.colorScheme.surfaceColorAtElevation(articleListTonalElevation.value.dp)) + .background(MaterialTheme.colorScheme.surfaceColorAtElevation(topBarTonalElevation.dp)) .statusBarsPadding() .navigationBarsPadding(), - containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(articleListTonalElevation.value.dp), + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + articleListTonalElevation.dp + ) onDark MaterialTheme.colorScheme.surface, topBar = { SmallTopAppBar( title = {}, colors = TopAppBarDefaults.smallTopAppBarColors( containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( - articleListTonalElevation.value.dp + topBarTonalElevation.dp ), ), navigationIcon = { @@ -197,7 +199,7 @@ fun FlowPage( state = listState, ) { item { - DisplayTextHeader(filterState, isSyncing, articleListFeedIcon.value) + DisplayTextHeader(filterState, isSyncing, articleListFeedIcon) AnimatedVisibility( visible = markAsRead, enter = fadeIn() + expandVertically(), @@ -259,8 +261,8 @@ fun FlowPage( } ArticleList( pagingItems = pagingItems, - articleListFeedIcon = articleListFeedIcon.value, - articleListTonalElevation = articleListTonalElevation.value, + articleListFeedIcon = articleListFeedIcon, + articleListTonalElevation = articleListTonalElevation, ) { onSearch = false navController.navigate("${RouteName.READING}/${it.article.id}") { @@ -279,12 +281,15 @@ fun FlowPage( bottomBar = { FilterBar( filter = filterState.filter, - filterOnClick = { - flowViewModel.dispatch(FlowViewAction.ScrollToItem(0)) - homeViewModel.dispatch(HomeViewAction.ChangeFilter(filterState.copy(filter = it))) - homeViewModel.dispatch(HomeViewAction.FetchArticles) - }, - ) + filterBarStyle = filterBarStyle, + filterBarFilled = filterBarFilled, + filterBarPadding = filterBarPadding.dp, + filterBarTonalElevation = filterBarTonalElevation.dp, + ) { + flowViewModel.dispatch(FlowViewAction.ScrollToItem(0)) + homeViewModel.dispatch(HomeViewAction.ChangeFilter(filterState.copy(filter = it))) + homeViewModel.dispatch(HomeViewAction.FetchArticles) + } } ) } diff --git a/app/src/main/java/me/ash/reader/ui/page/home/flow/StickyHeader.kt b/app/src/main/java/me/ash/reader/ui/page/home/flow/StickyHeader.kt index 93125e0..dcda056 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/flow/StickyHeader.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/flow/StickyHeader.kt @@ -11,6 +11,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import me.ash.reader.ui.ext.surfaceColorAtElevation +import me.ash.reader.ui.theme.palette.onDark @Composable fun StickyHeader( @@ -21,12 +22,17 @@ fun StickyHeader( Row( modifier = Modifier .fillMaxWidth() - .background(MaterialTheme.colorScheme.surfaceColorAtElevation(articleListTonalElevation.dp)), + .background( + MaterialTheme.colorScheme.surfaceColorAtElevation(articleListTonalElevation.dp) + onDark MaterialTheme.colorScheme.surface + ), verticalAlignment = Alignment.CenterVertically ) { Text( - modifier = Modifier - .padding(start = if (articleListFeedIcon) 54.dp else 24.dp, bottom = 4.dp), + modifier = Modifier.padding( + start = if (articleListFeedIcon) 54.dp else 24.dp, + bottom = 4.dp + ), text = currentItemDay, color = MaterialTheme.colorScheme.primary, style = MaterialTheme.typography.labelLarge, diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/ColorAndStyle.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/ColorAndStyle.kt index 55e491b..b7c8db7 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/color/ColorAndStyle.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/ColorAndStyle.kt @@ -28,12 +28,17 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import me.ash.reader.R +import me.ash.reader.data.preference.ThemePreference import me.ash.reader.ui.component.* -import me.ash.reader.ui.ext.* +import me.ash.reader.ui.ext.DataStoreKeys +import me.ash.reader.ui.ext.customPrimaryColor +import me.ash.reader.ui.ext.dataStore +import me.ash.reader.ui.ext.put import me.ash.reader.ui.page.common.RouteName import me.ash.reader.ui.page.settings.SettingItem import me.ash.reader.ui.svg.PALETTE import me.ash.reader.ui.svg.SVGString +import me.ash.reader.ui.theme.LocalTheme import me.ash.reader.ui.theme.LocalUseDarkTheme import me.ash.reader.ui.theme.palette.* import me.ash.reader.ui.theme.palette.TonalPalettes.Companion.toTonalPalettes @@ -47,8 +52,9 @@ fun ColorAndStyle( ) { val context = LocalContext.current val useDarkTheme = LocalUseDarkTheme.current + val theme = LocalTheme.current val wallpaperTonalPalettes = extractTonalPalettesFromUserWallpaper() - var radioButtonSelected by remember { mutableStateOf(if (context.themeIndex > 4) 0 else 1) } + var radioButtonSelected by remember { mutableStateOf(if (theme > 4) 0 else 1) } Scaffold( modifier = Modifier @@ -163,8 +169,11 @@ fun ColorAndStyle( ) SettingItem( title = stringResource(R.string.feeds_page), - enable = false, - onClick = {}, + onClick = { + navController.navigate(RouteName.FEEDS_PAGE_STYLE) { + launchSingleTop = true + } + }, ) {} SettingItem( title = stringResource(R.string.flow_page), @@ -245,12 +254,7 @@ fun Palettes( if (isCustom) { addDialogVisible = true } else { - scope.launch(Dispatchers.IO) { - context.dataStore.put( - DataStoreKeys.ThemeIndex, - themeIndexPrefix + index - ) - } + ThemePreference.put(context, scope, themeIndexPrefix + index) } }, palette = if (isCustom) tonalPalettes else palette diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPageStyle.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPageStyle.kt new file mode 100644 index 0000000..fdb19bc --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPageStyle.kt @@ -0,0 +1,379 @@ +package me.ash.reader.ui.page.settings.color.feeds + +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.Add +import androidx.compose.material.icons.rounded.ArrowBack +import androidx.compose.material.icons.rounded.Refresh +import androidx.compose.material3.* +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.compose.ui.unit.dp +import androidx.navigation.NavHostController +import me.ash.reader.R +import me.ash.reader.data.entity.Feed +import me.ash.reader.data.entity.Filter +import me.ash.reader.data.entity.Group +import me.ash.reader.data.preference.* +import me.ash.reader.data.preference.FeedsFilterBarFilledPreference.Companion.feedsFilterBarFilled +import me.ash.reader.data.preference.FeedsFilterBarPaddingPreference.feedsFilterBarPadding +import me.ash.reader.data.preference.FeedsFilterBarStylePreference.Companion.feedsFilterBarStyle +import me.ash.reader.data.preference.FeedsFilterBarTonalElevationPreference.Companion.feedsFilterBarTonalElevation +import me.ash.reader.data.preference.FeedsGroupListExpandPreference.Companion.feedsGroupListExpand +import me.ash.reader.data.preference.FeedsGroupListTonalElevationPreference.Companion.feedsGroupListTonalElevation +import me.ash.reader.data.preference.FeedsTopBarTonalElevationPreference.Companion.feedsTopBarTonalElevation +import me.ash.reader.ui.component.* +import me.ash.reader.ui.ext.collectAsStateValue +import me.ash.reader.ui.ext.surfaceColorAtElevation +import me.ash.reader.ui.page.home.FilterBar +import me.ash.reader.ui.page.home.feeds.GroupItem +import me.ash.reader.ui.page.settings.SettingItem +import me.ash.reader.ui.theme.palette.onDark +import me.ash.reader.ui.theme.palette.onLight + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun FeedsPageStyle( + navController: NavHostController, +) { + val context = LocalContext.current + val scope = rememberCoroutineScope() + val filterBarStyle = + context.feedsFilterBarStyle.collectAsStateValue(initial = FeedsFilterBarStylePreference.default) + val filterBarFilled = + context.feedsFilterBarFilled.collectAsStateValue(initial = FeedsFilterBarFilledPreference.default) + val filterBarPadding = + context.feedsFilterBarPadding.collectAsStateValue(initial = FeedsFilterBarPaddingPreference.default) + val filterBarTonalElevation = + context.feedsFilterBarTonalElevation.collectAsStateValue(initial = FeedsFilterBarTonalElevationPreference.default) + val topBarTonalElevation = + context.feedsTopBarTonalElevation.collectAsStateValue(initial = FeedsTopBarTonalElevationPreference.default) + val groupListExpand = + context.feedsGroupListExpand.collectAsStateValue(initial = FeedsGroupListExpandPreference.default) + val groupListTonalElevation = + context.feedsGroupListTonalElevation.collectAsStateValue(initial = FeedsGroupListTonalElevationPreference.default) + + var filterBarStyleDialogVisible by remember { mutableStateOf(false) } + var filterBarPaddingDialogVisible by remember { mutableStateOf(false) } + var filterBarTonalElevationDialogVisible by remember { mutableStateOf(false) } + var topBarTonalElevationDialogVisible by remember { mutableStateOf(false) } + var groupListTonalElevationDialogVisible by remember { mutableStateOf(false) } + + var filterBarPaddingValue: Int? by remember { mutableStateOf(filterBarPadding) } + + Scaffold( + modifier = Modifier + .background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface) + .statusBarsPadding() + .navigationBarsPadding(), + containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface, + topBar = { + SmallTopAppBar( + colors = TopAppBarDefaults.smallTopAppBarColors( + containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface + ), + title = {}, + navigationIcon = { + FeedbackIconButton( + imageVector = Icons.Rounded.ArrowBack, + contentDescription = stringResource(R.string.back), + tint = MaterialTheme.colorScheme.onSurface + ) { + navController.popBackStack() + } + }, + actions = {} + ) + }, + content = { + LazyColumn { + item { + DisplayText(text = stringResource(R.string.feeds_page), 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 + ) { + FeedsPagePreview( + topBarTonalElevation = topBarTonalElevation, + groupListExpand = groupListExpand, + groupListTonalElevation = groupListTonalElevation, + filterBarStyle = filterBarStyle.value, + filterBarFilled = filterBarFilled.value, + filterBarPadding = filterBarPadding.dp, + filterBarTonalElevation = filterBarTonalElevation.value.dp, + ) + } + Spacer(modifier = Modifier.height(24.dp)) + } + + // Top Bar + item { + Subtitle( + modifier = Modifier.padding(horizontal = 24.dp), + text = stringResource(R.string.top_bar) + ) + SettingItem( + title = stringResource(R.string.tonal_elevation), + desc = "${topBarTonalElevation.value}dp", + onClick = { + topBarTonalElevationDialogVisible = true + }, + ) {} + Tips(text = stringResource(R.string.tips_top_bar_tonal_elevation)) + Spacer(modifier = Modifier.height(24.dp)) + } + + // Group List + item { + Subtitle( + modifier = Modifier.padding(horizontal = 24.dp), + text = stringResource(R.string.group_list) + ) + SettingItem( + title = stringResource(R.string.always_expand), + onClick = { + (!groupListExpand).put(context, scope) + }, + ) { + Switch(activated = groupListExpand.value) { + (!groupListExpand).put(context, scope) + } + } + SettingItem( + title = stringResource(R.string.tonal_elevation), + desc = "${groupListTonalElevation.value}dp", + onClick = { + groupListTonalElevationDialogVisible = true + }, + ) {} + Tips(text = stringResource(R.string.tips_group_list_tonal_elevation)) + Spacer(modifier = Modifier.height(24.dp)) + } + + // Filter Bar + item { + Subtitle( + modifier = Modifier.padding(horizontal = 24.dp), + text = stringResource(R.string.filter_bar), + ) + SettingItem( + title = stringResource(R.string.style), + desc = filterBarStyle.getDesc(context), + onClick = { + filterBarStyleDialogVisible = true + }, + ) {} + SettingItem( + title = stringResource(R.string.fill_selected_icon), + onClick = { + (!filterBarFilled).put(context, scope) + }, + ) { + Switch(activated = filterBarFilled.value) { + (!filterBarFilled).put(context, scope) + } + } + SettingItem( + title = stringResource(R.string.padding_on_both_ends), + desc = "${filterBarPadding}dp", + onClick = { + filterBarPaddingValue = filterBarPadding + filterBarPaddingDialogVisible = true + }, + ) {} + SettingItem( + title = stringResource(R.string.tonal_elevation), + desc = "${filterBarTonalElevation.value}dp", + onClick = { + filterBarTonalElevationDialogVisible = true + }, + ) {} + Spacer(modifier = Modifier.height(24.dp)) + } + } + } + ) + + RadioDialog( + visible = filterBarStyleDialogVisible, + title = stringResource(R.string.style), + options = FeedsFilterBarStylePreference.values.map { + RadioDialogOption( + text = it.getDesc(context), + selected = filterBarStyle == it, + ) { + it.put(context, scope) + } + } + ) { + filterBarStyleDialogVisible = false + } + + TextFieldDialog( + visible = filterBarPaddingDialogVisible, + title = stringResource(R.string.padding_on_both_ends), + value = (filterBarPaddingValue ?: "").toString(), + placeholder = stringResource(R.string.value), + onValueChange = { + filterBarPaddingValue = it.filter { it.isDigit() }.toIntOrNull() + }, + onDismissRequest = { + filterBarPaddingDialogVisible = false + }, + onConfirm = { + FeedsFilterBarPaddingPreference.put(context, scope, filterBarPaddingValue ?: 0) + filterBarPaddingDialogVisible = false + } + ) + + RadioDialog( + visible = filterBarTonalElevationDialogVisible, + title = stringResource(R.string.tonal_elevation), + options = FeedsFilterBarTonalElevationPreference.values.map { + RadioDialogOption( + text = it.getDesc(context), + selected = filterBarTonalElevation == it, + ) { + it.put(context, scope) + } + } + ) { + filterBarTonalElevationDialogVisible = false + } + + RadioDialog( + visible = topBarTonalElevationDialogVisible, + title = stringResource(R.string.tonal_elevation), + options = FeedsTopBarTonalElevationPreference.values.map { + RadioDialogOption( + text = it.getDesc(context), + selected = topBarTonalElevation == it, + ) { + it.put(context, scope) + } + } + ) { + topBarTonalElevationDialogVisible = false + } + + RadioDialog( + visible = groupListTonalElevationDialogVisible, + title = stringResource(R.string.tonal_elevation), + options = FeedsGroupListTonalElevationPreference.values.map { + RadioDialogOption( + text = it.getDesc(context), + selected = groupListTonalElevation == it, + ) { + it.put(context, scope) + } + } + ) { + groupListTonalElevationDialogVisible = false + } +} + +@Composable +fun FeedsPagePreview( + topBarTonalElevation: FeedsTopBarTonalElevationPreference, + groupListExpand: FeedsGroupListExpandPreference, + groupListTonalElevation: FeedsGroupListTonalElevationPreference, + filterBarStyle: Int, + filterBarFilled: Boolean, + filterBarPadding: Dp, + filterBarTonalElevation: Dp, +) { + var filter by remember { mutableStateOf(Filter.Unread) } + + Column( + modifier = Modifier + .background( + color = MaterialTheme.colorScheme.surfaceColorAtElevation( + groupListTonalElevation.value.dp + ) onDark MaterialTheme.colorScheme.surface, + shape = RoundedCornerShape(24.dp) + ) + ) { + SmallTopAppBar( + title = {}, + colors = TopAppBarDefaults.smallTopAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + topBarTonalElevation.value.dp + ), + ), + navigationIcon = { + FeedbackIconButton( + imageVector = Icons.Rounded.ArrowBack, + contentDescription = stringResource(R.string.back), + tint = MaterialTheme.colorScheme.onSurface + ) {} + }, + actions = { + FeedbackIconButton( + imageVector = Icons.Rounded.Refresh, + contentDescription = stringResource(R.string.refresh), + tint = MaterialTheme.colorScheme.onSurface, + ) {} + FeedbackIconButton( + imageVector = Icons.Rounded.Add, + contentDescription = stringResource(R.string.subscribe), + tint = MaterialTheme.colorScheme.onSurface, + ) {} + } + ) + Spacer(modifier = Modifier.height(12.dp)) + GroupItem( + isExpanded = groupListExpand.value, + tonalElevation = groupListTonalElevation.value.dp, + group = Group( + id = "", + name = stringResource(R.string.defaults), + accountId = 0, + ), + feeds = listOf( + Feed( + id = "", + name = stringResource(R.string.preview_feed_name), + icon = "", + accountId = 0, + groupId = "", + url = "", + ).apply { + important = 100 + } + ), + ) + Spacer(modifier = Modifier.height(12.dp)) + FilterBar( + modifier = Modifier.padding(horizontal = 12.dp), + filter = filter, + filterBarStyle = filterBarStyle, + filterBarFilled = filterBarFilled, + filterBarPadding = filterBarPadding, + filterBarTonalElevation = filterBarTonalElevation, + ) { + filter = it + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/feedsPageStyle.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPageStyle.kt similarity index 56% rename from app/src/main/java/me/ash/reader/ui/page/settings/color/flow/feedsPageStyle.kt rename to app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPageStyle.kt index ab04904..046c939 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/feedsPageStyle.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPageStyle.kt @@ -8,6 +8,8 @@ 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.material.icons.rounded.DoneAll +import androidx.compose.material.icons.rounded.Search import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -15,6 +17,7 @@ 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.compose.ui.unit.dp import androidx.navigation.NavHostController import me.ash.reader.R @@ -23,22 +26,24 @@ import me.ash.reader.data.entity.ArticleWithFeed import me.ash.reader.data.entity.Feed import me.ash.reader.data.entity.Filter import me.ash.reader.data.preference.* -import me.ash.reader.data.preference.ArticleListDatePreference.Companion.articleListDate -import me.ash.reader.data.preference.ArticleListDescPreference.Companion.articleListDesc -import me.ash.reader.data.preference.ArticleListFeedIconPreference.Companion.articleListFeedIcon -import me.ash.reader.data.preference.ArticleListFeedNamePreference.Companion.articleListFeedName -import me.ash.reader.data.preference.ArticleListImagePreference.Companion.articleListImage -import me.ash.reader.data.preference.ArticleListTonalElevationPreference.Companion.articleListTonalElevation -import me.ash.reader.data.preference.FilterBarFilledPreference.Companion.filterBarFilled -import me.ash.reader.data.preference.FilterBarPaddingPreference.filterBarPadding -import me.ash.reader.data.preference.FilterBarStylePreference.Companion.filterBarStyle -import me.ash.reader.data.preference.FilterBarTonalElevationPreference.Companion.filterBarTonalElevation +import me.ash.reader.data.preference.FlowArticleListDatePreference.Companion.flowArticleListDate +import me.ash.reader.data.preference.FlowArticleListDescPreference.Companion.flowArticleListDesc +import me.ash.reader.data.preference.FlowArticleListFeedIconPreference.Companion.flowArticleListFeedIcon +import me.ash.reader.data.preference.FlowArticleListFeedNamePreference.Companion.flowArticleListFeedName +import me.ash.reader.data.preference.FlowArticleListImagePreference.Companion.flowArticleListImage +import me.ash.reader.data.preference.FlowArticleListTonalElevationPreference.Companion.flowArticleListTonalElevation +import me.ash.reader.data.preference.FlowFilterBarFilledPreference.Companion.flowFilterBarFilled +import me.ash.reader.data.preference.FlowFilterBarPaddingPreference.flowFilterBarPadding +import me.ash.reader.data.preference.FlowFilterBarStylePreference.Companion.flowFilterBarStyle +import me.ash.reader.data.preference.FlowFilterBarTonalElevationPreference.Companion.flowFilterBarTonalElevation +import me.ash.reader.data.preference.FlowTopBarTonalElevationPreference.Companion.flowTopBarTonalElevation import me.ash.reader.ui.component.* import me.ash.reader.ui.ext.collectAsStateValue import me.ash.reader.ui.ext.surfaceColorAtElevation import me.ash.reader.ui.page.home.FilterBar import me.ash.reader.ui.page.home.flow.ArticleItem import me.ash.reader.ui.page.settings.SettingItem +import me.ash.reader.ui.theme.palette.onDark import me.ash.reader.ui.theme.palette.onLight import java.util.* @@ -51,29 +56,32 @@ fun FlowPageStyle( val context = LocalContext.current val scope = rememberCoroutineScope() val filterBarStyle = - context.filterBarStyle.collectAsStateValue(initial = FilterBarStylePreference.default) + context.flowFilterBarStyle.collectAsStateValue(initial = FlowFilterBarStylePreference.default) val filterBarFilled = - context.filterBarFilled.collectAsStateValue(initial = FilterBarFilledPreference.default) + context.flowFilterBarFilled.collectAsStateValue(initial = FlowFilterBarFilledPreference.default) val filterBarPadding = - context.filterBarPadding.collectAsStateValue(initial = FilterBarPaddingPreference.default) + context.flowFilterBarPadding.collectAsStateValue(initial = FlowFilterBarPaddingPreference.default) val filterBarTonalElevation = - context.filterBarTonalElevation.collectAsStateValue(initial = FilterBarTonalElevationPreference.default) + context.flowFilterBarTonalElevation.collectAsStateValue(initial = FlowFilterBarTonalElevationPreference.default) + val topBarTonalElevation = + context.flowTopBarTonalElevation.collectAsStateValue(initial = FlowTopBarTonalElevationPreference.default) val articleListFeedIcon = - context.articleListFeedIcon.collectAsStateValue(initial = ArticleListFeedIconPreference.default) + context.flowArticleListFeedIcon.collectAsStateValue(initial = FlowArticleListFeedIconPreference.default) val articleListFeedName = - context.articleListFeedName.collectAsStateValue(initial = ArticleListFeedNamePreference.default) + context.flowArticleListFeedName.collectAsStateValue(initial = FlowArticleListFeedNamePreference.default) val articleListImage = - context.articleListImage.collectAsStateValue(initial = ArticleListImagePreference.default) + context.flowArticleListImage.collectAsStateValue(initial = FlowArticleListImagePreference.default) val articleListDesc = - context.articleListDesc.collectAsStateValue(initial = ArticleListDescPreference.default) + context.flowArticleListDesc.collectAsStateValue(initial = FlowArticleListDescPreference.default) val articleListDate = - context.articleListDate.collectAsStateValue(initial = ArticleListDatePreference.default) + context.flowArticleListDate.collectAsStateValue(initial = FlowArticleListDatePreference.default) val articleListTonalElevation = - context.articleListTonalElevation.collectAsStateValue(initial = ArticleListTonalElevationPreference.default) + context.flowArticleListTonalElevation.collectAsStateValue(initial = FlowArticleListTonalElevationPreference.default) var filterBarStyleDialogVisible by remember { mutableStateOf(false) } var filterBarPaddingDialogVisible by remember { mutableStateOf(false) } var filterBarTonalElevationDialogVisible by remember { mutableStateOf(false) } + var topBarTonalElevationDialogVisible by remember { mutableStateOf(false) } var articleListTonalElevationDialogVisible by remember { mutableStateOf(false) } var filterBarPaddingValue: Int? by remember { mutableStateOf(filterBarPadding) } @@ -107,6 +115,8 @@ fun FlowPageStyle( item { DisplayText(text = stringResource(R.string.flow_page), desc = "") } + + // Preview item { Row( modifier = Modifier @@ -121,67 +131,49 @@ fun FlowPageStyle( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { - FeedsPagePreview(articleListTonalElevation) + FlowPagePreview( + topBarTonalElevation = topBarTonalElevation, + articleListTonalElevation = articleListTonalElevation, + filterBarStyle = filterBarStyle.value, + filterBarFilled = filterBarFilled.value, + filterBarPadding = filterBarPadding.dp, + filterBarTonalElevation = filterBarTonalElevation.value.dp, + ) } Spacer(modifier = Modifier.height(24.dp)) } + + // Top Bar item { Subtitle( modifier = Modifier.padding(horizontal = 24.dp), - text = "过滤栏", + text = stringResource(R.string.top_bar) ) SettingItem( - title = "样式", - desc = filterBarStyle.getDesc(context), - onClick = { - filterBarStyleDialogVisible = true - }, - ) {} - SettingItem( - title = "填充已选中的图标", - onClick = { - (!filterBarFilled).put(context, scope) - }, - ) { - Switch(activated = filterBarFilled.value) { - (!filterBarFilled).put(context, scope) - } - } - SettingItem( - title = "两端边距", - desc = "${filterBarPadding}dp", - onClick = { - filterBarPaddingDialogVisible = true - }, - ) {} - SettingItem( - title = "色调海拔", - desc = "${filterBarTonalElevation.value}dp", - onClick = { - filterBarTonalElevationDialogVisible = true - }, - ) {} - Spacer(modifier = Modifier.height(24.dp)) - } - item { - Subtitle( - modifier = Modifier.padding(horizontal = 24.dp), - text = "标题栏" - ) - SettingItem( - title = "“标记为已读”按钮的位置", - desc = "顶部", + title = stringResource(R.string.mark_as_read_button_position), + desc = stringResource(R.string.top), + enable = false, onClick = {}, ) {} + SettingItem( + title = stringResource(R.string.tonal_elevation), + desc = "${topBarTonalElevation.value}dp", + onClick = { + topBarTonalElevationDialogVisible = true + }, + ) {} + Tips(text = stringResource(R.string.tips_top_bar_tonal_elevation)) Spacer(modifier = Modifier.height(24.dp)) } + + // Article List item { Subtitle( modifier = Modifier.padding(horizontal = 24.dp), - text = "文章列表" + text = stringResource(R.string.article_list) ) SettingItem( - title = "显示订阅源图标", + title = stringResource(R.string.display_feed_favicon), onClick = { (!articleListFeedIcon).put(context, scope) }, @@ -191,7 +183,7 @@ fun FlowPageStyle( } } SettingItem( - title = "显示订阅源名称", + title = stringResource(R.string.display_feed_name), onClick = { (!articleListFeedName).put(context, scope) }, @@ -201,13 +193,14 @@ fun FlowPageStyle( } } SettingItem( - title = "显示文章插图", + title = stringResource(R.string.display_article_image), + enable = false, onClick = {}, ) { Switch(activated = false, enable = false) } SettingItem( - title = "显示文章描述", + title = stringResource(R.string.display_article_desc), onClick = { (!articleListDesc).put(context, scope) }, @@ -217,7 +210,7 @@ fun FlowPageStyle( } } SettingItem( - title = "显示文章发布时间", + title = stringResource(R.string.display_article_date), onClick = { (!articleListDate).put(context, scope) }, @@ -227,12 +220,54 @@ fun FlowPageStyle( } } SettingItem( - title = "色调海拔", + title = stringResource(R.string.tonal_elevation), desc = "${articleListTonalElevation.value}dp", onClick = { articleListTonalElevationDialogVisible = true }, ) {} + Tips(text = stringResource(R.string.tips_article_list_tonal_elevation)) + Spacer(modifier = Modifier.height(24.dp)) + } + + // Filter Bar + item { + Subtitle( + modifier = Modifier.padding(horizontal = 24.dp), + text = stringResource(R.string.filter_bar), + ) + SettingItem( + title = stringResource(R.string.style), + desc = filterBarStyle.getDesc(context), + onClick = { + filterBarStyleDialogVisible = true + }, + ) {} + SettingItem( + title = stringResource(R.string.fill_selected_icon), + onClick = { + (!filterBarFilled).put(context, scope) + }, + ) { + Switch(activated = filterBarFilled.value) { + (!filterBarFilled).put(context, scope) + } + } + SettingItem( + title = stringResource(R.string.padding_on_both_ends), + desc = "${filterBarPadding}dp", + onClick = { + filterBarPaddingValue = filterBarPadding + filterBarPaddingDialogVisible = true + }, + ) {} + SettingItem( + title = stringResource(R.string.tonal_elevation), + desc = "${filterBarTonalElevation.value}dp", + onClick = { + filterBarTonalElevationDialogVisible = true + }, + ) {} Spacer(modifier = Modifier.height(24.dp)) } } @@ -241,8 +276,8 @@ fun FlowPageStyle( RadioDialog( visible = filterBarStyleDialogVisible, - title = stringResource(R.string.initial_filter), - options = FilterBarStylePreference.values.map { + title = stringResource(R.string.style), + options = FlowFilterBarStylePreference.values.map { RadioDialogOption( text = it.getDesc(context), selected = filterBarStyle == it, @@ -256,17 +291,17 @@ fun FlowPageStyle( TextFieldDialog( visible = filterBarPaddingDialogVisible, - title = "两端边距", + title = stringResource(R.string.padding_on_both_ends), value = (filterBarPaddingValue ?: "").toString(), - placeholder = stringResource(R.string.name), + placeholder = stringResource(R.string.value), onValueChange = { - filterBarPaddingValue = it.toIntOrNull() + filterBarPaddingValue = it.filter { it.isDigit() }.toIntOrNull() }, onDismissRequest = { filterBarPaddingDialogVisible = false }, onConfirm = { - FilterBarPaddingPreference.put(context, scope, filterBarPaddingValue ?: 0) + FlowFilterBarPaddingPreference.put(context, scope, filterBarPaddingValue ?: 0) filterBarPaddingDialogVisible = false } ) @@ -274,7 +309,7 @@ fun FlowPageStyle( RadioDialog( visible = filterBarTonalElevationDialogVisible, title = stringResource(R.string.tonal_elevation), - options = FilterBarTonalElevationPreference.values.map { + options = FlowFilterBarTonalElevationPreference.values.map { RadioDialogOption( text = it.getDesc(context), selected = filterBarTonalElevation == it, @@ -286,10 +321,25 @@ fun FlowPageStyle( filterBarTonalElevationDialogVisible = false } + RadioDialog( + visible = topBarTonalElevationDialogVisible, + title = stringResource(R.string.tonal_elevation), + options = FlowTopBarTonalElevationPreference.values.map { + RadioDialogOption( + text = it.getDesc(context), + selected = topBarTonalElevation == it, + ) { + it.put(context, scope) + } + } + ) { + topBarTonalElevationDialogVisible = false + } + RadioDialog( visible = articleListTonalElevationDialogVisible, title = stringResource(R.string.tonal_elevation), - options = ArticleListTonalElevationPreference.values.map { + options = FlowArticleListTonalElevationPreference.values.map { RadioDialogOption( text = it.getDesc(context), selected = articleListTonalElevation == it, @@ -303,43 +353,85 @@ fun FlowPageStyle( } @Composable -fun FeedsPagePreview( - articleListTonalElevation: ArticleListTonalElevationPreference, +fun FlowPagePreview( + topBarTonalElevation: FlowTopBarTonalElevationPreference, + articleListTonalElevation: FlowArticleListTonalElevationPreference, + filterBarStyle: Int, + filterBarFilled: Boolean, + filterBarPadding: Dp, + filterBarTonalElevation: Dp, ) { var filter by remember { mutableStateOf(Filter.Unread) } Column( modifier = Modifier .background( - color = MaterialTheme.colorScheme.surfaceColorAtElevation(articleListTonalElevation.value.dp), + color = MaterialTheme.colorScheme.surfaceColorAtElevation( + articleListTonalElevation.value.dp + ) onDark MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(24.dp) ) ) { + SmallTopAppBar( + title = {}, + colors = TopAppBarDefaults.smallTopAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + topBarTonalElevation.value.dp + ), + ), + navigationIcon = { + FeedbackIconButton( + imageVector = Icons.Rounded.ArrowBack, + contentDescription = stringResource(R.string.back), + tint = MaterialTheme.colorScheme.onSurface + ) {} + }, + actions = { + FeedbackIconButton( + imageVector = Icons.Rounded.DoneAll, + contentDescription = stringResource(R.string.mark_all_as_read), + tint = MaterialTheme.colorScheme.onSurface, + ) {} + FeedbackIconButton( + imageVector = Icons.Rounded.Search, + contentDescription = stringResource(R.string.search), + tint = MaterialTheme.colorScheme.onSurface, + ) {} + } + ) Spacer(modifier = Modifier.height(12.dp)) ArticleItem( articleWithFeed = ArticleWithFeed( Article( id = "", - title = "《黎明之剑》撒花完结,白金远瞳的“希灵三部曲”值得你通宵阅读", - shortDescription = "昨日在找书的时候无意间发现,“远瞳”的《黎明之剑》突然冲上了起点热搜榜首位,去小说中查找原因,原来是这部六百多万字的作品已经完结了。四年的时间,这部小说始终占据科幻分类前三甲的位置,不得不说“远瞳”的实力的确不容小觑。", - rawDescription = "昨日在找书的时候无意间发现,“远瞳”的《黎明之剑》突然冲上了起点热搜榜首位,去小说中查找原因,原来是这部六百多万字的作品已经完结了。四年的时间,这部小说始终占据科幻分类前三甲的位置,不得不说“远瞳”的实力的确不容小觑。", + title = stringResource(R.string.preview_article_title), + shortDescription = stringResource(R.string.preview_article_desc), + rawDescription = stringResource(R.string.preview_article_desc), link = "", feedId = "", accountId = 0, date = Date(), + isStarred = true, ), feed = Feed( id = "", - name = "佛门射手", + name = stringResource(R.string.preview_feed_name), icon = "", accountId = 0, groupId = "", url = "", - ) + ), ) ) Spacer(modifier = Modifier.height(12.dp)) - FilterBar(modifier = Modifier.padding(horizontal = 12.dp), filter = filter) { + FilterBar( + modifier = Modifier.padding(horizontal = 12.dp), + filter = filter, + filterBarStyle = filterBarStyle, + filterBarFilled = filterBarFilled, + filterBarPadding = filterBarPadding, + filterBarTonalElevation = filterBarTonalElevation, + ) { filter = it } } diff --git a/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt b/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt index c302a91..cc30fbd 100644 --- a/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.rounded.CheckCircleOutline import androidx.compose.material3.* import androidx.compose.runtime.Composable @@ -21,6 +20,7 @@ import kotlinx.coroutines.launch import me.ash.reader.R import me.ash.reader.ui.component.DisplayText import me.ash.reader.ui.component.DynamicSVGImage +import me.ash.reader.ui.component.Tips import me.ash.reader.ui.ext.DataStoreKeys import me.ash.reader.ui.ext.dataStore import me.ash.reader.ui.ext.put @@ -57,14 +57,12 @@ fun StartupPage( ) } item { - TipsItem( - modifier = Modifier - .padding(horizontal = 24.dp) - .padding(top = 40.dp) + Tips( + modifier = Modifier.padding(top = 40.dp), + text = stringResource(R.string.agree_terms), ) } item { - Spacer(modifier = Modifier.height(10.dp)) TextButton( modifier = Modifier.padding(horizontal = 12.dp), onClick = { @@ -119,26 +117,4 @@ fun StartupPage( ) } ) -} - -@Composable -private fun TipsItem( - modifier: Modifier = Modifier, -) { - Column( - modifier = modifier - .fillMaxWidth() - ) { - Icon( - imageVector = Icons.Outlined.Info, - contentDescription = stringResource(R.string.tips_and_support), - tint = MaterialTheme.colorScheme.onSurfaceVariant, - ) - Spacer(modifier = Modifier.height(22.dp)) - Text( - text = stringResource(R.string.agree_terms), - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/svg/SVGString.kt b/app/src/main/java/me/ash/reader/ui/svg/SVGString.kt index bbadd60..5bf1e59 100644 --- a/app/src/main/java/me/ash/reader/ui/svg/SVGString.kt +++ b/app/src/main/java/me/ash/reader/ui/svg/SVGString.kt @@ -10,6 +10,7 @@ object SVGString fun String.parseDynamicColor(tonalPalettes: TonalPalettes, isDarkTheme: Boolean): String = replace("fill=\"(.+?)\"".toRegex()) { val value = it.groupValues[1] + Log.i("RLog", "parseDynamicColor: $value") if (value.startsWith("#")) return@replace it.value try { val (scheme, tone) = value.split("(?<=\\d)(?=\\D)|(?=\\d)(?<=\\D)".toRegex()) @@ -24,6 +25,7 @@ fun String.parseDynamicColor(tonalPalettes: TonalPalettes, isDarkTheme: Boolean) }?.toArgb() ?: 0xFFFFFF "fill=\"${String.format("#%06X", 0xFFFFFF and argb)}\"" } catch (e: Exception) { + e.printStackTrace() Log.e("RLog", "parseDynamicColor: ${e.message}") it.value } diff --git a/app/src/main/java/me/ash/reader/ui/theme/Theme.kt b/app/src/main/java/me/ash/reader/ui/theme/Theme.kt index da76775..7354651 100644 --- a/app/src/main/java/me/ash/reader/ui/theme/Theme.kt +++ b/app/src/main/java/me/ash/reader/ui/theme/Theme.kt @@ -5,12 +5,29 @@ import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.compositionLocalOf import androidx.compose.ui.platform.LocalContext -import kotlinx.coroutines.flow.map -import me.ash.reader.ui.ext.DataStoreKeys -import me.ash.reader.ui.ext.dataStore +import me.ash.reader.data.preference.* +import me.ash.reader.data.preference.FeedsFilterBarFilledPreference.Companion.feedsFilterBarFilled +import me.ash.reader.data.preference.FeedsFilterBarPaddingPreference.feedsFilterBarPadding +import me.ash.reader.data.preference.FeedsFilterBarStylePreference.Companion.feedsFilterBarStyle +import me.ash.reader.data.preference.FeedsFilterBarTonalElevationPreference.Companion.feedsFilterBarTonalElevation +import me.ash.reader.data.preference.FeedsGroupListExpandPreference.Companion.feedsGroupListExpand +import me.ash.reader.data.preference.FeedsGroupListTonalElevationPreference.Companion.feedsGroupListTonalElevation +import me.ash.reader.data.preference.FeedsTopBarTonalElevationPreference.Companion.feedsTopBarTonalElevation +import me.ash.reader.data.preference.FlowArticleListDatePreference.Companion.flowArticleListDate +import me.ash.reader.data.preference.FlowArticleListDescPreference.Companion.flowArticleListDesc +import me.ash.reader.data.preference.FlowArticleListFeedIconPreference.Companion.flowArticleListFeedIcon +import me.ash.reader.data.preference.FlowArticleListFeedNamePreference.Companion.flowArticleListFeedName +import me.ash.reader.data.preference.FlowArticleListImagePreference.Companion.flowArticleListImage +import me.ash.reader.data.preference.FlowArticleListTonalElevationPreference.Companion.flowArticleListTonalElevation +import me.ash.reader.data.preference.FlowFilterBarFilledPreference.Companion.flowFilterBarFilled +import me.ash.reader.data.preference.FlowFilterBarPaddingPreference.flowFilterBarPadding +import me.ash.reader.data.preference.FlowFilterBarStylePreference.Companion.flowFilterBarStyle +import me.ash.reader.data.preference.FlowFilterBarTonalElevationPreference.Companion.flowFilterBarTonalElevation +import me.ash.reader.data.preference.FlowTopBarTonalElevationPreference.Companion.flowTopBarTonalElevation +import me.ash.reader.data.preference.ThemePreference.Theme +import me.ash.reader.ui.ext.collectAsStateValue import me.ash.reader.ui.theme.palette.LocalTonalPalettes import me.ash.reader.ui.theme.palette.TonalPalettes import me.ash.reader.ui.theme.palette.core.ProvideZcamViewingConditions @@ -19,6 +36,36 @@ import me.ash.reader.ui.theme.palette.dynamicDarkColorScheme import me.ash.reader.ui.theme.palette.dynamicLightColorScheme val LocalUseDarkTheme = compositionLocalOf { false } +val LocalTheme = compositionLocalOf { ThemePreference.default } + +val LocalFeedsFilterBarStyle = compositionLocalOf { FeedsFilterBarStylePreference.default.value } +val LocalFeedsFilterBarFilled = compositionLocalOf { FeedsFilterBarFilledPreference.default.value } +val LocalFeedsFilterBarPadding = compositionLocalOf { FeedsFilterBarPaddingPreference.default } +val LocalFeedsFilterBarTonalElevation = + compositionLocalOf { FeedsFilterBarTonalElevationPreference.default.value } +val LocalFeedsTopBarTonalElevation = + compositionLocalOf { FeedsTopBarTonalElevationPreference.default.value } +val LocalFeedsGroupListExpand = + compositionLocalOf { FeedsGroupListExpandPreference.default.value } +val LocalFeedsGroupListTonalElevation = + compositionLocalOf { FeedsGroupListTonalElevationPreference.default.value } + +val LocalFlowFilterBarStyle = compositionLocalOf { FlowFilterBarStylePreference.default.value } +val LocalFlowFilterBarFilled = compositionLocalOf { FlowFilterBarFilledPreference.default.value } +val LocalFlowFilterBarPadding = compositionLocalOf { FlowFilterBarPaddingPreference.default } +val LocalFlowFilterBarTonalElevation = + compositionLocalOf { FlowFilterBarTonalElevationPreference.default.value } +val LocalFlowTopBarTonalElevation = + compositionLocalOf { FlowTopBarTonalElevationPreference.default.value } +val LocalFlowArticleListFeedIcon = + compositionLocalOf { FlowArticleListFeedIconPreference.default.value } +val LocalFlowArticleListFeedName = + compositionLocalOf { FlowArticleListFeedNamePreference.default.value } +val LocalFlowArticleListImage = compositionLocalOf { FlowArticleListImagePreference.default.value } +val LocalFlowArticleListDesc = compositionLocalOf { FlowArticleListDescPreference.default.value } +val LocalFlowArticleListDate = compositionLocalOf { FlowArticleListDatePreference.default.value } +val LocalFlowArticleListTonalElevation = + compositionLocalOf { FlowArticleListTonalElevationPreference.default.value } @SuppressLint("FlowOperatorInvokedInComposition") @Composable @@ -28,26 +75,83 @@ fun AppTheme( content: @Composable () -> Unit ) { val context = LocalContext.current - val themeIndex = context.dataStore.data - .map { it[DataStoreKeys.ThemeIndex.key] ?: 5 } - .collectAsState(initial = 5).value + val theme = context.Theme.collectAsStateValue(initial = ThemePreference.default) val tonalPalettes = wallpaperPalettes[ - if (themeIndex >= wallpaperPalettes.size) { + if (theme >= wallpaperPalettes.size) { when { wallpaperPalettes.size == 5 -> 0 wallpaperPalettes.size > 5 -> 5 else -> 0 } } else { - themeIndex + theme } ] + val feedsFilterBarStyle = + context.feedsFilterBarStyle.collectAsStateValue(initial = FeedsFilterBarStylePreference.default) + val feedsFilterBarFilled = + context.feedsFilterBarFilled.collectAsStateValue(initial = FeedsFilterBarFilledPreference.default) + val feedsFilterBarPadding = + context.feedsFilterBarPadding.collectAsStateValue(initial = FeedsFilterBarPaddingPreference.default) + val feedsFilterBarTonalElevation = + context.feedsFilterBarTonalElevation.collectAsStateValue(initial = FeedsFilterBarTonalElevationPreference.default) + val feedsTopBarTonalElevation = + context.feedsTopBarTonalElevation.collectAsStateValue(initial = FeedsTopBarTonalElevationPreference.default) + val feedsGroupListExpand = + context.feedsGroupListExpand.collectAsStateValue(initial = FeedsGroupListExpandPreference.default) + val feedsGroupListTonalElevation = + context.feedsGroupListTonalElevation.collectAsStateValue(initial = FeedsGroupListTonalElevationPreference.default) + + val flowFilterBarStyle = + context.flowFilterBarStyle.collectAsStateValue(initial = FlowFilterBarStylePreference.default) + val flowFilterBarFilled = + context.flowFilterBarFilled.collectAsStateValue(initial = FlowFilterBarFilledPreference.default) + val flowFilterBarPadding = + context.flowFilterBarPadding.collectAsStateValue(initial = FlowFilterBarPaddingPreference.default) + val flowFilterBarTonalElevation = + context.flowFilterBarTonalElevation.collectAsStateValue(initial = FlowFilterBarTonalElevationPreference.default) + val flowTopBarTonalElevation = + context.flowTopBarTonalElevation.collectAsStateValue(initial = FlowTopBarTonalElevationPreference.default) + val flowArticleListFeedIcon = + context.flowArticleListFeedIcon.collectAsStateValue(initial = FlowArticleListFeedIconPreference.default) + val flowArticleListFeedName = + context.flowArticleListFeedName.collectAsStateValue(initial = FlowArticleListFeedNamePreference.default) + val flowArticleListImage = + context.flowArticleListImage.collectAsStateValue(initial = FlowArticleListImagePreference.default) + val flowArticleListDesc = + context.flowArticleListDesc.collectAsStateValue(initial = FlowArticleListDescPreference.default) + val flowArticleListDate = + context.flowArticleListDate.collectAsStateValue(initial = FlowArticleListDatePreference.default) + val flowArticleListTonalElevation = + context.flowArticleListTonalElevation.collectAsStateValue(initial = FlowArticleListTonalElevationPreference.default) + ProvideZcamViewingConditions { CompositionLocalProvider( LocalTonalPalettes provides tonalPalettes.also { it.Preheating() }, - LocalUseDarkTheme provides useDarkTheme + LocalUseDarkTheme provides useDarkTheme, + LocalTheme provides theme, + + LocalFeedsFilterBarStyle provides feedsFilterBarStyle.value, + LocalFeedsFilterBarFilled provides feedsFilterBarFilled.value, + LocalFeedsFilterBarPadding provides feedsFilterBarPadding, + LocalFeedsFilterBarTonalElevation provides feedsFilterBarTonalElevation.value, + LocalFeedsTopBarTonalElevation provides feedsTopBarTonalElevation.value, + LocalFeedsGroupListExpand provides feedsGroupListExpand.value, + LocalFeedsGroupListTonalElevation provides feedsGroupListTonalElevation.value, + + LocalFlowFilterBarStyle provides flowFilterBarStyle.value, + LocalFlowFilterBarFilled provides flowFilterBarFilled.value, + LocalFlowFilterBarPadding provides flowFilterBarPadding, + LocalFlowFilterBarTonalElevation provides flowFilterBarTonalElevation.value, + LocalFlowTopBarTonalElevation provides flowTopBarTonalElevation.value, + LocalFlowArticleListFeedIcon provides flowArticleListFeedIcon.value, + LocalFlowArticleListFeedName provides flowArticleListFeedName.value, + LocalFlowArticleListImage provides flowArticleListImage.value, + LocalFlowArticleListDesc provides flowArticleListDesc.value, + LocalFlowArticleListDate provides flowArticleListDate.value, + LocalFlowArticleListTonalElevation provides flowArticleListTonalElevation.value, ) { MaterialTheme( colorScheme = diff --git a/app/src/main/java/me/ash/reader/ui/theme/palette/DynamicTonalPalette.kt b/app/src/main/java/me/ash/reader/ui/theme/palette/DynamicTonalPalette.kt index 818d16c..3df4107 100644 --- a/app/src/main/java/me/ash/reader/ui/theme/palette/DynamicTonalPalette.kt +++ b/app/src/main/java/me/ash/reader/ui/theme/palette/DynamicTonalPalette.kt @@ -31,6 +31,7 @@ fun dynamicLightColorScheme(): ColorScheme { onSurface = palettes neutral 10, surfaceVariant = palettes neutralVariant 90, onSurfaceVariant = palettes neutralVariant 30, + surfaceTint = palettes primary 40, inverseSurface = palettes neutral 20, inverseOnSurface = palettes neutral 95, outline = palettes neutralVariant 50, @@ -60,6 +61,7 @@ fun dynamicDarkColorScheme(): ColorScheme { onSurface = palettes neutral 90, surfaceVariant = palettes neutralVariant 30, onSurfaceVariant = palettes neutralVariant 80, + surfaceTint = palettes primary 80, inverseSurface = palettes neutral 90, inverseOnSurface = palettes neutral 20, outline = palettes neutralVariant 60, diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5920644..95f2e0d 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -99,7 +99,7 @@ 例如 #666666 或 666666 外观 样式 - 深色模式 + 深色主题 跟随系统设置 色调海拔 字体 @@ -124,4 +124,28 @@ 启动时 起始页面 起始过滤条件 + 呜呜呜,黎明之剑完结了 + 是宴席,就有结束的时候,但这本书真的陪了我好久啊,好舍不得,而且主线结束了坑却没填完,不知道啥时候才有番外啊 + 漩涡书院 + + 两端边距 + 显示文章发布时间 + 显示文章描述 + 显示文章插图 + 显示订阅源名称 + 显示订阅源图标 + 文章列表 + 分组列表 + 始终展开 + 顶部 + “标记为已读”按钮的位置 + 标题栏 + 填充已选中的图标 + 过滤栏 + 图标 + 图标和文字 + 图标和文字(仅选中时) + 标题栏的色调海拔仅在滚动时可用。 + 文章列表的色调海拔仅在亮色主题时可用。 + 分组列表的色调海拔仅在亮色主题时可用。 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 114011d..f72095b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,9 +88,9 @@ About, open source Welcome Before you can continue, you need to agree to Read You\'s Terms of Service and Privacy Policy. - View the <i><u>Terms of Service and Privacy Policy</u></i> + View the <i><u>Terms of Service & Privacy Policy</u></i> https://github.com/Ashinch/ReadYou/blob/main/TERMS_OF_SERVICE_AND_PRIVACY_POLICY.md - Agree and Continue + Agree Wallpaper Colors No Palettes Only Android 8.1+ @@ -116,7 +116,7 @@ Update Skip This Version Checking for updates… - This is the latest version + This is latest version Check failure Download failure The request rate is limited @@ -124,4 +124,28 @@ On Start Initial Page Initial Filter + The novel "Lord of the Mysteries" has finally come to an end + The Fool is the eighth and final volume of the Lord of the Mysteries series written by Cuttlefish That Loves Diving. + Reddit + value + Padding on Both Ends + Display Article Publish Time + Display Article Descriptions + Display Article Images + Display Feed Names + Display Feed Favicons + Article List + Group List + Always Expand + Top + \"Mark as Read\" Button Position + Top Bar + Fill The Selected Icon + Filter Bar + Icons + Icons & Labels + Icons & Label (Only Selected) + Tone elevation of the top bar is only available when scrolling. + Tone elevation of the article list is only available for light theme. + Tone elevation of the group list is only available for light theme. \ No newline at end of file