Skip to content

Commit

Permalink
[feature|build|doc] Supports preserving unread/favored articles when …
Browse files Browse the repository at this point in the history
…auto-deleting; update dependencies; update README
  • Loading branch information
SkyD666 committed Oct 15, 2024
1 parent bcecc7f commit a49c94b
Show file tree
Hide file tree
Showing 17 changed files with 166 additions and 44 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<img src="doc/image/AniVu.svg" style="height: 210px"/>
</div>
<h1>🥰 AniVu</h1>
<p>(<b>A</b> <b>N</b>ew <b>I</b>ntegration <b>View</b>)</p>
<p>
<a href="https://github.com/SkyD666/AniVu/actions" style="text-decoration:none">
<img src="https://img.shields.io/github/actions/workflow/status/SkyD666/AniVu/pre_release.yml?branch=master&style=for-the-badge" alt="GitHub Workflow Status" />
Expand Down Expand Up @@ -30,16 +31,17 @@
</a>
</p>
<p>
<b>AniVu</b>, an <b>all-in-one tool</b> for <b>RSS subscription and updates</b>, <b>bit torrent downloads</b>, and <b>video playback</b>.
An <b>all-in-one tool</b> for <b>RSS 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>Jetpack Compose</b>.
</p>
<p>
<b><a href="doc/readme/README-zh-rCN.md">中文</a></b>&nbsp&nbsp&nbsp|&nbsp&nbsp&nbsp<b><a href="doc/readme/README-zh-rTW.md">正體中文</a></b>&nbsp&nbsp&nbsp|&nbsp&nbsp&nbsp<b><a href="https://crowdin.com/project/anivu">Help us translate</a></b>
<b><a href="doc/readme/README-zh-rCN.md">简体中文</a></b>&nbsp&nbsp&nbsp|&nbsp&nbsp&nbsp<b><a href="doc/readme/README-zh-rTW.md">正體中文</a></b>&nbsp&nbsp&nbsp|&nbsp&nbsp&nbsp<b><a href="https://crowdin.com/project/anivu">Help us translate</a></b>
</p>
</div>


<a href="https://f-droid.org/packages/com.skyd.anivu"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" alt="Get it on F-Droid" height="80"></a>

