Some domain Track model migrations

This commit is contained in:
arkon 2023-12-24 18:30:24 -05:00
parent 5908bd1930
commit 6d74a86711
28 changed files with 129 additions and 127 deletions

View File

@ -16,7 +16,7 @@ fun Track.copyPersonalFrom(other: Track): Track {
fun Track.toDbTrack(): DbTrack = DbTrack.create(syncId).also {
it.id = id
it.manga_id = mangaId
it.media_id = remoteId
it.remote_id = remoteId
it.library_id = libraryId
it.title = title
it.last_chapter_read = lastChapterRead.toFloat()
@ -34,7 +34,7 @@ fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? {
id = trackId,
mangaId = manga_id,
syncId = sync_id.toLong(),
remoteId = media_id,
remoteId = remote_id,
libraryId = library_id,
title = title,
lastChapterRead = last_chapter_read.toDouble(),

View File

@ -47,7 +47,6 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import dev.icerock.moko.resources.StringResource
import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.presentation.components.DropdownMenu
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.presentation.track.components.TrackLogoIcon
@ -101,7 +100,7 @@ fun TrackInfoDialogHome(
}
},
onChaptersClick = { onChapterClick(item) },
score = item.tracker.displayScore(item.track.toDbTrack())
score = item.tracker.displayScore(item.track)
.takeIf { supportsScoring && item.track.score != 0.0 },
onScoreClick = { onScoreClick(item) }
.takeIf { supportsScoring },

View File

@ -63,7 +63,7 @@ internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composab
it.id = Random.nextLong()
it.manga_id = Random.nextLong()
it.sync_id = Random.nextInt()
it.media_id = Random.nextLong()
it.remote_id = Random.nextLong()
it.library_id = Random.nextLong()
it.title = lorem((1..10).random()).joinToString()
it.last_chapter_read = (0..100).random().toFloat()

View File

@ -10,7 +10,7 @@ interface Track : Serializable {
var sync_id: Int
var media_id: Long
var remote_id: Long
var library_id: Long?

View File

@ -8,7 +8,7 @@ class TrackImpl : Track {
override var sync_id: Int = 0
override var media_id: Long = 0
override var remote_id: Long = 0
override var library_id: Long? = null

View File

@ -1,11 +1,11 @@
package eu.kanade.tachiyomi.data.track
import eu.kanade.tachiyomi.data.database.models.Track
import tachiyomi.domain.track.model.Track
/**
* Tracker that support deleting am entry from a user's list.
*/
interface DeletableTracker {
suspend fun delete(track: Track): Track
suspend fun delete(track: Track)
}

View File

@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import okhttp3.OkHttpClient
import tachiyomi.domain.track.model.Track as DomainTrack
interface Tracker {
@ -39,11 +40,11 @@ interface Tracker {
fun getScoreList(): ImmutableList<String>
// TODO: Store all scores as 10 point in the future maybe?
fun get10PointScore(track: tachiyomi.domain.track.model.Track): Double
fun get10PointScore(track: DomainTrack): Double
fun indexToScore(index: Int): Float
fun displayScore(track: Track): String
fun displayScore(track: DomainTrack): String
suspend fun update(track: Track, didReadChapter: Boolean = false): Track

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.track.anilist
import android.graphics.Color
import dev.icerock.moko.resources.StringResource
import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.BaseTracker
@ -120,16 +121,16 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
}
}
override fun displayScore(track: Track): String {
override fun displayScore(track: DomainTrack): String {
val score = track.score
return when (scorePreference.get()) {
POINT_5 -> when (score) {
0f -> "0 ★"
0.0 -> "0 ★"
else -> "${((score + 10) / 20).toInt()}"
}
POINT_3 -> when {
score == 0f -> "0"
score == 0.0 -> "0"
score <= 35 -> "😦"
score <= 60 -> "😐"
else -> "😊"
@ -167,13 +168,13 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
return api.updateLibManga(track)
}
override suspend fun delete(track: Track): Track {
if (track.library_id == null || track.library_id!! == 0L) {
val libManga = api.findLibManga(track, getUsername().toInt()) ?: return track
track.library_id = libManga.library_id
override suspend fun delete(track: DomainTrack) {
if (track.libraryId == null || track.libraryId == 0L) {
val libManga = api.findLibManga(track.toDbTrack(), getUsername().toInt()) ?: return
return api.deleteLibManga(track.copy(id = libManga.library_id!!))
}
return api.deleteLibManga(track)
api.deleteLibManga(track)
}
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {

View File

@ -31,6 +31,7 @@ import java.time.LocalDate
import java.time.ZoneId
import java.time.ZonedDateTime
import kotlin.time.Duration.Companion.minutes
import tachiyomi.domain.track.model.Track as DomainTrack
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
@ -55,7 +56,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
val payload = buildJsonObject {
put("query", query)
putJsonObject("variables") {
put("mangaId", track.media_id)
put("mangaId", track.remote_id)
put("progress", track.last_chapter_read.toInt())
put("status", track.toAnilistStatus())
}
@ -113,8 +114,8 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
}
}
suspend fun deleteLibManga(track: Track): Track {
return withIOContext {
suspend fun deleteLibManga(track: DomainTrack) {
withIOContext {
val query = """
|mutation DeleteManga(${'$'}listId: Int) {
|DeleteMediaListEntry(id: ${'$'}listId) {
@ -126,12 +127,11 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
val payload = buildJsonObject {
put("query", query)
putJsonObject("variables") {
put("listId", track.library_id)
put("listId", track.libraryId)
}
}
authClient.newCall(POST(apiUrl, body = payload.toString().toRequestBody(jsonMime)))
.awaitSuccess()
track
}
}
suspend fun search(search: String): List<TrackSearch> {
@ -235,7 +235,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
put("query", query)
putJsonObject("variables") {
put("id", userid)
put("manga_id", track.media_id)
put("manga_id", track.remote_id)
}
}
with(json) {
@ -258,8 +258,8 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
}
}
suspend fun getLibManga(track: Track, userid: Int): Track {
return findLibManga(track, userid) ?: throw Exception("Could not find manga")
suspend fun getLibManga(track: Track, userId: Int): Track {
return findLibManga(track, userId) ?: throw Exception("Could not find manga")
}
fun createOAuth(token: String): OAuth {

View File

@ -9,9 +9,10 @@ import kotlinx.serialization.Serializable
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
import java.util.Locale
import tachiyomi.domain.track.model.Track as DomainTrack
data class ALManga(
val media_id: Long,
val remote_id: Long,
val title_user_pref: String,
val image_url_lge: String,
val description: String?,
@ -23,13 +24,13 @@ data class ALManga(
) {
fun toTrack() = TrackSearch.create(TrackerManager.ANILIST).apply {
media_id = this@ALManga.media_id
remote_id = this@ALManga.remote_id
title = title_user_pref
total_chapters = this@ALManga.total_chapters
cover_url = image_url_lge
summary = description?.htmlDecode() ?: ""
score = average_score.toFloat()
tracking_url = AnilistApi.mangaUrl(media_id)
tracking_url = AnilistApi.mangaUrl(remote_id)
publishing_status = this@ALManga.publishing_status
publishing_type = format
if (start_date_fuzzy != 0L) {
@ -54,7 +55,7 @@ data class ALUserManga(
) {
fun toTrack() = Track.create(TrackerManager.ANILIST).apply {
media_id = manga.media_id
remote_id = manga.remote_id
title = manga.title_user_pref
status = toTrackStatus()
score = score_raw.toFloat()
@ -98,28 +99,28 @@ fun Track.toAnilistStatus() = when (status) {
private val preferences: TrackPreferences by injectLazy()
fun Track.toAnilistScore(): String = when (preferences.anilistScoreType().get()) {
// 10 point
fun DomainTrack.toAnilistScore(): String = when (preferences.anilistScoreType().get()) {
// 10 point
"POINT_10" -> (score.toInt() / 10).toString()
// 100 point
// 100 point
"POINT_100" -> score.toInt().toString()
// 5 stars
// 5 stars
"POINT_5" -> when {
score == 0f -> "0"
score == 0.0 -> "0"
score < 30 -> "1"
score < 50 -> "2"
score < 70 -> "3"
score < 90 -> "4"
else -> "5"
}
// Smiley
// Smiley
"POINT_3" -> when {
score == 0f -> "0"
score == 0.0 -> "0"
score <= 35 -> ":("
score <= 60 -> ":|"
else -> ":)"
}
// 10 point decimal
// 10 point decimal
"POINT_10_DECIMAL" -> (score / 10).toString()
else -> throw NotImplementedError("Unknown score type")
}

View File

@ -12,6 +12,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import tachiyomi.i18n.MR
import uy.kohesive.injekt.injectLazy
import tachiyomi.domain.track.model.Track as DomainTrack
class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
@ -23,7 +24,7 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
override fun getScoreList(): ImmutableList<String> = SCORE_LIST
override fun displayScore(track: Track): String {
override fun displayScore(track: DomainTrack): String {
return track.score.toInt().toString()
}

View File

@ -42,7 +42,7 @@ class BangumiApi(
.add("rating", track.score.toInt().toString())
.add("status", track.toBangumiStatus())
.build()
authClient.newCall(POST("$apiUrl/collection/${track.media_id}/update", body = body))
authClient.newCall(POST("$apiUrl/collection/${track.remote_id}/update", body = body))
.awaitSuccess()
track
}
@ -55,7 +55,7 @@ class BangumiApi(
.add("rating", track.score.toInt().toString())
.add("status", track.toBangumiStatus())
.build()
authClient.newCall(POST("$apiUrl/collection/${track.media_id}/update", body = sbody))
authClient.newCall(POST("$apiUrl/collection/${track.remote_id}/update", body = sbody))
.awaitSuccess()
// chapter update
@ -64,7 +64,7 @@ class BangumiApi(
.build()
authClient.newCall(
POST(
"$apiUrl/subject/${track.media_id}/update/watched_eps",
"$apiUrl/subject/${track.remote_id}/update/watched_eps",
body = body,
),
).awaitSuccess()
@ -111,7 +111,7 @@ class BangumiApi(
}
val rating = obj["rating"]?.jsonObject?.get("score")?.jsonPrimitive?.floatOrNull ?: -1f
return TrackSearch.create(trackId).apply {
media_id = obj["id"]!!.jsonPrimitive.long
remote_id = obj["id"]!!.jsonPrimitive.long
title = obj["name_cn"]!!.jsonPrimitive.content
cover_url = coverUrl
summary = obj["name"]!!.jsonPrimitive.content
@ -124,7 +124,7 @@ class BangumiApi(
suspend fun findLibManga(track: Track): Track? {
return withIOContext {
with(json) {
authClient.newCall(GET("$apiUrl/subject/${track.media_id}"))
authClient.newCall(GET("$apiUrl/subject/${track.remote_id}"))
.awaitSuccess()
.parseAs<JsonObject>()
.let { jsonToSearch(it) }
@ -134,7 +134,7 @@ class BangumiApi(
suspend fun statusLibManga(track: Track): Track? {
return withIOContext {
val urlUserRead = "$apiUrl/collection/${track.media_id}"
val urlUserRead = "$apiUrl/collection/${track.remote_id}"
val requestUserRead = Request.Builder()
.url(urlUserRead)
.cacheControl(CacheControl.FORCE_NETWORK)

View File

@ -55,7 +55,7 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker {
override fun getScoreList(): ImmutableList<String> = persistentListOf()
override fun displayScore(track: Track): String = ""
override fun displayScore(track: DomainTrack): String = ""
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {

View File

@ -14,6 +14,7 @@ import kotlinx.serialization.json.Json
import tachiyomi.i18n.MR
import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat
import tachiyomi.domain.track.model.Track as DomainTrack
class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
@ -65,7 +66,7 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
return if (index > 0) (index + 1) / 2f else 0f
}
override fun displayScore(track: Track): String {
override fun displayScore(track: DomainTrack): String {
val df = DecimalFormat("0.#")
return df.format(track.score)
}
@ -92,15 +93,15 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
return api.updateLibManga(track)
}
override suspend fun delete(track: Track): Track {
return api.removeLibManga(track)
override suspend fun delete(track: DomainTrack) {
api.removeLibManga(track)
}
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
val remoteTrack = api.findLibManga(track, getUserId())
return if (remoteTrack != null) {
track.copyPersonalFrom(remoteTrack)
track.media_id = remoteTrack.media_id
track.remote_id = remoteTrack.remote_id
if (track.status != COMPLETED) {
track.status = if (hasReadChapters) READING else track.status

View File

@ -29,6 +29,7 @@ import tachiyomi.core.util.lang.withIOContext
import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import tachiyomi.domain.track.model.Track as DomainTrack
class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) {
@ -54,7 +55,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
}
putJsonObject("media") {
putJsonObject("data") {
put("id", track.media_id)
put("id", track.remote_id)
put("type", "manga")
}
}
@ -77,7 +78,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
.awaitSuccess()
.parseAs<JsonObject>()
.let {
track.media_id = it["data"]!!.jsonObject["id"]!!.jsonPrimitive.long
track.remote_id = it["data"]!!.jsonObject["id"]!!.jsonPrimitive.long
track
}
}
@ -89,7 +90,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
val data = buildJsonObject {
putJsonObject("data") {
put("type", "libraryEntries")
put("id", track.media_id)
put("id", track.remote_id)
putJsonObject("attributes") {
put("status", track.toKitsuStatus())
put("progress", track.last_chapter_read.toInt())
@ -103,7 +104,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
with(json) {
authClient.newCall(
Request.Builder()
.url("${baseUrl}library-entries/${track.media_id}")
.url("${baseUrl}library-entries/${track.remote_id}")
.headers(
headersOf(
"Content-Type",
@ -124,19 +125,19 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
}
}
suspend fun removeLibManga(track: Track): Track {
return withIOContext {
authClient.newCall(
DELETE(
"${baseUrl}library-entries/${track.media_id}",
headers = headersOf(
"Content-Type",
"application/vnd.api+json",
suspend fun removeLibManga(track: DomainTrack) {
withIOContext {
authClient
.newCall(
DELETE(
"${baseUrl}library-entries/${track.remoteId}",
headers = headersOf(
"Content-Type",
"application/vnd.api+json",
),
),
),
)
)
.awaitSuccess()
track
}
}
suspend fun search(query: String): List<TrackSearch> {
@ -187,7 +188,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
suspend fun findLibManga(track: Track, userId: String): Track? {
return withIOContext {
val url = "${baseUrl}library-entries".toUri().buildUpon()
.encodedQuery("filter[manga_id]=${track.media_id}&filter[user_id]=$userId")
.encodedQuery("filter[manga_id]=${track.remote_id}&filter[user_id]=$userId")
.appendQueryParameter("include", "manga")
.build()
with(json) {
@ -210,7 +211,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
suspend fun getLibManga(track: Track): Track {
return withIOContext {
val url = "${baseUrl}library-entries".toUri().buildUpon()
.encodedQuery("filter[id]=${track.media_id}")
.encodedQuery("filter[id]=${track.remote_id}")
.appendQueryParameter("include", "manga")
.build()
with(json) {

View File

@ -37,12 +37,12 @@ class KitsuSearchManga(obj: JsonObject) {
@CallSuper
fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply {
media_id = this@KitsuSearchManga.id
remote_id = this@KitsuSearchManga.id
title = canonicalTitle
total_chapters = chapterCount ?: 0
cover_url = original ?: ""
summary = synopsis ?: ""
tracking_url = KitsuApi.mangaUrl(media_id)
tracking_url = KitsuApi.mangaUrl(remote_id)
score = rating ?: -1f
publishing_status = if (endDate == null) {
"Publishing"
@ -70,12 +70,12 @@ class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
val progress = obj["attributes"]!!.jsonObject["progress"]!!.jsonPrimitive.int
fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply {
media_id = libraryId
remote_id = libraryId
title = canonicalTitle
total_chapters = chapterCount ?: 0
cover_url = original
summary = synopsis
tracking_url = KitsuApi.mangaUrl(media_id)
tracking_url = KitsuApi.mangaUrl(remote_id)
publishing_status = this@KitsuLibManga.status
publishing_type = type
start_date = startDate

View File

@ -52,7 +52,7 @@ class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker {
override fun getScoreList(): ImmutableList<String> = persistentListOf()
override fun displayScore(track: Track): String = ""
override fun displayScore(track: DomainTrack): String = ""
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {

View File

@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import tachiyomi.i18n.MR
import tachiyomi.domain.track.model.Track as DomainTrack
class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker {
@ -60,7 +61,7 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
override fun indexToScore(index: Int): Float = SCORE_LIST[index].toFloat()
override fun displayScore(track: Track): String = track.score.toString()
override fun displayScore(track: DomainTrack): String = track.score.toString()
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETE_LIST && didReadChapter) {
@ -70,9 +71,8 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
return track
}
override suspend fun delete(track: Track): Track {
override suspend fun delete(track: DomainTrack) {
api.deleteSeriesFromList(track)
return track
}
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {

View File

@ -30,6 +30,7 @@ import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody
import tachiyomi.core.util.system.logcat
import uy.kohesive.injekt.injectLazy
import tachiyomi.domain.track.model.Track as DomainTrack
class MangaUpdatesApi(
interceptor: MangaUpdatesInterceptor,
@ -48,7 +49,7 @@ class MangaUpdatesApi(
suspend fun getSeriesListItem(track: Track): Pair<ListItem, Rating?> {
val listItem = with(json) {
authClient.newCall(GET("$baseUrl/v1/lists/series/${track.media_id}"))
authClient.newCall(GET("$baseUrl/v1/lists/series/${track.remote_id}"))
.awaitSuccess()
.parseAs<ListItem>()
}
@ -63,7 +64,7 @@ class MangaUpdatesApi(
val body = buildJsonArray {
addJsonObject {
putJsonObject("series") {
put("id", track.media_id)
put("id", track.remote_id)
}
put("list_id", status)
}
@ -87,7 +88,7 @@ class MangaUpdatesApi(
val body = buildJsonArray {
addJsonObject {
putJsonObject("series") {
put("id", track.media_id)
put("id", track.remote_id)
}
put("list_id", track.status)
putJsonObject("status") {
@ -106,9 +107,9 @@ class MangaUpdatesApi(
updateSeriesRating(track)
}
suspend fun deleteSeriesFromList(track: Track) {
suspend fun deleteSeriesFromList(track: DomainTrack) {
val body = buildJsonArray {
add(track.media_id)
add(track.remoteId)
}
authClient.newCall(
POST(
@ -122,7 +123,7 @@ class MangaUpdatesApi(
private suspend fun getSeriesRating(track: Track): Rating? {
return try {
with(json) {
authClient.newCall(GET("$baseUrl/v1/series/${track.media_id}/rating"))
authClient.newCall(GET("$baseUrl/v1/series/${track.remote_id}/rating"))
.awaitSuccess()
.parseAs<Rating>()
}
@ -138,7 +139,7 @@ class MangaUpdatesApi(
}
authClient.newCall(
PUT(
url = "$baseUrl/v1/series/${track.media_id}/rating",
url = "$baseUrl/v1/series/${track.remote_id}/rating",
body = body.toString().toRequestBody(contentType),
),
)
@ -146,7 +147,7 @@ class MangaUpdatesApi(
} else {
authClient.newCall(
DELETE(
url = "$baseUrl/v1/series/${track.media_id}/rating",
url = "$baseUrl/v1/series/${track.remote_id}/rating",
),
)
.awaitSuccess()

View File

@ -25,7 +25,7 @@ data class Record(
fun Record.toTrackSearch(id: Long): TrackSearch {
return TrackSearch.create(id).apply {
media_id = this@toTrackSearch.seriesId ?: 0L
remote_id = this@toTrackSearch.seriesId ?: 0L
title = this@toTrackSearch.title?.htmlDecode() ?: ""
total_chapters = 0
cover_url = this@toTrackSearch.image?.url?.original ?: ""

View File

@ -10,7 +10,7 @@ class TrackSearch : Track {
override var sync_id: Int = 0
override var media_id: Long = 0
override var remote_id: Long = 0
override var library_id: Long? = null
@ -48,7 +48,7 @@ class TrackSearch : Track {
if (manga_id != other.manga_id) return false
if (sync_id != other.sync_id) return false
if (media_id != other.media_id) return false
if (remote_id != other.remote_id) return false
return true
}
@ -56,7 +56,7 @@ class TrackSearch : Track {
override fun hashCode(): Int {
var result = manga_id.hashCode()
result = 31 * result + sync_id
result = 31 * result + media_id.hashCode()
result = 31 * result + remote_id.hashCode()
return result
}

View File

@ -13,6 +13,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import tachiyomi.i18n.MR
import uy.kohesive.injekt.injectLazy
import tachiyomi.domain.track.model.Track as DomainTrack
class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
@ -65,7 +66,7 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
override fun getScoreList(): ImmutableList<String> = SCORE_LIST
override fun displayScore(track: Track): String {
override fun displayScore(track: DomainTrack): String {
return track.score.toInt().toString()
}
@ -91,15 +92,15 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
return api.updateItem(track)
}
override suspend fun delete(track: Track): Track {
return api.deleteItem(track)
override suspend fun delete(track: DomainTrack) {
api.deleteItem(track)
}
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
val remoteTrack = api.findListItem(track)
return if (remoteTrack != null) {
track.copyPersonalFrom(remoteTrack)
track.media_id = remoteTrack.media_id
track.remote_id = remoteTrack.remote_id
if (track.status != COMPLETED) {
val isRereading = track.status == REREADING

View File

@ -4,6 +4,7 @@ import android.net.Uri
import androidx.core.net.toUri
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.DELETE
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.awaitSuccess
@ -31,6 +32,7 @@ import tachiyomi.core.util.lang.withIOContext
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
import java.util.Locale
import tachiyomi.domain.track.model.Track as DomainTrack
class MyAnimeListApi(
private val trackId: Long,
@ -114,7 +116,7 @@ class MyAnimeListApi(
.let {
val obj = it.jsonObject
TrackSearch.create(trackId).apply {
media_id = obj["id"]!!.jsonPrimitive.long
remote_id = obj["id"]!!.jsonPrimitive.long
title = obj["title"]!!.jsonPrimitive.content
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
@ -122,7 +124,7 @@ class MyAnimeListApi(
cover_url =
obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content
?: ""
tracking_url = "https://myanimelist.net/manga/$media_id"
tracking_url = "https://myanimelist.net/manga/$remote_id"
publishing_status =
obj["status"]!!.jsonPrimitive.content.replace("_", " ")
publishing_type =
@ -154,7 +156,7 @@ class MyAnimeListApi(
}
val request = Request.Builder()
.url(mangaUrl(track.media_id).toString())
.url(mangaUrl(track.remote_id).toString())
.put(formBodyBuilder.build())
.build()
with(json) {
@ -166,24 +168,18 @@ class MyAnimeListApi(
}
}
suspend fun deleteItem(track: Track): Track {
return withIOContext {
val request = Request.Builder()
.url(mangaUrl(track.media_id).toString())
.delete()
.build()
with(json) {
authClient.newCall(request)
.awaitSuccess()
track
}
suspend fun deleteItem(track: DomainTrack) {
withIOContext {
authClient
.newCall(DELETE(mangaUrl(track.remoteId).toString()))
.awaitSuccess()
}
}
suspend fun findListItem(track: Track): Track? {
return withIOContext {
val uri = "$baseApiUrl/manga".toUri().buildUpon()
.appendPath(track.media_id.toString())
.appendPath(track.remote_id.toString())
.appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}")
.build()
with(json) {

View File

@ -13,6 +13,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import tachiyomi.i18n.MR
import uy.kohesive.injekt.injectLazy
import tachiyomi.domain.track.model.Track as DomainTrack
class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
@ -37,7 +38,7 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
override fun getScoreList(): ImmutableList<String> = SCORE_LIST
override fun displayScore(track: Track): String {
override fun displayScore(track: DomainTrack): String {
return track.score.toInt().toString()
}
@ -59,8 +60,8 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
return api.updateLibManga(track, getUsername())
}
override suspend fun delete(track: Track): Track {
return api.deleteLibManga(track)
override suspend fun delete(track: DomainTrack) {
api.deleteLibManga(track)
}
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {

View File

@ -27,6 +27,7 @@ import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody
import tachiyomi.core.util.lang.withIOContext
import uy.kohesive.injekt.injectLazy
import tachiyomi.domain.track.model.Track as DomainTrack
class ShikimoriApi(
private val trackId: Long,
@ -44,7 +45,7 @@ class ShikimoriApi(
val payload = buildJsonObject {
putJsonObject("user_rate") {
put("user_id", userId)
put("target_id", track.media_id)
put("target_id", track.remote_id)
put("target_type", "Manga")
put("chapters", track.last_chapter_read.toInt())
put("score", track.score.toInt())
@ -69,14 +70,11 @@ class ShikimoriApi(
suspend fun updateLibManga(track: Track, userId: String): Track = addLibManga(track, userId)
suspend fun deleteLibManga(track: Track): Track {
return withIOContext {
authClient.newCall(
DELETE(
"$apiUrl/v2/user_rates/${track.library_id}",
),
).awaitSuccess()
track
suspend fun deleteLibManga(track: DomainTrack) {
withIOContext {
authClient
.newCall(DELETE("$apiUrl/v2/user_rates/${track.libraryId}"))
.awaitSuccess()
}
}
@ -102,7 +100,7 @@ class ShikimoriApi(
private fun jsonToSearch(obj: JsonObject): TrackSearch {
return TrackSearch.create(trackId).apply {
media_id = obj["id"]!!.jsonPrimitive.long
remote_id = obj["id"]!!.jsonPrimitive.long
title = obj["name"]!!.jsonPrimitive.content
total_chapters = obj["chapters"]!!.jsonPrimitive.int
cover_url = baseUrl + obj["image"]!!.jsonObject["preview"]!!.jsonPrimitive.content
@ -118,7 +116,7 @@ class ShikimoriApi(
private fun jsonToTrack(obj: JsonObject, mangas: JsonObject): Track {
return Track.create(trackId).apply {
title = mangas["name"]!!.jsonPrimitive.content
media_id = obj["id"]!!.jsonPrimitive.long
remote_id = obj["id"]!!.jsonPrimitive.long
total_chapters = mangas["chapters"]!!.jsonPrimitive.int
library_id = obj["id"]!!.jsonPrimitive.long
last_chapter_read = obj["chapters"]!!.jsonPrimitive.float
@ -131,7 +129,7 @@ class ShikimoriApi(
suspend fun findLibManga(track: Track, userId: String): Track? {
return withIOContext {
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
.appendPath(track.media_id.toString())
.appendPath(track.remote_id.toString())
.build()
val mangas = with(json) {
authClient.newCall(GET(urlMangas.toString()))
@ -141,7 +139,7 @@ class ShikimoriApi(
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
.appendQueryParameter("user_id", userId)
.appendQueryParameter("target_id", track.media_id.toString())
.appendQueryParameter("target_id", track.remote_id.toString())
.appendQueryParameter("target_type", "Manga")
.build()
with(json) {

View File

@ -45,7 +45,7 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
override fun getScoreList(): ImmutableList<String> = persistentListOf()
override fun displayScore(track: Track): String = ""
override fun displayScore(track: DomainTrack): String = ""
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
if (track.status != COMPLETED) {

View File

@ -399,7 +399,7 @@ private data class TrackScoreSelectorScreen(
private class Model(
private val track: Track,
private val tracker: Tracker,
) : StateScreenModel<Model.State>(State(tracker.displayScore(track.toDbTrack()))) {
) : StateScreenModel<Model.State>(State(tracker.displayScore(track))) {
fun getSelections(): ImmutableList<String> {
return tracker.getScoreList()
@ -816,7 +816,7 @@ private data class TrackerRemoveScreen(
fun deleteMangaFromService() {
screenModelScope.launchNonCancellable {
(tracker as DeletableTracker).delete(track.toDbTrack())
(tracker as DeletableTracker).delete(track)
}
}

View File

@ -58,7 +58,7 @@ data class DummyTracker(
override fun indexToScore(index: Int): Float = getScoreList()[index].toFloat()
override fun displayScore(track: eu.kanade.tachiyomi.data.database.models.Track): String =
override fun displayScore(track: Track): String =
track.score.toString()
override suspend fun update(