Implement automatic removal of downloads on Suwayomi after reading, configurable via extension settings (#2673)

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
Constantin Piber
2025-12-20 13:54:17 +01:00
committed by GitHub
parent c96b6ae562
commit 1263df9d41
3 changed files with 42 additions and 14 deletions
+3
View File
@@ -11,6 +11,9 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
- `Other` - for technical stuff.
## [Unreleased]
### Added
- Automatically remove downloads on Suwayomi after reading, configurable via extension settings ([@cpiber](https://github.com/cpiber)) ([#2673](https://github.com/mihonapp/mihon/pull/2673))
### Improved
- Minimize memory usage by reducing in-memory cover cache size ([@Lolle2000la](https://github.com/Lolle2000la)) ([#2266](https://github.com/mihonapp/mihon/pull/2266))
@@ -23,6 +23,9 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
const val UNREAD = 1L
const val READING = 2L
const val COMPLETED = 3L
private const val TRACKER_DELETE_KEY = "Tracker Delete"
private const val TRACKER_DELETE_DEFAULT = false
}
override fun getStatusList(): List<Long> = listOf(UNREAD, READING, COMPLETED)
@@ -55,7 +58,7 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
}
}
return api.updateProgress(track)
return api.updateProgress(track, getPrefTrackerDelete())
}
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
@@ -102,4 +105,9 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
private fun String.getMangaId(): Long =
this.substringAfterLast('/').toLong()
private fun getPrefTrackerDelete(): Boolean {
val preferences = api.sourcePreferences()
return preferences.getBoolean(TRACKER_DELETE_KEY, TRACKER_DELETE_DEFAULT)
}
}
@@ -1,12 +1,15 @@
package eu.kanade.tachiyomi.data.track.suwayomi
import android.content.SharedPreferences
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.network.jsonMime
import eu.kanade.tachiyomi.network.parseAs
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.sourcePreferences
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.addAll
import kotlinx.serialization.json.buildJsonObject
@@ -29,10 +32,13 @@ class SuwayomiApi(private val trackId: Long) {
private val sourceManager: SourceManager by injectLazy()
private val source: HttpSource by lazy { (sourceManager.get(sourceId) as HttpSource) }
private val configurableSource: ConfigurableSource by lazy { (sourceManager.get(sourceId) as ConfigurableSource) }
private val client: OkHttpClient by lazy { source.client }
private val baseUrl: String by lazy { source.baseUrl.trimEnd('/') }
private val apiUrl: String by lazy { "$baseUrl/api/graphql" }
public fun sourcePreferences(): SharedPreferences = configurableSource.sourcePreferences()
suspend fun getTrackSearch(mangaId: Long): TrackSearch = withIOContext {
val query = """
|query GetManga(${'$'}mangaId: Int!) {
@@ -79,9 +85,11 @@ class SuwayomiApi(private val trackId: Long) {
}
}
suspend fun updateProgress(track: Track): Track {
suspend fun updateProgress(track: Track, deleteDownloadsOnServer: Boolean = false): Track {
val mangaId = track.remote_id
// TODO: Include a filter on the chapter number here
// Below, we only consider older chapters; since v2.1.1985 filtering works properly in the query
val chaptersQuery = """
|query GetMangaUnreadChapters(${'$'}mangaId: Int!) {
| chapters(condition: {mangaId: ${'$'}mangaId, isRead: false}) {
@@ -113,15 +121,26 @@ class SuwayomiApi(private val trackId: Long) {
.mapNotNull { n -> n.id.takeIf { n.chapterNumber <= track.last_chapter_read } }
}
val markQuery = """
|mutation MarkChaptersRead(${'$'}chapters: [Int!]!) {
| updateChapters(input: {ids: ${'$'}chapters, patch: {isRead: true}}) {
| chapters {
| id
| }
| }
|}
""".trimMargin()
val markQuery = if (deleteDownloadsOnServer) {
"""
|mutation MarkChaptersRead(${'$'}chapters: [Int!]!) {
| updateChapters(input: {ids: ${'$'}chapters, patch: {isRead: true}}) {
| __typename
| }
| deleteDownloadedChapters(input: {ids: ${'$'}chapters}) {
| __typename
| }
|}
""".trimMargin()
} else {
"""
|mutation MarkChaptersRead(${'$'}chapters: [Int!]!) {
| updateChapters(input: {ids: ${'$'}chapters, patch: {isRead: true}}) {
| __typename
| }
|}
""".trimMargin()
}
val markPayload = buildJsonObject {
put("query", markQuery)
putJsonObject("variables") {
@@ -143,9 +162,7 @@ class SuwayomiApi(private val trackId: Long) {
val trackQuery = """
|mutation TrackManga(${'$'}mangaId: Int!) {
| trackProgress(input: {mangaId: ${'$'}mangaId}) {
| trackRecords {
| lastChapterRead
| }
| __typename
| }
|}
""".trimMargin()