Skip to content

Commit

Permalink
[feature|optimize|build] Support hide the duplicate title present in …
Browse files Browse the repository at this point in the history
…description; support swipe on article item; migrate feed screen, media screen, article screen, search screen to Compose; update dependencies
  • Loading branch information
SkyD666 committed Apr 22, 2024
1 parent 7a63462 commit bbb85e8
Show file tree
Hide file tree
Showing 126 changed files with 3,381 additions and 2,634 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<b>AniVu</b>, an <b>all-in-one tool</b> for <b>RSS anime subscription and updates</b>, <b>bit torrent downloads</b>, and <b>video playback</b>.
</p>
<p>
AniVu utilizes the <b><a href="https://developer.android.com/topic/architecture#recommended-app-arch">MVI</a></b> architecture and fully adopts the <b><a href="https://m3.material.io/">Material You</a></b> design style. All pages are developed using <b>Android View</b>.
AniVu utilizes the <b><a href="https://developer.android.com/topic/architecture#recommended-app-arch">MVI</a></b> architecture and fully adopts the <b><a href="https://m3.material.io/">Material You</a></b> design style. All pages are developed using <b>Android View</b> and <b>Jetpack Compose</b>.
</p>
<p>
<b><a href="doc/readme/README-zh-rCN.md">中文</a></b>
Expand All @@ -39,6 +39,7 @@




## 💡 Features

1. **Subscribe to RSS**, Update RSS, **Read** RSS
Expand Down Expand Up @@ -72,6 +73,7 @@
## 🛠 Primary technology stack