## 💡 Features
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ android {
minSdk = 24
targetSdk = 35
versionCode = 24
versionName = "2.1-beta06"
versionName = "2.1-beta07"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
23 changes: 3 additions & 20 deletions app/src/main/java/com/skyd/anivu/ext/NavExt.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package com.skyd.anivu.ext

import android.os.Bundle
import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import androidx.navigation.NavDeepLinkRequest
import androidx.navigation.NavDestination
import androidx.navigation.NavOptions
import androidx.navigation.Navigator

Expand All @@ -16,23 +13,9 @@ fun NavController.navigate(
navOptions: NavOptions? = null,
navigatorExtras: Navigator.Extras? = null
) {
val routeLink = NavDeepLinkRequest
.Builder
.fromUri(NavDestination.createRoute(route).toUri())
.build()

val deepLinkMatch = graph.matchDeepLink(routeLink)
if (deepLinkMatch != null) {
val destination = deepLinkMatch.destination
val id = destination.id
navigate(
id,
args.apply { putAll(deepLinkMatch.matchingArgs ?: Bundle()) },
navOptions,
navigatorExtras
)
} else {
navigate(route, navOptions, navigatorExtras)
val nodeId = graph.findNode(route = route)?.id
if (nodeId != null) {
navigate(nodeId, args, navOptions, navigatorExtras)
}
}

Expand Down
4 changes: 4 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 @@ -33,6 +33,8 @@ import com.skyd.anivu.model.preference.behavior.feed.HideEmptyDefaultPreference
import com.skyd.anivu.model.preference.data.OpmlExportDirPreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleBeforePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleFrequencyPreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepFavoritePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepUnreadPreference
import com.skyd.anivu.model.preference.data.autodelete.UseAutoDeletePreference
import com.skyd.anivu.model.preference.data.medialib.MediaLibLocationPreference
import com.skyd.anivu.model.preference.player.HardwareDecodePreference
Expand Down Expand Up @@ -118,6 +120,8 @@ fun Preferences.toSettings(): Settings {
useAutoDelete = UseAutoDeletePreference.fromPreferences(this),
autoDeleteArticleFrequency = AutoDeleteArticleFrequencyPreference.fromPreferences(this),
autoDeleteArticleBefore = AutoDeleteArticleBeforePreference.fromPreferences(this),
autoDeleteArticleKeepUnread = AutoDeleteArticleKeepUnreadPreference.fromPreferences(this),
autoDeleteArticleKeepFavorite = AutoDeleteArticleKeepFavoritePreference.fromPreferences(this),
opmlExportDir = OpmlExportDirPreference.fromPreferences(this),
mediaLibLocation = MediaLibLocationPreference.fromPreferences(this),

Expand Down
12 changes: 9 additions & 3 deletions app/src/main/java/com/skyd/anivu/model/db/dao/ArticleDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,17 @@ interface ArticleDao {
@Query(
"""
DELETE FROM $ARTICLE_TABLE_NAME
WHERE ${ArticleBean.UPDATE_AT_COLUMN} IS NULL
OR ${ArticleBean.UPDATE_AT_COLUMN} <= :timestamp
WHERE (${ArticleBean.UPDATE_AT_COLUMN} IS NULL
OR ${ArticleBean.UPDATE_AT_COLUMN} <= :timestamp)
AND (:keepUnread = 0 OR ${ArticleBean.IS_READ_COLUMN} = 1)
AND (:keepFavorite = 0 OR ${ArticleBean.IS_FAVORITE_COLUMN} = 0)
"""
)
suspend fun deleteArticleBefore(timestamp: Long): Int
suspend fun deleteArticleBefore(
timestamp: Long,
keepUnread: Boolean = true,
keepFavorite: Boolean = true,
): Int

@Transaction
@RawQuery(observedEntities = [FeedBean::class, ArticleBean::class, EnclosureBean::class])
Expand Down
12 changes: 10 additions & 2 deletions app/src/main/java/com/skyd/anivu/model/preference/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import com.skyd.anivu.model.preference.appearance.feed.FeedDefaultGroupExpandPre
import com.skyd.anivu.model.preference.appearance.feed.FeedListTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.feed.FeedTopBarTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.media.MediaShowThumbnailPreference
import com.skyd.anivu.model.preference.appearance.read.ReadTextSizePreference
import com.skyd.anivu.model.preference.appearance.read.ReadContentTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.read.ReadTextSizePreference
import com.skyd.anivu.model.preference.appearance.read.ReadTopBarTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.search.SearchItemMinWidthPreference
import com.skyd.anivu.model.preference.appearance.search.SearchListTonalElevationPreference
Expand All @@ -38,6 +38,8 @@ import com.skyd.anivu.model.preference.behavior.feed.HideEmptyDefaultPreference
import com.skyd.anivu.model.preference.data.OpmlExportDirPreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleBeforePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleFrequencyPreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepFavoritePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepUnreadPreference
import com.skyd.anivu.model.preference.data.autodelete.UseAutoDeletePreference
import com.skyd.anivu.model.preference.data.medialib.MediaLibLocationPreference
import com.skyd.anivu.model.preference.player.HardwareDecodePreference
Expand Down Expand Up @@ -71,6 +73,8 @@ import com.skyd.anivu.ui.local.LocalArticleTapAction
import com.skyd.anivu.ui.local.LocalArticleTopBarTonalElevation
import com.skyd.anivu.ui.local.LocalAutoDeleteArticleBefore
import com.skyd.anivu.ui.local.LocalAutoDeleteArticleFrequency
import com.skyd.anivu.ui.local.LocalAutoDeleteArticleKeepFavorite
import com.skyd.anivu.ui.local.LocalAutoDeleteArticleKeepUnread
import com.skyd.anivu.ui.local.LocalDarkMode
import com.skyd.anivu.ui.local.LocalDateStyle
import com.skyd.anivu.ui.local.LocalDeduplicateTitleInDesc
Expand Down Expand Up @@ -100,8 +104,8 @@ import com.skyd.anivu.ui.local.LocalProxyPassword
import com.skyd.anivu.ui.local.LocalProxyPort
import com.skyd.anivu.ui.local.LocalProxyType
import com.skyd.anivu.ui.local.LocalProxyUsername
import com.skyd.anivu.ui.local.LocalReadTextSize
import com.skyd.anivu.ui.local.LocalReadContentTonalElevation
import com.skyd.anivu.ui.local.LocalReadTextSize
import com.skyd.anivu.ui.local.LocalReadTopBarTonalElevation
import com.skyd.anivu.ui.local.LocalRssSyncBatteryNotLowConstraint
import com.skyd.anivu.ui.local.LocalRssSyncChargingConstraint
Expand Down Expand Up @@ -172,6 +176,8 @@ data class Settings(
val useAutoDelete: Boolean = UseAutoDeletePreference.default,
val autoDeleteArticleFrequency: Long = AutoDeleteArticleFrequencyPreference.default,
val autoDeleteArticleBefore: Long = AutoDeleteArticleBeforePreference.default,
val autoDeleteArticleKeepUnread: Boolean = AutoDeleteArticleKeepUnreadPreference.default,
val autoDeleteArticleKeepFavorite: Boolean = AutoDeleteArticleKeepFavoritePreference.default,
val opmlExportDir: String = OpmlExportDirPreference.default,
val mediaLibLocation: String = MediaLibLocationPreference.default,
// Transmission
Expand Down Expand Up @@ -245,6 +251,8 @@ fun SettingsProvider(
LocalUseAutoDelete provides settings.useAutoDelete,
LocalAutoDeleteArticleFrequency provides settings.autoDeleteArticleFrequency,
LocalAutoDeleteArticleBefore provides settings.autoDeleteArticleBefore,
LocalAutoDeleteArticleKeepUnread provides settings.autoDeleteArticleKeepUnread,
LocalAutoDeleteArticleKeepFavorite provides settings.autoDeleteArticleKeepFavorite,
LocalOpmlExportDir provides settings.opmlExportDir,
LocalMediaLibLocation provides settings.mediaLibLocation,
// Transmission
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.skyd.anivu.model.preference.data.autodelete

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 AutoDeleteArticleKeepFavoritePreference : BasePreference<Boolean> {
private const val AUTO_DELETE_ARTICLE_KEEP_FAVORITE = "autoDeleteArticleKeepFavorite"

override val default = true

val key = booleanPreferencesKey(AUTO_DELETE_ARTICLE_KEEP_FAVORITE)

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
@@ -0,0 +1,27 @@
package com.skyd.anivu.model.preference.data.autodelete

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 AutoDeleteArticleKeepUnreadPreference : BasePreference<Boolean> {
private const val AUTO_DELETE_ARTICLE_KEEP_UNREAD = "autoDeleteArticleKeepUnread"

override val default = true

val key = booleanPreferencesKey(AUTO_DELETE_ARTICLE_KEEP_UNREAD)

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 @@ -7,6 +7,8 @@ import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.getOrDefault
import com.skyd.anivu.model.db.dao.ArticleDao
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleBeforePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepFavoritePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepUnreadPreference
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
Expand All @@ -28,8 +30,15 @@ class DeleteArticleWorker(context: Context, parameters: WorkerParameters) :
override suspend fun doWork(): Result {
runCatching {
hiltEntryPoint.articleDao.deleteArticleBefore(
System.currentTimeMillis() -
applicationContext.dataStore.getOrDefault(AutoDeleteArticleBeforePreference)
timestamp = System.currentTimeMillis() - applicationContext.dataStore.getOrDefault(
AutoDeleteArticleBeforePreference
),
keepUnread = applicationContext.dataStore.getOrDefault(
AutoDeleteArticleKeepUnreadPreference
),
keepFavorite = applicationContext.dataStore.getOrDefault(
AutoDeleteArticleKeepFavoritePreference
),
)
}.onFailure { return Result.failure() }
return Result.success()
Expand Down
14 changes: 11 additions & 3 deletions app/src/main/java/com/skyd/anivu/ui/local/LocalValue.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import com.skyd.anivu.model.preference.appearance.feed.FeedDefaultGroupExpandPre
import com.skyd.anivu.model.preference.appearance.feed.FeedListTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.feed.FeedTopBarTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.media.MediaShowThumbnailPreference
import com.skyd.anivu.model.preference.appearance.read.ReadTextSizePreference
import com.skyd.anivu.model.preference.appearance.read.ReadContentTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.read.ReadTextSizePreference
import com.skyd.anivu.model.preference.appearance.read.ReadTopBarTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.search.SearchItemMinWidthPreference
import com.skyd.anivu.model.preference.appearance.search.SearchListTonalElevationPreference
Expand All @@ -34,6 +34,8 @@ import com.skyd.anivu.model.preference.behavior.feed.HideEmptyDefaultPreference
import com.skyd.anivu.model.preference.data.OpmlExportDirPreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleBeforePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleFrequencyPreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepFavoritePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepUnreadPreference
import com.skyd.anivu.model.preference.data.autodelete.UseAutoDeletePreference
import com.skyd.anivu.model.preference.data.medialib.MediaLibLocationPreference
import com.skyd.anivu.model.preference.player.HardwareDecodePreference
Expand Down Expand Up @@ -94,8 +96,10 @@ val LocalArticleItemMinWidth = compositionLocalOf { ArticleItemMinWidthPreferenc
val LocalSearchItemMinWidth = compositionLocalOf { SearchItemMinWidthPreference.default }
val LocalMediaShowThumbnail = compositionLocalOf { MediaShowThumbnailPreference.default }
val LocalReadTextSize = compositionLocalOf { ReadTextSizePreference.default }
val LocalReadContentTonalElevation = compositionLocalOf { ReadContentTonalElevationPreference.default }
val LocalReadTopBarTonalElevation = compositionLocalOf { ReadTopBarTonalElevationPreference.default }
val LocalReadContentTonalElevation =
compositionLocalOf { ReadContentTonalElevationPreference.default }
val LocalReadTopBarTonalElevation =
compositionLocalOf { ReadTopBarTonalElevationPreference.default }

// Update
val LocalIgnoreUpdateVersion = compositionLocalOf { IgnoreUpdateVersionPreference.default }
Expand Down Expand Up @@ -135,6 +139,10 @@ val LocalUseAutoDelete = compositionLocalOf { UseAutoDeletePreference.default }
val LocalAutoDeleteArticleFrequency =
compositionLocalOf { AutoDeleteArticleFrequencyPreference.default }
val LocalAutoDeleteArticleBefore = compositionLocalOf { AutoDeleteArticleBeforePreference.default }
val LocalAutoDeleteArticleKeepUnread =
compositionLocalOf { AutoDeleteArticleKeepUnreadPreference.default }
val LocalAutoDeleteArticleKeepFavorite =
compositionLocalOf { AutoDeleteArticleKeepFavoritePreference.default }
val LocalOpmlExportDir = compositionLocalOf { OpmlExportDirPreference.default }
val LocalMediaLibLocation = compositionLocalOf { MediaLibLocationPreference.default }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AutoDelete
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.MarkEmailUnread
import androidx.compose.material.icons.outlined.Timer
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
Expand Down Expand Up @@ -31,6 +33,8 @@ import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.getOrDefault
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleBeforePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleFrequencyPreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepFavoritePreference
import com.skyd.anivu.model.preference.data.autodelete.AutoDeleteArticleKeepUnreadPreference
import com.skyd.anivu.model.preference.data.autodelete.UseAutoDeletePreference
import com.skyd.anivu.ui.component.AniVuTopBar
import com.skyd.anivu.ui.component.AniVuTopBarStyle
Expand All @@ -40,6 +44,8 @@ import com.skyd.anivu.ui.component.SwitchSettingsItem
import com.skyd.anivu.ui.component.dialog.SliderDialog
import com.skyd.anivu.ui.local.LocalAutoDeleteArticleBefore
import com.skyd.anivu.ui.local.LocalAutoDeleteArticleFrequency
import com.skyd.anivu.ui.local.LocalAutoDeleteArticleKeepFavorite
import com.skyd.anivu.ui.local.LocalAutoDeleteArticleKeepUnread
import com.skyd.anivu.ui.local.LocalUseAutoDelete
import kotlin.time.Duration
import kotlin.time.Duration.Companion.days
Expand Down Expand Up @@ -113,6 +119,32 @@ fun AutoDeleteScreen() {
enabled = useAutoDelete,
)
}
item {
SwitchSettingsItem(
imageVector = Icons.Outlined.MarkEmailUnread,
text = stringResource(id = R.string.auto_delete_article_screen_keep_unread),
description = stringResource(id = R.string.auto_delete_article_screen_keep_unread_description),
checked = LocalAutoDeleteArticleKeepUnread.current,
onCheckedChange = {
AutoDeleteArticleKeepUnreadPreference.put(
context = context, scope = scope, value = it,
)
}
)
}
item {
SwitchSettingsItem(
imageVector = Icons.Outlined.FavoriteBorder,
text = stringResource(id = R.string.auto_delete_article_screen_keep_favorite),
description = stringResource(id = R.string.auto_delete_article_screen_keep_favorite_description),
checked = LocalAutoDeleteArticleKeepFavorite.current,
onCheckedChange = {
AutoDeleteArticleKeepFavoritePreference.put(
context = context, scope = scope, value = it,
)
}
)
}
}

if (openAutoDeleteFrequencyDialog) {
Expand Down
Loading

0 comments on commit a49c94b

Please sign in to comment.