Optimize the flow page
This commit is contained in:
parent
ba3620d84f
commit
66094f8075
|
@ -0,0 +1,10 @@
|
||||||
|
package me.ash.reader.data.constant
|
||||||
|
|
||||||
|
object ElevationTokens {
|
||||||
|
const val Level0 = 0
|
||||||
|
const val Level1 = 1
|
||||||
|
const val Level2 = 3
|
||||||
|
const val Level3 = 6
|
||||||
|
const val Level4 = 8
|
||||||
|
const val Level5 = 12
|
||||||
|
}
|
|
@ -1,9 +1,6 @@
|
||||||
package me.ash.reader.data.entity
|
package me.ash.reader.data.entity
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.*
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.ForeignKey
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
|
@ -45,4 +42,7 @@ data class Article(
|
||||||
var isStarred: Boolean = false,
|
var isStarred: Boolean = false,
|
||||||
@ColumnInfo(defaultValue = "false")
|
@ColumnInfo(defaultValue = "false")
|
||||||
var isReadLater: Boolean = false,
|
var isReadLater: Boolean = false,
|
||||||
)
|
) {
|
||||||
|
@Ignore
|
||||||
|
var dateString: String? = null
|
||||||
|
}
|
|
@ -4,17 +4,18 @@ import android.content.Context
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.data.constant.ElevationTokens
|
||||||
import me.ash.reader.ui.ext.DataStoreKeys
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
import me.ash.reader.ui.ext.dataStore
|
import me.ash.reader.ui.ext.dataStore
|
||||||
import me.ash.reader.ui.ext.put
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
sealed class FeedsFilterBarTonalElevationPreference(val value: Int) : Preference() {
|
sealed class FeedsFilterBarTonalElevationPreference(val value: Int) : Preference() {
|
||||||
object Level0 : FeedsFilterBarTonalElevationPreference(0)
|
object Level0 : FeedsFilterBarTonalElevationPreference(ElevationTokens.Level0)
|
||||||
object Level1 : FeedsFilterBarTonalElevationPreference(1)
|
object Level1 : FeedsFilterBarTonalElevationPreference(ElevationTokens.Level1)
|
||||||
object Level2 : FeedsFilterBarTonalElevationPreference(3)
|
object Level2 : FeedsFilterBarTonalElevationPreference(ElevationTokens.Level2)
|
||||||
object Level3 : FeedsFilterBarTonalElevationPreference(6)
|
object Level3 : FeedsFilterBarTonalElevationPreference(ElevationTokens.Level3)
|
||||||
object Level4 : FeedsFilterBarTonalElevationPreference(8)
|
object Level4 : FeedsFilterBarTonalElevationPreference(ElevationTokens.Level4)
|
||||||
object Level5 : FeedsFilterBarTonalElevationPreference(12)
|
object Level5 : FeedsFilterBarTonalElevationPreference(ElevationTokens.Level5)
|
||||||
|
|
||||||
override fun put(context: Context, scope: CoroutineScope) {
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
@ -27,12 +28,12 @@ sealed class FeedsFilterBarTonalElevationPreference(val value: Int) : Preference
|
||||||
|
|
||||||
fun getDesc(context: Context): String =
|
fun getDesc(context: Context): String =
|
||||||
when (this) {
|
when (this) {
|
||||||
Level0 -> "Level 0 (0dp)"
|
Level0 -> "Level 0 (${ElevationTokens.Level0}dp)"
|
||||||
Level1 -> "Level 1 (1dp)"
|
Level1 -> "Level 1 (${ElevationTokens.Level1}dp)"
|
||||||
Level2 -> "Level 2 (3dp)"
|
Level2 -> "Level 2 (${ElevationTokens.Level2}dp)"
|
||||||
Level3 -> "Level 3 (6dp)"
|
Level3 -> "Level 3 (${ElevationTokens.Level3}dp)"
|
||||||
Level4 -> "Level 4 (8dp)"
|
Level4 -> "Level 4 (${ElevationTokens.Level4}dp)"
|
||||||
Level5 -> "Level 5 (12dp)"
|
Level5 -> "Level 5 (${ElevationTokens.Level5}dp)"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -41,13 +42,14 @@ sealed class FeedsFilterBarTonalElevationPreference(val value: Int) : Preference
|
||||||
|
|
||||||
fun fromPreferences(preferences: Preferences) =
|
fun fromPreferences(preferences: Preferences) =
|
||||||
when (preferences[DataStoreKeys.FeedsFilterBarTonalElevation.key]) {
|
when (preferences[DataStoreKeys.FeedsFilterBarTonalElevation.key]) {
|
||||||
0 -> Level0
|
ElevationTokens.Level0 -> Level0
|
||||||
1 -> Level1
|
ElevationTokens.Level1 -> Level1
|
||||||
3 -> Level2
|
ElevationTokens.Level2 -> Level2
|
||||||
6 -> Level3
|
ElevationTokens.Level3 -> Level3
|
||||||
8 -> Level4
|
ElevationTokens.Level4 -> Level4
|
||||||
12 -> Level5
|
ElevationTokens.Level5 -> Level5
|
||||||
else -> default
|
else -> default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,18 @@ import android.content.Context
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.data.constant.ElevationTokens
|
||||||
import me.ash.reader.ui.ext.DataStoreKeys
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
import me.ash.reader.ui.ext.dataStore
|
import me.ash.reader.ui.ext.dataStore
|
||||||
import me.ash.reader.ui.ext.put
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
sealed class FeedsGroupListTonalElevationPreference(val value: Int) : Preference() {
|
sealed class FeedsGroupListTonalElevationPreference(val value: Int) : Preference() {
|
||||||
object Level0 : FeedsGroupListTonalElevationPreference(0)
|
object Level0 : FeedsGroupListTonalElevationPreference(ElevationTokens.Level0)
|
||||||
object Level1 : FeedsGroupListTonalElevationPreference(1)
|
object Level1 : FeedsGroupListTonalElevationPreference(ElevationTokens.Level1)
|
||||||
object Level2 : FeedsGroupListTonalElevationPreference(3)
|
object Level2 : FeedsGroupListTonalElevationPreference(ElevationTokens.Level2)
|
||||||
object Level3 : FeedsGroupListTonalElevationPreference(6)
|
object Level3 : FeedsGroupListTonalElevationPreference(ElevationTokens.Level3)
|
||||||
object Level4 : FeedsGroupListTonalElevationPreference(8)
|
object Level4 : FeedsGroupListTonalElevationPreference(ElevationTokens.Level4)
|
||||||
object Level5 : FeedsGroupListTonalElevationPreference(12)
|
object Level5 : FeedsGroupListTonalElevationPreference(ElevationTokens.Level5)
|
||||||
|
|
||||||
override fun put(context: Context, scope: CoroutineScope) {
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
@ -27,12 +28,12 @@ sealed class FeedsGroupListTonalElevationPreference(val value: Int) : Preference
|
||||||
|
|
||||||
fun getDesc(context: Context): String =
|
fun getDesc(context: Context): String =
|
||||||
when (this) {
|
when (this) {
|
||||||
Level0 -> "Level 0 (0dp)"
|
Level0 -> "Level 0 (${ElevationTokens.Level0}dp)"
|
||||||
Level1 -> "Level 1 (1dp)"
|
Level1 -> "Level 1 (${ElevationTokens.Level1}dp)"
|
||||||
Level2 -> "Level 2 (3dp)"
|
Level2 -> "Level 2 (${ElevationTokens.Level2}dp)"
|
||||||
Level3 -> "Level 3 (6dp)"
|
Level3 -> "Level 3 (${ElevationTokens.Level3}dp)"
|
||||||
Level4 -> "Level 4 (8dp)"
|
Level4 -> "Level 4 (${ElevationTokens.Level4}dp)"
|
||||||
Level5 -> "Level 5 (12dp)"
|
Level5 -> "Level 5 (${ElevationTokens.Level5}dp)"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -41,12 +42,12 @@ sealed class FeedsGroupListTonalElevationPreference(val value: Int) : Preference
|
||||||
|
|
||||||
fun fromPreferences(preferences: Preferences) =
|
fun fromPreferences(preferences: Preferences) =
|
||||||
when (preferences[DataStoreKeys.FeedsGroupListTonalElevation.key]) {
|
when (preferences[DataStoreKeys.FeedsGroupListTonalElevation.key]) {
|
||||||
0 -> Level0
|
ElevationTokens.Level0 -> Level0
|
||||||
1 -> Level1
|
ElevationTokens.Level1 -> Level1
|
||||||
3 -> Level2
|
ElevationTokens.Level2 -> Level2
|
||||||
6 -> Level3
|
ElevationTokens.Level3 -> Level3
|
||||||
8 -> Level4
|
ElevationTokens.Level4 -> Level4
|
||||||
12 -> Level5
|
ElevationTokens.Level5 -> Level5
|
||||||
else -> default
|
else -> default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,18 @@ import android.content.Context
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.data.constant.ElevationTokens
|
||||||
import me.ash.reader.ui.ext.DataStoreKeys
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
import me.ash.reader.ui.ext.dataStore
|
import me.ash.reader.ui.ext.dataStore
|
||||||
import me.ash.reader.ui.ext.put
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
sealed class FeedsTopBarTonalElevationPreference(val value: Int) : Preference() {
|
sealed class FeedsTopBarTonalElevationPreference(val value: Int) : Preference() {
|
||||||
object Level0 : FeedsTopBarTonalElevationPreference(0)
|
object Level0 : FeedsTopBarTonalElevationPreference(ElevationTokens.Level0)
|
||||||
object Level1 : FeedsTopBarTonalElevationPreference(1)
|
object Level1 : FeedsTopBarTonalElevationPreference(ElevationTokens.Level1)
|
||||||
object Level2 : FeedsTopBarTonalElevationPreference(3)
|
object Level2 : FeedsTopBarTonalElevationPreference(ElevationTokens.Level2)
|
||||||
object Level3 : FeedsTopBarTonalElevationPreference(6)
|
object Level3 : FeedsTopBarTonalElevationPreference(ElevationTokens.Level3)
|
||||||
object Level4 : FeedsTopBarTonalElevationPreference(8)
|
object Level4 : FeedsTopBarTonalElevationPreference(ElevationTokens.Level4)
|
||||||
object Level5 : FeedsTopBarTonalElevationPreference(12)
|
object Level5 : FeedsTopBarTonalElevationPreference(ElevationTokens.Level5)
|
||||||
|
|
||||||
override fun put(context: Context, scope: CoroutineScope) {
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
@ -27,12 +28,12 @@ sealed class FeedsTopBarTonalElevationPreference(val value: Int) : Preference()
|
||||||
|
|
||||||
fun getDesc(context: Context): String =
|
fun getDesc(context: Context): String =
|
||||||
when (this) {
|
when (this) {
|
||||||
Level0 -> "Level 0 (0dp)"
|
Level0 -> "Level 0 (${ElevationTokens.Level0}dp)"
|
||||||
Level1 -> "Level 1 (1dp)"
|
Level1 -> "Level 1 (${ElevationTokens.Level1}dp)"
|
||||||
Level2 -> "Level 2 (3dp)"
|
Level2 -> "Level 2 (${ElevationTokens.Level2}dp)"
|
||||||
Level3 -> "Level 3 (6dp)"
|
Level3 -> "Level 3 (${ElevationTokens.Level3}dp)"
|
||||||
Level4 -> "Level 4 (8dp)"
|
Level4 -> "Level 4 (${ElevationTokens.Level4}dp)"
|
||||||
Level5 -> "Level 5 (12dp)"
|
Level5 -> "Level 5 (${ElevationTokens.Level5}dp)"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -41,12 +42,12 @@ sealed class FeedsTopBarTonalElevationPreference(val value: Int) : Preference()
|
||||||
|
|
||||||
fun fromPreferences(preferences: Preferences) =
|
fun fromPreferences(preferences: Preferences) =
|
||||||
when (preferences[DataStoreKeys.FeedsTopBarTonalElevation.key]) {
|
when (preferences[DataStoreKeys.FeedsTopBarTonalElevation.key]) {
|
||||||
0 -> Level0
|
ElevationTokens.Level0 -> Level0
|
||||||
1 -> Level1
|
ElevationTokens.Level1 -> Level1
|
||||||
3 -> Level2
|
ElevationTokens.Level2 -> Level2
|
||||||
6 -> Level3
|
ElevationTokens.Level3 -> Level3
|
||||||
8 -> Level4
|
ElevationTokens.Level4 -> Level4
|
||||||
12 -> Level5
|
ElevationTokens.Level5 -> Level5
|
||||||
else -> default
|
else -> default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,18 @@ import android.content.Context
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.data.constant.ElevationTokens
|
||||||
import me.ash.reader.ui.ext.DataStoreKeys
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
import me.ash.reader.ui.ext.dataStore
|
import me.ash.reader.ui.ext.dataStore
|
||||||
import me.ash.reader.ui.ext.put
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
sealed class FlowArticleListTonalElevationPreference(val value: Int) : Preference() {
|
sealed class FlowArticleListTonalElevationPreference(val value: Int) : Preference() {
|
||||||
object Level0 : FlowArticleListTonalElevationPreference(0)
|
object Level0 : FlowArticleListTonalElevationPreference(ElevationTokens.Level0)
|
||||||
object Level1 : FlowArticleListTonalElevationPreference(1)
|
object Level1 : FlowArticleListTonalElevationPreference(ElevationTokens.Level1)
|
||||||
object Level2 : FlowArticleListTonalElevationPreference(3)
|
object Level2 : FlowArticleListTonalElevationPreference(ElevationTokens.Level2)
|
||||||
object Level3 : FlowArticleListTonalElevationPreference(6)
|
object Level3 : FlowArticleListTonalElevationPreference(ElevationTokens.Level3)
|
||||||
object Level4 : FlowArticleListTonalElevationPreference(8)
|
object Level4 : FlowArticleListTonalElevationPreference(ElevationTokens.Level4)
|
||||||
object Level5 : FlowArticleListTonalElevationPreference(12)
|
object Level5 : FlowArticleListTonalElevationPreference(ElevationTokens.Level5)
|
||||||
|
|
||||||
override fun put(context: Context, scope: CoroutineScope) {
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
@ -27,12 +28,12 @@ sealed class FlowArticleListTonalElevationPreference(val value: Int) : Preferenc
|
||||||
|
|
||||||
fun getDesc(context: Context): String =
|
fun getDesc(context: Context): String =
|
||||||
when (this) {
|
when (this) {
|
||||||
Level0 -> "Level 0 (0dp)"
|
Level0 -> "Level 0 (${ElevationTokens.Level0}dp)"
|
||||||
Level1 -> "Level 1 (1dp)"
|
Level1 -> "Level 1 (${ElevationTokens.Level1}dp)"
|
||||||
Level2 -> "Level 2 (3dp)"
|
Level2 -> "Level 2 (${ElevationTokens.Level2}dp)"
|
||||||
Level3 -> "Level 3 (6dp)"
|
Level3 -> "Level 3 (${ElevationTokens.Level3}dp)"
|
||||||
Level4 -> "Level 4 (8dp)"
|
Level4 -> "Level 4 (${ElevationTokens.Level4}dp)"
|
||||||
Level5 -> "Level 5 (12dp)"
|
Level5 -> "Level 5 (${ElevationTokens.Level5}dp)"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -41,12 +42,12 @@ sealed class FlowArticleListTonalElevationPreference(val value: Int) : Preferenc
|
||||||
|
|
||||||
fun fromPreferences(preferences: Preferences) =
|
fun fromPreferences(preferences: Preferences) =
|
||||||
when (preferences[DataStoreKeys.FlowArticleListTonalElevation.key]) {
|
when (preferences[DataStoreKeys.FlowArticleListTonalElevation.key]) {
|
||||||
0 -> Level0
|
ElevationTokens.Level0 -> Level0
|
||||||
1 -> Level1
|
ElevationTokens.Level1 -> Level1
|
||||||
3 -> Level2
|
ElevationTokens.Level2 -> Level2
|
||||||
6 -> Level3
|
ElevationTokens.Level3 -> Level3
|
||||||
8 -> Level4
|
ElevationTokens.Level4 -> Level4
|
||||||
12 -> Level5
|
ElevationTokens.Level5 -> Level5
|
||||||
else -> default
|
else -> default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,18 @@ import android.content.Context
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.data.constant.ElevationTokens
|
||||||
import me.ash.reader.ui.ext.DataStoreKeys
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
import me.ash.reader.ui.ext.dataStore
|
import me.ash.reader.ui.ext.dataStore
|
||||||
import me.ash.reader.ui.ext.put
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
sealed class FlowFilterBarTonalElevationPreference(val value: Int) : Preference() {
|
sealed class FlowFilterBarTonalElevationPreference(val value: Int) : Preference() {
|
||||||
object Level0 : FlowFilterBarTonalElevationPreference(0)
|
object Level0 : FlowFilterBarTonalElevationPreference(ElevationTokens.Level0)
|
||||||
object Level1 : FlowFilterBarTonalElevationPreference(1)
|
object Level1 : FlowFilterBarTonalElevationPreference(ElevationTokens.Level1)
|
||||||
object Level2 : FlowFilterBarTonalElevationPreference(3)
|
object Level2 : FlowFilterBarTonalElevationPreference(ElevationTokens.Level2)
|
||||||
object Level3 : FlowFilterBarTonalElevationPreference(6)
|
object Level3 : FlowFilterBarTonalElevationPreference(ElevationTokens.Level3)
|
||||||
object Level4 : FlowFilterBarTonalElevationPreference(8)
|
object Level4 : FlowFilterBarTonalElevationPreference(ElevationTokens.Level4)
|
||||||
object Level5 : FlowFilterBarTonalElevationPreference(12)
|
object Level5 : FlowFilterBarTonalElevationPreference(ElevationTokens.Level5)
|
||||||
|
|
||||||
override fun put(context: Context, scope: CoroutineScope) {
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
@ -27,12 +28,12 @@ sealed class FlowFilterBarTonalElevationPreference(val value: Int) : Preference(
|
||||||
|
|
||||||
fun getDesc(context: Context): String =
|
fun getDesc(context: Context): String =
|
||||||
when (this) {
|
when (this) {
|
||||||
Level0 -> "Level 0 (0dp)"
|
Level0 -> "Level 0 (${ElevationTokens.Level0}dp)"
|
||||||
Level1 -> "Level 1 (1dp)"
|
Level1 -> "Level 1 (${ElevationTokens.Level1}dp)"
|
||||||
Level2 -> "Level 2 (3dp)"
|
Level2 -> "Level 2 (${ElevationTokens.Level2}dp)"
|
||||||
Level3 -> "Level 3 (6dp)"
|
Level3 -> "Level 3 (${ElevationTokens.Level3}dp)"
|
||||||
Level4 -> "Level 4 (8dp)"
|
Level4 -> "Level 4 (${ElevationTokens.Level4}dp)"
|
||||||
Level5 -> "Level 5 (12dp)"
|
Level5 -> "Level 5 (${ElevationTokens.Level5}dp)"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -41,12 +42,12 @@ sealed class FlowFilterBarTonalElevationPreference(val value: Int) : Preference(
|
||||||
|
|
||||||
fun fromPreferences(preferences: Preferences) =
|
fun fromPreferences(preferences: Preferences) =
|
||||||
when (preferences[DataStoreKeys.FlowFilterBarTonalElevation.key]) {
|
when (preferences[DataStoreKeys.FlowFilterBarTonalElevation.key]) {
|
||||||
0 -> Level0
|
ElevationTokens.Level0 -> Level0
|
||||||
1 -> Level1
|
ElevationTokens.Level1 -> Level1
|
||||||
3 -> Level2
|
ElevationTokens.Level2 -> Level2
|
||||||
6 -> Level3
|
ElevationTokens.Level3 -> Level3
|
||||||
8 -> Level4
|
ElevationTokens.Level4 -> Level4
|
||||||
12 -> Level5
|
ElevationTokens.Level5 -> Level5
|
||||||
else -> default
|
else -> default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,18 @@ import android.content.Context
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.data.constant.ElevationTokens
|
||||||
import me.ash.reader.ui.ext.DataStoreKeys
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
import me.ash.reader.ui.ext.dataStore
|
import me.ash.reader.ui.ext.dataStore
|
||||||
import me.ash.reader.ui.ext.put
|
import me.ash.reader.ui.ext.put
|
||||||
|
|
||||||
sealed class FlowTopBarTonalElevationPreference(val value: Int) : Preference() {
|
sealed class FlowTopBarTonalElevationPreference(val value: Int) : Preference() {
|
||||||
object Level0 : FlowTopBarTonalElevationPreference(0)
|
object Level0 : FlowTopBarTonalElevationPreference(ElevationTokens.Level0)
|
||||||
object Level1 : FlowTopBarTonalElevationPreference(1)
|
object Level1 : FlowTopBarTonalElevationPreference(ElevationTokens.Level1)
|
||||||
object Level2 : FlowTopBarTonalElevationPreference(3)
|
object Level2 : FlowTopBarTonalElevationPreference(ElevationTokens.Level2)
|
||||||
object Level3 : FlowTopBarTonalElevationPreference(6)
|
object Level3 : FlowTopBarTonalElevationPreference(ElevationTokens.Level3)
|
||||||
object Level4 : FlowTopBarTonalElevationPreference(8)
|
object Level4 : FlowTopBarTonalElevationPreference(ElevationTokens.Level4)
|
||||||
object Level5 : FlowTopBarTonalElevationPreference(12)
|
object Level5 : FlowTopBarTonalElevationPreference(ElevationTokens.Level5)
|
||||||
|
|
||||||
override fun put(context: Context, scope: CoroutineScope) {
|
override fun put(context: Context, scope: CoroutineScope) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
@ -27,12 +28,12 @@ sealed class FlowTopBarTonalElevationPreference(val value: Int) : Preference() {
|
||||||
|
|
||||||
fun getDesc(context: Context): String =
|
fun getDesc(context: Context): String =
|
||||||
when (this) {
|
when (this) {
|
||||||
Level0 -> "Level 0 (0dp)"
|
Level0 -> "Level 0 (${ElevationTokens.Level0}dp)"
|
||||||
Level1 -> "Level 1 (1dp)"
|
Level1 -> "Level 1 (${ElevationTokens.Level1}dp)"
|
||||||
Level2 -> "Level 2 (3dp)"
|
Level2 -> "Level 2 (${ElevationTokens.Level2}dp)"
|
||||||
Level3 -> "Level 3 (6dp)"
|
Level3 -> "Level 3 (${ElevationTokens.Level3}dp)"
|
||||||
Level4 -> "Level 4 (8dp)"
|
Level4 -> "Level 4 (${ElevationTokens.Level4}dp)"
|
||||||
Level5 -> "Level 5 (12dp)"
|
Level5 -> "Level 5 (${ElevationTokens.Level5}dp)"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -41,12 +42,12 @@ sealed class FlowTopBarTonalElevationPreference(val value: Int) : Preference() {
|
||||||
|
|
||||||
fun fromPreferences(preferences: Preferences) =
|
fun fromPreferences(preferences: Preferences) =
|
||||||
when (preferences[DataStoreKeys.FlowTopBarTonalElevation.key]) {
|
when (preferences[DataStoreKeys.FlowTopBarTonalElevation.key]) {
|
||||||
0 -> Level0
|
ElevationTokens.Level0 -> Level0
|
||||||
1 -> Level1
|
ElevationTokens.Level1 -> Level1
|
||||||
3 -> Level2
|
ElevationTokens.Level2 -> Level2
|
||||||
6 -> Level3
|
ElevationTokens.Level3 -> Level3
|
||||||
8 -> Level4
|
ElevationTokens.Level4 -> Level4
|
||||||
12 -> Level5
|
ElevationTokens.Level5 -> Level5
|
||||||
else -> default
|
else -> default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ class OpmlRepository @Inject constructor(
|
||||||
Opml(
|
Opml(
|
||||||
"2.0",
|
"2.0",
|
||||||
Head(
|
Head(
|
||||||
accountDao.queryById(context.currentAccountId).name,
|
accountDao.queryById(context.currentAccountId)?.name,
|
||||||
Date().toString(), null, null, null,
|
Date().toString(), null, null, null,
|
||||||
null, null, null, null,
|
null, null, null, null,
|
||||||
null, null, null, null,
|
null, null, null, null,
|
||||||
|
|
|
@ -21,8 +21,6 @@ import net.dankito.readability4j.extended.Readability4JExtended
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.text.ParsePosition
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -86,7 +84,12 @@ class RssHelper @Inject constructor(
|
||||||
return withContext(dispatcherIO) {
|
return withContext(dispatcherIO) {
|
||||||
val a = mutableListOf<Article>()
|
val a = mutableListOf<Article>()
|
||||||
val accountId = context.currentAccountId
|
val accountId = context.currentAccountId
|
||||||
val parseRss: SyndFeed = SyndFeedInput().build(XmlReader(URL(feed.url)))
|
val parseRss: SyndFeed = SyndFeedInput().build(
|
||||||
|
XmlReader(URL(feed.url).openConnection().apply {
|
||||||
|
connectTimeout = 5000
|
||||||
|
readTimeout = 5000
|
||||||
|
})
|
||||||
|
)
|
||||||
parseRss.entries.forEach {
|
parseRss.entries.forEach {
|
||||||
if (latestLink != null && latestLink == it.link) return@withContext a
|
if (latestLink != null && latestLink == it.link) return@withContext a
|
||||||
val desc = it.description?.value
|
val desc = it.description?.value
|
||||||
|
@ -111,13 +114,13 @@ class RssHelper @Inject constructor(
|
||||||
date = it.publishedDate ?: it.updatedDate ?: Date(),
|
date = it.publishedDate ?: it.updatedDate ?: Date(),
|
||||||
title = Html.fromHtml(it.title.toString()).toString(),
|
title = Html.fromHtml(it.title.toString()).toString(),
|
||||||
author = it.author,
|
author = it.author,
|
||||||
rawDescription = (desc ?: content) ?: "",
|
rawDescription = (content ?: desc) ?: "",
|
||||||
shortDescription = (Readability4JExtended("", desc ?: content ?: "")
|
shortDescription = (Readability4JExtended("", desc ?: content ?: "")
|
||||||
.parse().textContent ?: "")
|
.parse().textContent ?: "")
|
||||||
.take(100)
|
.take(100)
|
||||||
.trim(),
|
.trim(),
|
||||||
fullContent = content,
|
fullContent = content,
|
||||||
img = findImg((desc ?: content) ?: ""),
|
img = findImg((content ?: desc) ?: ""),
|
||||||
link = it.link ?: "",
|
link = it.link ?: "",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,6 +11,13 @@ class StringsRepository @Inject constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
) {
|
) {
|
||||||
fun getString(resId: Int, vararg formatArgs: Any) = context.getString(resId, *formatArgs)
|
fun getString(resId: Int, vararg formatArgs: Any) = context.getString(resId, *formatArgs)
|
||||||
fun getQuantityString(resId: Int, quantity: Int, vararg formatArgs: Any) = context.resources.getQuantityString(resId, quantity, *formatArgs)
|
|
||||||
fun formatAsString(date: Date?) = date?.formatAsString(context)
|
fun getQuantityString(resId: Int, quantity: Int, vararg formatArgs: Any) =
|
||||||
|
context.resources.getQuantityString(resId, quantity, *formatArgs)
|
||||||
|
|
||||||
|
fun formatAsString(
|
||||||
|
date: Date?,
|
||||||
|
onlyHourMinute: Boolean? = false,
|
||||||
|
atHourMinute: Boolean? = false
|
||||||
|
) = date?.formatAsString(context, onlyHourMinute, atHourMinute)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import coil.size.Scale
|
||||||
import coil.size.Size
|
import coil.size.Size
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
|
|
||||||
val Size_1000 = Size(1000, 1000)
|
val SIZE_1000 = Size(1000, 1000)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RYAsyncImage(
|
fun RYAsyncImage(
|
||||||
|
|
|
@ -50,7 +50,12 @@ class HomeViewModel @Inject constructor(
|
||||||
fun fetchArticles() {
|
fun fetchArticles() {
|
||||||
_homeUiState.update {
|
_homeUiState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
pagingData = Pager(PagingConfig(pageSize = 50)) {
|
pagingData = Pager(
|
||||||
|
config = PagingConfig(
|
||||||
|
pageSize = 100,
|
||||||
|
enablePlaceholders = false,
|
||||||
|
)
|
||||||
|
) {
|
||||||
if (_homeUiState.value.searchContent.isNotBlank()) {
|
if (_homeUiState.value.searchContent.isNotBlank()) {
|
||||||
rssRepository.get().searchArticles(
|
rssRepository.get().searchArticles(
|
||||||
content = _homeUiState.value.searchContent.trim(),
|
content = _homeUiState.value.searchContent.trim(),
|
||||||
|
@ -68,7 +73,14 @@ class HomeViewModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.flow.map {
|
}.flow.map {
|
||||||
it.map { FlowItemView.Article(it) }.insertSeparators { before, after ->
|
it.map {
|
||||||
|
FlowItemView.Article(it.apply {
|
||||||
|
article.dateString = stringsRepository.formatAsString(
|
||||||
|
date = article.date,
|
||||||
|
onlyHourMinute = true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}.insertSeparators { before, after ->
|
||||||
val beforeDate =
|
val beforeDate =
|
||||||
stringsRepository.formatAsString(before?.articleWithFeed?.article?.date)
|
stringsRepository.formatAsString(before?.articleWithFeed?.article?.date)
|
||||||
val afterDate =
|
val afterDate =
|
||||||
|
|
|
@ -4,16 +4,13 @@ import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
import me.ash.reader.data.entity.Article
|
import me.ash.reader.data.entity.Article
|
||||||
import me.ash.reader.data.entity.Feed
|
import me.ash.reader.data.entity.Feed
|
||||||
import me.ash.reader.data.entity.Group
|
import me.ash.reader.data.entity.Group
|
||||||
import me.ash.reader.data.module.DispatcherIO
|
|
||||||
import me.ash.reader.data.repository.OpmlRepository
|
import me.ash.reader.data.repository.OpmlRepository
|
||||||
import me.ash.reader.data.repository.RssHelper
|
import me.ash.reader.data.repository.RssHelper
|
||||||
import me.ash.reader.data.repository.RssRepository
|
import me.ash.reader.data.repository.RssRepository
|
||||||
|
@ -28,8 +25,6 @@ class SubscribeViewModel @Inject constructor(
|
||||||
private val rssRepository: RssRepository,
|
private val rssRepository: RssRepository,
|
||||||
private val rssHelper: RssHelper,
|
private val rssHelper: RssHelper,
|
||||||
private val stringsRepository: StringsRepository,
|
private val stringsRepository: StringsRepository,
|
||||||
@DispatcherIO
|
|
||||||
private val dispatcherIO: CoroutineDispatcher,
|
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val _subscribeUiState = MutableStateFlow(SubscribeUiState())
|
private val _subscribeUiState = MutableStateFlow(SubscribeUiState())
|
||||||
val subscribeUiState: StateFlow<SubscribeUiState> = _subscribeUiState.asStateFlow()
|
val subscribeUiState: StateFlow<SubscribeUiState> = _subscribeUiState.asStateFlow()
|
||||||
|
@ -55,7 +50,7 @@ class SubscribeViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun importFromInputStream(inputStream: InputStream) {
|
fun importFromInputStream(inputStream: InputStream) {
|
||||||
viewModelScope.launch(dispatcherIO) {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
opmlRepository.saveToDatabase(inputStream)
|
opmlRepository.saveToDatabase(inputStream)
|
||||||
rssRepository.get().doSync()
|
rssRepository.get().doSync()
|
||||||
|
@ -68,13 +63,10 @@ class SubscribeViewModel @Inject constructor(
|
||||||
fun subscribe() {
|
fun subscribe() {
|
||||||
val feed = _subscribeUiState.value.feed ?: return
|
val feed = _subscribeUiState.value.feed ?: return
|
||||||
val articles = _subscribeUiState.value.articles
|
val articles = _subscribeUiState.value.articles
|
||||||
viewModelScope.launch(dispatcherIO) {
|
viewModelScope.launch {
|
||||||
val groupId = async {
|
|
||||||
_subscribeUiState.value.selectedGroupId
|
|
||||||
}
|
|
||||||
rssRepository.get().subscribe(
|
rssRepository.get().subscribe(
|
||||||
feed.copy(
|
feed.copy(
|
||||||
groupId = groupId.await(),
|
groupId = _subscribeUiState.value.selectedGroupId,
|
||||||
isNotification = _subscribeUiState.value.allowNotificationPreset,
|
isNotification = _subscribeUiState.value.allowNotificationPreset,
|
||||||
isFullContent = _subscribeUiState.value.parseFullContentPreset,
|
isFullContent = _subscribeUiState.value.parseFullContentPreset,
|
||||||
), articles
|
), articles
|
||||||
|
@ -123,7 +115,7 @@ class SubscribeViewModel @Inject constructor(
|
||||||
|
|
||||||
fun search() {
|
fun search() {
|
||||||
searchJob?.cancel()
|
searchJob?.cancel()
|
||||||
viewModelScope.launch(dispatcherIO) {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
_subscribeUiState.update {
|
_subscribeUiState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
|
|
|
@ -2,7 +2,6 @@ package me.ash.reader.ui.page.home.flow
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.Star
|
import androidx.compose.material.icons.rounded.Star
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
@ -23,10 +22,10 @@ import coil.size.Scale
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
import me.ash.reader.data.entity.ArticleWithFeed
|
import me.ash.reader.data.entity.ArticleWithFeed
|
||||||
import me.ash.reader.data.preference.*
|
import me.ash.reader.data.preference.*
|
||||||
import me.ash.reader.ui.component.base.RYAsyncImage
|
|
||||||
import me.ash.reader.ui.ext.formatAsString
|
|
||||||
import me.ash.reader.ui.component.FeedIcon
|
import me.ash.reader.ui.component.FeedIcon
|
||||||
import me.ash.reader.ui.component.base.Size_1000
|
import me.ash.reader.ui.component.base.RYAsyncImage
|
||||||
|
import me.ash.reader.ui.component.base.SIZE_1000
|
||||||
|
import me.ash.reader.ui.theme.SHAPE_20
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ArticleItem(
|
fun ArticleItem(
|
||||||
|
@ -43,7 +42,7 @@ fun ArticleItem(
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 12.dp)
|
.padding(horizontal = 12.dp)
|
||||||
.clip(RoundedCornerShape(20.dp))
|
.clip(SHAPE_20)
|
||||||
.clickable { onClick(articleWithFeed) }
|
.clickable { onClick(articleWithFeed) }
|
||||||
.padding(horizontal = 12.dp, vertical = 12.dp)
|
.padding(horizontal = 12.dp, vertical = 12.dp)
|
||||||
.alpha(if (articleWithFeed.article.isStarred || articleWithFeed.article.isUnread) 1f else 0.5f),
|
.alpha(if (articleWithFeed.article.isStarred || articleWithFeed.article.isUnread) 1f else 0.5f),
|
||||||
|
@ -80,21 +79,20 @@ fun ArticleItem(
|
||||||
if (articleWithFeed.article.isStarred) {
|
if (articleWithFeed.article.isStarred) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.alpha(0.7f)
|
||||||
.size(14.dp)
|
.size(14.dp)
|
||||||
.padding(end = 2.dp),
|
.padding(end = 2.dp),
|
||||||
imageVector = Icons.Rounded.Star,
|
imageVector = Icons.Rounded.Star,
|
||||||
contentDescription = stringResource(R.string.starred),
|
contentDescription = stringResource(R.string.starred),
|
||||||
tint = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
tint = MaterialTheme.colorScheme.outline,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Date
|
// Date
|
||||||
Text(
|
Text(
|
||||||
text = articleWithFeed.article.date.formatAsString(
|
modifier = Modifier.alpha(0.7f),
|
||||||
context,
|
text = articleWithFeed.article.dateString ?: "",
|
||||||
onlyHourMinute = true
|
color = MaterialTheme.colorScheme.outline,
|
||||||
),
|
|
||||||
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -128,8 +126,9 @@ fun ArticleItem(
|
||||||
// Description
|
// Description
|
||||||
if (articleListDesc.value && articleWithFeed.article.shortDescription.isNotBlank()) {
|
if (articleListDesc.value && articleWithFeed.article.shortDescription.isNotBlank()) {
|
||||||
Text(
|
Text(
|
||||||
|
modifier = Modifier.alpha(0.7f),
|
||||||
text = articleWithFeed.article.shortDescription,
|
text = articleWithFeed.article.shortDescription,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
@ -143,11 +142,11 @@ fun ArticleItem(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 10.dp)
|
.padding(start = 10.dp)
|
||||||
.size(80.dp)
|
.size(80.dp)
|
||||||
.clip(RoundedCornerShape(20.dp)),
|
.clip(SHAPE_20),
|
||||||
data = articleWithFeed.article.img,
|
data = articleWithFeed.article.img,
|
||||||
scale = Scale.FILL,
|
scale = Scale.FILL,
|
||||||
precision = Precision.INEXACT,
|
precision = Precision.INEXACT,
|
||||||
size = Size_1000,
|
size = SIZE_1000,
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ import me.ash.reader.data.entity.ArticleWithFeed
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
fun LazyListScope.ArticleList(
|
fun LazyListScope.ArticleList(
|
||||||
pagingItems: LazyPagingItems<FlowItemView>,
|
pagingItems: LazyPagingItems<FlowItemView>,
|
||||||
articleListFeedIcon: Boolean,
|
isShowFeedIcon: Boolean,
|
||||||
articleListDateStickyHeader: Boolean,
|
isShowStickyHeader: Boolean,
|
||||||
articleListTonalElevation: Int,
|
articleListTonalElevation: Int,
|
||||||
onClick: (ArticleWithFeed) -> Unit = {},
|
onClick: (ArticleWithFeed) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
|
@ -31,13 +31,13 @@ fun LazyListScope.ArticleList(
|
||||||
}
|
}
|
||||||
is FlowItemView.Date -> {
|
is FlowItemView.Date -> {
|
||||||
if (item.showSpacer) item { Spacer(modifier = Modifier.height(40.dp)) }
|
if (item.showSpacer) item { Spacer(modifier = Modifier.height(40.dp)) }
|
||||||
if (articleListDateStickyHeader) {
|
if (isShowStickyHeader) {
|
||||||
stickyHeader(key = item.date) {
|
stickyHeader(key = item.date) {
|
||||||
StickyHeader(item.date, articleListFeedIcon, articleListTonalElevation)
|
StickyHeader(item.date, isShowFeedIcon, articleListTonalElevation)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
item(key = item.date) {
|
item(key = item.date) {
|
||||||
StickyHeader(item.date, articleListFeedIcon, articleListTonalElevation)
|
StickyHeader(item.date, isShowFeedIcon, articleListTonalElevation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ import me.ash.reader.ui.component.base.RYScaffold
|
||||||
import me.ash.reader.ui.component.base.SwipeRefresh
|
import me.ash.reader.ui.component.base.SwipeRefresh
|
||||||
import me.ash.reader.ui.ext.collectAsStateValue
|
import me.ash.reader.ui.ext.collectAsStateValue
|
||||||
import me.ash.reader.ui.page.common.RouteName
|
import me.ash.reader.ui.page.common.RouteName
|
||||||
import me.ash.reader.ui.page.home.FilterState
|
|
||||||
import me.ash.reader.ui.page.home.HomeViewModel
|
import me.ash.reader.ui.page.home.HomeViewModel
|
||||||
|
|
||||||
@OptIn(
|
@OptIn(
|
||||||
|
@ -165,7 +164,15 @@ fun FlowPage(
|
||||||
state = listState,
|
state = listState,
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
DisplayTextHeader(filterUiState, isSyncing, articleListFeedIcon.value)
|
DisplayText(
|
||||||
|
modifier = Modifier.padding(start = if (articleListFeedIcon.value) 30.dp else 0.dp),
|
||||||
|
text = when {
|
||||||
|
filterUiState.group != null -> filterUiState.group.name
|
||||||
|
filterUiState.feed != null -> filterUiState.feed.name
|
||||||
|
else -> filterUiState.filter.getName()
|
||||||
|
},
|
||||||
|
desc = if (isSyncing) stringResource(R.string.syncing) else "",
|
||||||
|
)
|
||||||
RYExtensibleVisibility(visible = markAsRead) {
|
RYExtensibleVisibility(visible = markAsRead) {
|
||||||
Spacer(modifier = Modifier.height((56 + 24 + 10).dp))
|
Spacer(modifier = Modifier.height((56 + 24 + 10).dp))
|
||||||
}
|
}
|
||||||
|
@ -217,8 +224,8 @@ fun FlowPage(
|
||||||
}
|
}
|
||||||
ArticleList(
|
ArticleList(
|
||||||
pagingItems = pagingItems,
|
pagingItems = pagingItems,
|
||||||
articleListFeedIcon = articleListFeedIcon.value,
|
isShowFeedIcon = articleListFeedIcon.value,
|
||||||
articleListDateStickyHeader = articleListDateStickyHeader.value,
|
isShowStickyHeader = articleListDateStickyHeader.value,
|
||||||
articleListTonalElevation = articleListTonalElevation.value,
|
articleListTonalElevation = articleListTonalElevation.value,
|
||||||
) {
|
) {
|
||||||
onSearch = false
|
onSearch = false
|
||||||
|
@ -248,20 +255,3 @@ fun FlowPage(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun DisplayTextHeader(
|
|
||||||
filterState: FilterState,
|
|
||||||
isSyncing: Boolean,
|
|
||||||
articleListFeedIcon: Boolean,
|
|
||||||
) {
|
|
||||||
DisplayText(
|
|
||||||
modifier = Modifier.padding(start = if (articleListFeedIcon) 30.dp else 0.dp),
|
|
||||||
text = when {
|
|
||||||
filterState.group != null -> filterState.group.name
|
|
||||||
filterState.feed != null -> filterState.feed.name
|
|
||||||
else -> filterState.filter.getName()
|
|
||||||
},
|
|
||||||
desc = if (isSyncing) stringResource(R.string.syncing) else "",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import kotlinx.coroutines.launch
|
||||||
import me.ash.reader.data.entity.ArticleWithFeed
|
import me.ash.reader.data.entity.ArticleWithFeed
|
||||||
import me.ash.reader.data.repository.RssRepository
|
import me.ash.reader.data.repository.RssRepository
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.annotation.concurrent.Immutable
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
|
@ -77,10 +76,7 @@ enum class MarkAsReadBefore {
|
||||||
All,
|
All,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
|
||||||
sealed class FlowItemView {
|
sealed class FlowItemView {
|
||||||
@Immutable
|
|
||||||
class Article(val articleWithFeed: ArticleWithFeed) : FlowItemView()
|
class Article(val articleWithFeed: ArticleWithFeed) : FlowItemView()
|
||||||
@Immutable
|
|
||||||
class Date(val date: String, val showSpacer: Boolean) : FlowItemView()
|
class Date(val date: String, val showSpacer: Boolean) : FlowItemView()
|
||||||
}
|
}
|
|
@ -12,19 +12,19 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.style.BaselineShift
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.constant.ElevationTokens
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchBar(
|
fun SearchBar(
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
value: String,
|
value: String,
|
||||||
placeholder: String = "",
|
placeholder: String = "",
|
||||||
focusRequester: FocusRequester = remember { FocusRequester() },
|
focusRequester: FocusRequester = remember { FocusRequester() },
|
||||||
|
@ -39,7 +39,7 @@ fun SearchBar(
|
||||||
.padding(horizontal = 24.dp)
|
.padding(horizontal = 24.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
tonalElevation = 3.dp
|
tonalElevation = ElevationTokens.Level2.dp
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
@ -62,6 +62,7 @@ fun SearchBar(
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.focusRequester(focusRequester),
|
.focusRequester(focusRequester),
|
||||||
colors = TextFieldDefaults.textFieldColors(
|
colors = TextFieldDefaults.textFieldColors(
|
||||||
|
textColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
focusedIndicatorColor = Color.Transparent,
|
focusedIndicatorColor = Color.Transparent,
|
||||||
unfocusedIndicatorColor = Color.Transparent,
|
unfocusedIndicatorColor = Color.Transparent,
|
||||||
|
@ -70,17 +71,13 @@ fun SearchBar(
|
||||||
onValueChange = { onValueChange(it) },
|
onValueChange = { onValueChange(it) },
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
|
modifier = Modifier.alpha(0.7f),
|
||||||
text = placeholder,
|
text = placeholder,
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
alpha = 0.7f
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
textStyle = MaterialTheme.typography.bodyLarge.copy(
|
textStyle = MaterialTheme.typography.bodyLarge,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
baselineShift = BaselineShift(0.1f)
|
|
||||||
),
|
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
imeAction = ImeAction.Done
|
imeAction = ImeAction.Done
|
||||||
|
|
|
@ -15,8 +15,8 @@ import me.ash.reader.ui.theme.palette.onDark
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun StickyHeader(
|
fun StickyHeader(
|
||||||
currentItemDay: String,
|
dateString: String,
|
||||||
articleListFeedIcon: Boolean,
|
isShowFeedIcon: Boolean,
|
||||||
articleListTonalElevation: Int,
|
articleListTonalElevation: Int,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
@ -30,10 +30,10 @@ fun StickyHeader(
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
start = if (articleListFeedIcon) 54.dp else 24.dp,
|
start = if (isShowFeedIcon) 54.dp else 24.dp,
|
||||||
bottom = 4.dp
|
bottom = 4.dp
|
||||||
),
|
),
|
||||||
text = currentItemDay,
|
text = dateString,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,7 +18,7 @@ import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ReadingViewModel @Inject constructor(
|
class ReadingViewModel @Inject constructor(
|
||||||
val rssRepository: RssRepository,
|
private val rssRepository: RssRepository,
|
||||||
private val rssHelper: RssHelper,
|
private val rssHelper: RssHelper,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val _readingUiState = MutableStateFlow(ReadingUiState())
|
private val _readingUiState = MutableStateFlow(ReadingUiState())
|
||||||
|
|
15
app/src/main/java/me/ash/reader/ui/theme/Shapes.kt
Normal file
15
app/src/main/java/me/ash/reader/ui/theme/Shapes.kt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package me.ash.reader.ui.theme
|
||||||
|
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Shapes
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
val Shapes = Shapes(
|
||||||
|
extraSmall = RoundedCornerShape(4.0.dp),
|
||||||
|
small = RoundedCornerShape(8.0.dp),
|
||||||
|
medium = RoundedCornerShape(12.0.dp),
|
||||||
|
large = RoundedCornerShape(16.0.dp),
|
||||||
|
extraLarge = RoundedCornerShape(28.0.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
val SHAPE_20 = RoundedCornerShape(20.0.dp)
|
|
@ -40,7 +40,8 @@ fun AppTheme(
|
||||||
if (useDarkTheme) dynamicDarkColorScheme()
|
if (useDarkTheme) dynamicDarkColorScheme()
|
||||||
else dynamicLightColorScheme(),
|
else dynamicLightColorScheme(),
|
||||||
typography = AppTypography,
|
typography = AppTypography,
|
||||||
content = content
|
shapes = Shapes,
|
||||||
|
content = content,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,6 @@
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19v-4.58l0.99,0.99 4,-4 4,4 4,-3.99L19,12.43L19,19zM19,9.59l-1.01,-1.01 -4,4.01 -4,-4 -4,4 -0.99,-1L5,5h14v4.59z"
|
android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19v-4.58l0.99,0.99 4,-4 4,4 4,-3.99L19,12.43L19,19zM19,9.59l-1.01,-1.01 -4,4.01 -4,-4 -4,4 -0.99,-1L5,5h14v4.59z"
|
||||||
android:fillColor="#000000"/>
|
android:fillColor="#000000"
|
||||||
|
android:fillAlpha="0.3"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -5,5 +5,6 @@
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:pathData="M8,2c-1.1,0 -2,0.9 -2,2v3.17c0,0.53 0.21,1.04 0.59,1.42L10,12l-3.42,3.42c-0.37,0.38 -0.58,0.89 -0.58,1.42L6,20c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2v-3.16c0,-0.53 -0.21,-1.04 -0.58,-1.41L14,12l3.41,-3.4c0.38,-0.38 0.59,-0.89 0.59,-1.42L18,4c0,-1.1 -0.9,-2 -2,-2L8,2zM16,16.5L16,19c0,0.55 -0.45,1 -1,1L9,20c-0.55,0 -1,-0.45 -1,-1v-2.5l4,-4 4,4zM12,11.5l-4,-4L8,5c0,-0.55 0.45,-1 1,-1h6c0.55,0 1,0.45 1,1v2.5l-4,4z"
|
android:pathData="M8,2c-1.1,0 -2,0.9 -2,2v3.17c0,0.53 0.21,1.04 0.59,1.42L10,12l-3.42,3.42c-0.37,0.38 -0.58,0.89 -0.58,1.42L6,20c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2v-3.16c0,-0.53 -0.21,-1.04 -0.58,-1.41L14,12l3.41,-3.4c0.38,-0.38 0.59,-0.89 0.59,-1.42L18,4c0,-1.1 -0.9,-2 -2,-2L8,2zM16,16.5L16,19c0,0.55 -0.45,1 -1,1L9,20c-0.55,0 -1,-0.45 -1,-1v-2.5l4,-4 4,4zM12,11.5l-4,-4L8,5c0,-0.55 0.45,-1 1,-1h6c0.55,0 1,0.45 1,1v2.5l-4,4z"
|
||||||
android:fillColor="#000000"/>
|
android:fillColor="#000000"
|
||||||
|
android:fillAlpha="0.3"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user