- **MVI** Architecture
- Jetpack **Compose**
- Kotlin **Coroutines and Flow**
- **Material You**
- **ViewModel**
Expand Down
12 changes: 8 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ android {
minSdk = 24
targetSdk = 34
versionCode = 13
versionName = "1.1-beta11"
versionName = "1.1-beta12"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -144,8 +144,10 @@ dependencies {
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
implementation("androidx.navigation:navigation-compose:2.7.7")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")
implementation("androidx.compose.ui:ui:1.6.5")
implementation("androidx.compose.material:material:1.6.5")
implementation("androidx.compose.material3:material3:1.2.1")
implementation("androidx.compose.material3:material3-window-size-class:1.2.1")
implementation("androidx.compose.material:material-icons-extended:1.6.5")
Expand All @@ -158,10 +160,11 @@ dependencies {
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("androidx.media3:media3-exoplayer:1.3.0")
implementation("androidx.media3:media3-exoplayer-dash:1.3.0")
implementation("androidx.media3:media3-ui:1.3.0")
implementation("androidx.media3:media3-exoplayer:1.3.1")
implementation("androidx.media3:media3-exoplayer-dash:1.3.1")
implementation("androidx.media3:media3-ui:1.3.1")
implementation("androidx.paging:paging-runtime-ktx:3.2.1")
implementation("androidx.paging:paging-compose:3.3.0-beta01")
implementation("androidx.preference:preference-ktx:1.2.1")
implementation("com.google.code.gson:gson:2.10.1")

Expand All @@ -180,6 +183,7 @@ dependencies {

implementation("io.coil-kt:coil:2.6.0")
implementation("io.coil-kt:coil-compose:2.6.0")
implementation("io.coil-kt:coil-gif:2.5.0")
implementation("com.rometools:rome:2.1.0")
implementation("net.dankito.readability4j:readability4j:1.0.8")

Expand Down
5 changes: 1 addition & 4 deletions app/src/main/java/com/skyd/anivu/base/BaseActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.skyd.anivu.base

import android.content.res.Resources
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
Expand Down Expand Up @@ -28,9 +27,7 @@ abstract class BaseActivity<T : ViewBinding> : AppCompatActivity() {
protected open fun T.initView() {}

protected open fun beforeSetContentView() {}
override fun getTheme(): Resources.Theme {
return super.getTheme()
}

private fun initTheme() {
setTheme(ThemePreference.toResId(this))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ abstract class BaseComposeFragment : Fragment() {
}
}

private val defaultTransitionProvider = BaseFragment.TransitionProvider()
protected val defaultTransitionProvider = BaseFragment.TransitionProvider()

protected val nullTransitionProvider: BaseFragment.TransitionProvider? = null

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/skyd/anivu/base/mvi/MviViewState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.skyd.anivu.base.mvi
import android.os.Bundle

/**
* Immutable object which contains all the required information to render a [MviView].
* Immutable object which contains all the required information to render a View.
*/
interface MviViewState

Expand Down
49 changes: 49 additions & 0 deletions app/src/main/java/com/skyd/anivu/ext/ColorExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.skyd.anivu.ext

import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Color
import com.skyd.anivu.model.preference.appearance.DarkModePreference
import com.skyd.anivu.ui.local.LocalDarkMode

@Stable
@Composable
@ReadOnlyComposable
infix fun Color.alwaysLight(isAlways: Boolean): Color {
val colorScheme = MaterialTheme.colorScheme
return if (isAlways && DarkModePreference.inDark(value = LocalDarkMode.current)) {
when (this) {
colorScheme.primary -> colorScheme.onPrimary
colorScheme.secondary -> colorScheme.onSecondary
colorScheme.tertiary -> colorScheme.onTertiary
colorScheme.background -> colorScheme.onBackground
colorScheme.error -> colorScheme.onError
colorScheme.surface -> colorScheme.onSurface
colorScheme.surfaceVariant -> colorScheme.onSurfaceVariant
colorScheme.primaryContainer -> colorScheme.onPrimaryContainer
colorScheme.secondaryContainer -> colorScheme.onSecondaryContainer
colorScheme.tertiaryContainer -> colorScheme.onTertiaryContainer
colorScheme.errorContainer -> colorScheme.onErrorContainer
colorScheme.inverseSurface -> colorScheme.inverseOnSurface

colorScheme.onPrimary -> colorScheme.primary
colorScheme.onSecondary -> colorScheme.secondary
colorScheme.onTertiary -> colorScheme.tertiary
colorScheme.onBackground -> colorScheme.background
colorScheme.onError -> colorScheme.error
colorScheme.onSurface -> colorScheme.surface
colorScheme.onSurfaceVariant -> colorScheme.surfaceVariant
colorScheme.onPrimaryContainer -> colorScheme.primaryContainer
colorScheme.onSecondaryContainer -> colorScheme.secondaryContainer
colorScheme.onTertiaryContainer -> colorScheme.tertiaryContainer
colorScheme.onErrorContainer -> colorScheme.errorContainer
colorScheme.inverseOnSurface -> colorScheme.inverseSurface

else -> Color.Unspecified
}
} else {
this
}
}
8 changes: 8 additions & 0 deletions app/src/main/java/com/skyd/anivu/ext/PreferenceExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import com.skyd.anivu.model.preference.IgnoreUpdateVersionPreference
import com.skyd.anivu.model.preference.Settings
import com.skyd.anivu.model.preference.appearance.DarkModePreference
import com.skyd.anivu.model.preference.appearance.ThemePreference
import com.skyd.anivu.model.preference.behavior.article.ArticleSwipeLeftActionPreference
import com.skyd.anivu.model.preference.behavior.article.ArticleTapActionPreference
import com.skyd.anivu.model.preference.behavior.article.DeduplicateTitleInDescPreference

fun Preferences.toSettings(): Settings {
return Settings(
Expand All @@ -14,5 +17,10 @@ fun Preferences.toSettings(): Settings {

// Update
ignoreUpdateVersion = IgnoreUpdateVersionPreference.fromPreferences(this),

// Behavior
deduplicateTitleInDesc = DeduplicateTitleInDescPreference.fromPreferences(this),
articleTapAction = ArticleTapActionPreference.fromPreferences(this),
articleSwipeLeftAction = ArticleSwipeLeftActionPreference.fromPreferences(this),
)
}
2 changes: 1 addition & 1 deletion app/src/main/java/com/skyd/anivu/model/db/dao/FeedDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ interface FeedDao {

@Transaction
@RawQuery(observedEntities = [FeedBean::class])
fun getFeedList(sql: SupportSQLiteQuery): List<FeedBean>
fun getFeedListPagingSource(sql: SupportSQLiteQuery): List<FeedBean>

@Transaction
@Query("SELECT ${FeedBean.URL_COLUMN} FROM $FEED_TABLE_NAME")
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/skyd/anivu/model/preference/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.toSettings
import com.skyd.anivu.model.preference.appearance.DarkModePreference
import com.skyd.anivu.model.preference.appearance.ThemePreference
import com.skyd.anivu.model.preference.behavior.article.ArticleSwipeLeftActionPreference
import com.skyd.anivu.model.preference.behavior.article.ArticleTapActionPreference
import com.skyd.anivu.model.preference.behavior.article.DeduplicateTitleInDescPreference
import com.skyd.anivu.ui.local.LocalArticleSwipeLeftAction
import com.skyd.anivu.ui.local.LocalArticleTapAction
import com.skyd.anivu.ui.local.LocalDarkMode
import com.skyd.anivu.ui.local.LocalDeduplicateTitleInDesc
import com.skyd.anivu.ui.local.LocalIgnoreUpdateVersion
import com.skyd.anivu.ui.local.LocalTheme
import kotlinx.coroutines.Dispatchers
Expand All @@ -22,6 +28,10 @@ data class Settings(
val darkMode: Int = DarkModePreference.default,
// Update
val ignoreUpdateVersion: Long = IgnoreUpdateVersionPreference.default,
// Behavior
val deduplicateTitleInDesc: Boolean = DeduplicateTitleInDescPreference.default,
val articleTapAction: String = ArticleTapActionPreference.default,
val articleSwipeLeftAction: String = ArticleSwipeLeftActionPreference.default,
)

@Composable
Expand All @@ -38,6 +48,10 @@ fun SettingsProvider(
LocalDarkMode provides settings.darkMode,
// Update
LocalIgnoreUpdateVersion provides settings.ignoreUpdateVersion,
// Behavior
LocalDeduplicateTitleInDesc provides settings.deduplicateTitleInDesc,
LocalArticleTapAction provides settings.articleTapAction,
LocalArticleSwipeLeftAction provides settings.articleSwipeLeftAction,
) {
content()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.skyd.anivu.model.preference.behavior.article

import android.content.Context
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import com.skyd.anivu.R
import com.skyd.anivu.base.BasePreference
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.getOrDefault
import com.skyd.anivu.ext.put
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object ArticleSwipeLeftActionPreference : BasePreference<String> {
private const val ARTICLE_SWIPE_LEFT_ACTION = "articleSwipeLeftAction"

const val READ = "Read"
const val SHOW_ENCLOSURES = "ShowEnclosures"

val values = arrayOf(READ, SHOW_ENCLOSURES)

override val default = SHOW_ENCLOSURES

val key = stringPreferencesKey(ARTICLE_SWIPE_LEFT_ACTION)

fun put(context: Context, scope: CoroutineScope, value: String) {
scope.launch(Dispatchers.IO) {
context.dataStore.put(key, value)
}
}

override fun fromPreferences(preferences: Preferences): String = preferences[key] ?: default

fun toDisplayName(
context: Context,
value: String = context.dataStore.getOrDefault(this),
): String = when (value) {
READ -> context.getString(R.string.article_action_read)
SHOW_ENCLOSURES -> context.getString(R.string.article_action_show_enclosures)
else -> context.getString(R.string.unknown)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.skyd.anivu.model.preference.behavior.article

import android.content.Context
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import com.skyd.anivu.R
import com.skyd.anivu.base.BasePreference
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.getOrDefault
import com.skyd.anivu.ext.put
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object ArticleTapActionPreference : BasePreference<String> {
private const val ARTICLE_TAP_ACTION = "articleTapAction"

const val READ = "Read"
const val SHOW_ENCLOSURES = "ShowEnclosures"

val values = arrayOf(READ, SHOW_ENCLOSURES)

override val default = READ

val key = stringPreferencesKey(ARTICLE_TAP_ACTION)

fun put(context: Context, scope: CoroutineScope, value: String) {
scope.launch(Dispatchers.IO) {
context.dataStore.put(key, value)
}
}

override fun fromPreferences(preferences: Preferences): String = preferences[key] ?: default

fun toDisplayName(
context: Context,
value: String = context.dataStore.getOrDefault(this),
): String = when (value) {
READ -> context.getString(R.string.article_action_read)
SHOW_ENCLOSURES -> context.getString(R.string.article_action_show_enclosures)
else -> context.getString(R.string.unknown)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.skyd.anivu.model.preference.behavior.article

import android.content.Context
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import com.skyd.anivu.base.BasePreference
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.put
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object DeduplicateTitleInDescPreference : BasePreference<Boolean> {
private const val DEDUPLICATE_TITLE_IN_DESC = "deduplicateTitleInDesc"
override val default = true

val key = booleanPreferencesKey(DEDUPLICATE_TITLE_IN_DESC)

fun put(context: Context, scope: CoroutineScope, value: Boolean) {
scope.launch(Dispatchers.IO) {
context.dataStore.put(key, value)
}
}

override fun fromPreferences(preferences: Preferences): Boolean = preferences[key] ?: default
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.skyd.anivu.base.BaseRepository
import com.skyd.anivu.model.bean.ArticleBean
import com.skyd.anivu.model.bean.ArticleWithEnclosureBean
import com.skyd.anivu.model.db.dao.ArticleDao
import com.skyd.anivu.model.db.dao.FeedDao
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class SearchRepository @Inject constructor(
k = query,
limit = { key to params.loadSize },
)
resultList.addAll(feedDao.getFeedList(feedSql))
resultList.addAll(feedDao.getFeedListPagingSource(feedSql))
val articleSql by lazy {
genSql(
tableName = ARTICLE_TABLE_NAME,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ class DeleteArticleWorker(context: Context, parameters: WorkerParameters) :
}

companion object {
const val uniqueWorkName = "deleteArticleWorker"
const val UNIQUE_WORK_NAME = "deleteArticleWorker"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fun listenerDeleteArticleFrequency(context: Context) {
)
}.distinctUntilChanged().combine(
WorkManager.getInstance(context)
.getWorkInfosForUniqueWorkFlow(DeleteArticleWorker.uniqueWorkName)
.getWorkInfosForUniqueWorkFlow(DeleteArticleWorker.UNIQUE_WORK_NAME)
.distinctUntilChanged(),
) { deleteArticleConfiguration, workInfos ->
val workInfo = workInfos.firstOrNull()
Expand Down Expand Up @@ -103,7 +103,7 @@ fun startRssSyncWorker(
deleteArticleFrequency: Long,
) {
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
DeleteArticleWorker.uniqueWorkName,
DeleteArticleWorker.UNIQUE_WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
getDeleteArticleWorkRequest(
deleteArticleFrequency = deleteArticleFrequency,
Expand All @@ -112,7 +112,7 @@ fun startRssSyncWorker(
}

fun stopDeleteArticleWorker(context: Context) {
WorkManager.getInstance(context).cancelUniqueWork(DeleteArticleWorker.uniqueWorkName)
WorkManager.getInstance(context).cancelUniqueWork(DeleteArticleWorker.UNIQUE_WORK_NAME)
}

fun getDeleteArticleWorkRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ class RssSyncWorker(context: Context, parameters: WorkerParameters) :
}

companion object {
const val uniqueWorkName = "rssSyncWorker"
const val UNIQUE_WORK_NAME = "rssSyncWorker"
}
}
Loading

0 comments on commit bbb85e8

Please sign in to comment.