Add more details when first adding a tracker

Such as last read chapter
Completed status
Start Date (if applicable)
End Date (also if applicable)
This commit is contained in:
Jays2Kings 2021-03-22 02:23:35 -04:00
parent 5cf9d09a02
commit d0c802b6ea
9 changed files with 76 additions and 7 deletions

View File

@ -19,13 +19,15 @@ import java.util.Date
interface ChapterQueries : DbProvider { interface ChapterQueries : DbProvider {
fun getChapters(manga: Manga) = db.get() fun getChapters(manga: Manga) = getChapters(manga.id)
fun getChapters(mangaId: Long?) = db.get()
.listOfObjects(Chapter::class.java) .listOfObjects(Chapter::class.java)
.withQuery( .withQuery(
Query.builder() Query.builder()
.table(ChapterTable.TABLE) .table(ChapterTable.TABLE)
.where("${ChapterTable.COL_MANGA_ID} = ?") .where("${ChapterTable.COL_MANGA_ID} = ?")
.whereArgs(manga.id) .whereArgs(mangaId)
.build() .build()
) )
.prepare() .prepare()

View File

@ -3,10 +3,15 @@ package eu.kanade.tachiyomi.data.track
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.anilist.Anilist
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.manga.track.SetTrackReadingDatesDialog
import eu.kanade.tachiyomi.util.system.executeOnIO
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -14,6 +19,7 @@ abstract class TrackService(val id: Int) {
val preferences: PreferencesHelper by injectLazy() val preferences: PreferencesHelper by injectLazy()
val networkService: NetworkHelper by injectLazy() val networkService: NetworkHelper by injectLazy()
val db: DatabaseHelper by injectLazy()
open fun canRemoveFromService() = false open fun canRemoveFromService() = false
open val client: OkHttpClient open val client: OkHttpClient
get() = networkService.client get() = networkService.client
@ -34,6 +40,8 @@ abstract class TrackService(val id: Int) {
abstract fun isCompletedStatus(index: Int): Boolean abstract fun isCompletedStatus(index: Int): Boolean
abstract fun completedStatus(): Int
abstract fun getStatus(status: Int): String abstract fun getStatus(status: Int): String
abstract fun getGlobalStatus(status: Int): String abstract fun getGlobalStatus(status: Int): String
@ -77,3 +85,39 @@ abstract class TrackService(val id: Int) {
preferences.setTrackCredentials(this, username, password) preferences.setTrackCredentials(this, username, password)
} }
} }
suspend fun TrackService.updateNewTrackInfo(track: Track) {
val allRead = db.getManga(track.manga_id).executeOnIO()?.status == SManga.COMPLETED &&
db.getChapters(track.manga_id).executeOnIO().all { it.read }
if (supportsReadingDates) {
track.started_reading_date = getStartDate(track)
track.finished_reading_date = getCompletedDate(track, allRead)
}
track.last_chapter_read = getLastChapterRead(track)
if (allRead) {
track.status = completedStatus()
}
}
suspend fun TrackService.getStartDate(track: Track): Long {
if (db.getChapters(track.manga_id).executeOnIO().any { it.read }) {
val chapters = db.getHistoryByMangaId(track.manga_id).executeOnIO()
val date = chapters.minOfOrNull { it.last_read } ?: return 0L
return if (date <= 0L) 0L else date
}
return 0L
}
suspend fun TrackService.getCompletedDate(track: Track, allRead: Boolean): Long {
if (allRead) {
val chapters = db.getHistoryByMangaId(track.manga_id).executeOnIO()
val date = chapters.maxOfOrNull { it.last_read } ?: return 0L
return if (date <= 0L) 0L else date
}
return 0L
}
suspend fun TrackService.getLastChapterRead(track: Track): Int {
val chapters = db.getChapters(track.manga_id).executeOnIO()
return chapters.filter { it.read }.minByOrNull { it.source_order }?.chapter_number?.toInt() ?: 0
}

View File

@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.updateNewTrackInfo
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -44,6 +45,8 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED
override fun completedStatus() = COMPLETED
override fun getStatus(status: Int): String = with(context) { override fun getStatus(status: Int): String = with(context) {
when (status) { when (status) {
READING -> getString(R.string.reading) READING -> getString(R.string.reading)
@ -127,6 +130,7 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
override suspend fun add(track: Track): Track { override suspend fun add(track: Track): Track {
track.score = DEFAULT_SCORE.toFloat() track.score = DEFAULT_SCORE.toFloat()
track.status = DEFAULT_STATUS track.status = DEFAULT_STATUS
updateNewTrackInfo(track)
return api.addLibManga(track) return api.addLibManga(track)
} }

View File

@ -38,7 +38,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
val variables = jsonObject( val variables = jsonObject(
"mangaId" to track.media_id, "mangaId" to track.media_id,
"progress" to track.last_chapter_read, "progress" to track.last_chapter_read,
"status" to track.toAnilistStatus() "status" to track.toAnilistStatus(),
"startedAt" to createDate(track.started_reading_date),
"completedAt" to createDate(track.finished_reading_date)
) )
val payload = jsonObject( val payload = jsonObject(
"query" to addToLibraryQuery(), "query" to addToLibraryQuery(),
@ -264,8 +266,8 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
fun addToLibraryQuery() = fun addToLibraryQuery() =
""" """
|mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus) { |mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus, ${'$'}startedAt: FuzzyDateInput, ${'$'}completedAt: FuzzyDateInput) {
|SaveMediaListEntry (mediaId: ${'$'}mangaId, progress: ${'$'}progress, status: ${'$'}status) { |SaveMediaListEntry (mediaId: ${'$'}mangaId, progress: ${'$'}progress, status: ${'$'}status, startedAt: ${'$'}startedAt, completedAt: ${'$'}completedAt) {
| id | id
| status | status
|} |}

View File

@ -8,6 +8,8 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
import eu.kanade.tachiyomi.data.track.updateNewTrackInfo
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -40,6 +42,7 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
override suspend fun add(track: Track): Track { override suspend fun add(track: Track): Track {
track.score = DEFAULT_SCORE.toFloat() track.score = DEFAULT_SCORE.toFloat()
track.status = DEFAULT_STATUS track.status = DEFAULT_STATUS
updateNewTrackInfo(track)
api.addLibManga(track) api.addLibManga(track)
return update(track) return update(track)
} }
@ -83,6 +86,8 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED
override fun completedStatus(): Int = MyAnimeList.COMPLETED
override fun getStatus(status: Int): String = with(context) { override fun getStatus(status: Int): String = with(context) {
when (status) { when (status) {
READING -> getString(R.string.reading) READING -> getString(R.string.reading)

View File

@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat import java.text.DecimalFormat
@ -48,6 +49,8 @@ class Kitsu(private val context: Context, id: Int) : TrackService(id) {
override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED
override fun completedStatus(): Int = MyAnimeList.COMPLETED
override fun getStatus(status: Int): String = with(context) { override fun getStatus(status: Int): String = with(context) {
when (status) { when (status) {
READING -> getString(R.string.currently_reading) READING -> getString(R.string.currently_reading)

View File

@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.data.track.updateNewTrackInfo
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -58,6 +59,8 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED
override fun completedStatus(): Int = COMPLETED
override fun getScoreList(): List<String> { override fun getScoreList(): List<String> {
return IntRange(0, 10).map(Int::toString) return IntRange(0, 10).map(Int::toString)
} }
@ -69,6 +72,7 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
override suspend fun add(track: Track): Track { override suspend fun add(track: Track): Track {
track.status = READING track.status = READING
track.score = 0F track.score = 0F
updateNewTrackInfo(track)
return api.updateItem(track) return api.updateItem(track)
} }

View File

@ -7,6 +7,8 @@ import com.google.gson.Gson
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
import eu.kanade.tachiyomi.data.track.updateNewTrackInfo
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -31,6 +33,8 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) {
override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED override fun isCompletedStatus(index: Int) = getStatusList()[index] == COMPLETED
override fun completedStatus(): Int = MyAnimeList.COMPLETED
override fun getStatus(status: Int): String = with(context) { override fun getStatus(status: Int): String = with(context) {
when (status) { when (status) {
READING -> getString(R.string.reading) READING -> getString(R.string.reading)
@ -73,6 +77,7 @@ class Shikimori(private val context: Context, id: Int) : TrackService(id) {
override suspend fun add(track: Track): Track { override suspend fun add(track: Track): Track {
track.score = DEFAULT_SCORE.toFloat() track.score = DEFAULT_SCORE.toFloat()
track.status = DEFAULT_STATUS track.status = DEFAULT_STATUS
updateNewTrackInfo(track)
return api.addLibManga(track, getUsername()) return api.addLibManga(track, getUsername())
} }
override suspend fun bind(track: Track): Track { override suspend fun bind(track: Track): Track {

View File

@ -899,8 +899,8 @@ class MangaDetailsPresenter(
fun getSuggestedDate(readingDate: SetTrackReadingDatesDialog.ReadingDate): Long? { fun getSuggestedDate(readingDate: SetTrackReadingDatesDialog.ReadingDate): Long? {
val chapters = db.getHistoryByMangaId(manga.id ?: 0L).executeAsBlocking() val chapters = db.getHistoryByMangaId(manga.id ?: 0L).executeAsBlocking()
val date = when (readingDate) { val date = when (readingDate) {
SetTrackReadingDatesDialog.ReadingDate.Start -> chapters.minByOrNull { it.last_read }?.last_read SetTrackReadingDatesDialog.ReadingDate.Start -> chapters.minOfOrNull { it.last_read }
SetTrackReadingDatesDialog.ReadingDate.Finish -> chapters.maxByOrNull { it.last_read }?.last_read SetTrackReadingDatesDialog.ReadingDate.Finish -> chapters.maxOfOrNull { it.last_read }
} ?: return null } ?: return null
return if (date <= 0L) null else date return if (date <= 0L) null else date
} }