mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-28 23:53:16 -05:00
Some domain Track model migrations
This commit is contained in:
parent
5908bd1930
commit
6d74a86711
28 changed files with 129 additions and 127 deletions
|
@ -16,7 +16,7 @@ fun Track.copyPersonalFrom(other: Track): Track {
|
||||||
fun Track.toDbTrack(): DbTrack = DbTrack.create(syncId).also {
|
fun Track.toDbTrack(): DbTrack = DbTrack.create(syncId).also {
|
||||||
it.id = id
|
it.id = id
|
||||||
it.manga_id = mangaId
|
it.manga_id = mangaId
|
||||||
it.media_id = remoteId
|
it.remote_id = remoteId
|
||||||
it.library_id = libraryId
|
it.library_id = libraryId
|
||||||
it.title = title
|
it.title = title
|
||||||
it.last_chapter_read = lastChapterRead.toFloat()
|
it.last_chapter_read = lastChapterRead.toFloat()
|
||||||
|
@ -34,7 +34,7 @@ fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? {
|
||||||
id = trackId,
|
id = trackId,
|
||||||
mangaId = manga_id,
|
mangaId = manga_id,
|
||||||
syncId = sync_id.toLong(),
|
syncId = sync_id.toLong(),
|
||||||
remoteId = media_id,
|
remoteId = remote_id,
|
||||||
libraryId = library_id,
|
libraryId = library_id,
|
||||||
title = title,
|
title = title,
|
||||||
lastChapterRead = last_chapter_read.toDouble(),
|
lastChapterRead = last_chapter_read.toDouble(),
|
||||||
|
|
|
@ -47,7 +47,6 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import dev.icerock.moko.resources.StringResource
|
import dev.icerock.moko.resources.StringResource
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
|
||||||
import eu.kanade.presentation.components.DropdownMenu
|
import eu.kanade.presentation.components.DropdownMenu
|
||||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||||
import eu.kanade.presentation.track.components.TrackLogoIcon
|
import eu.kanade.presentation.track.components.TrackLogoIcon
|
||||||
|
@ -101,7 +100,7 @@ fun TrackInfoDialogHome(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onChaptersClick = { onChapterClick(item) },
|
onChaptersClick = { onChapterClick(item) },
|
||||||
score = item.tracker.displayScore(item.track.toDbTrack())
|
score = item.tracker.displayScore(item.track)
|
||||||
.takeIf { supportsScoring && item.track.score != 0.0 },
|
.takeIf { supportsScoring && item.track.score != 0.0 },
|
||||||
onScoreClick = { onScoreClick(item) }
|
onScoreClick = { onScoreClick(item) }
|
||||||
.takeIf { supportsScoring },
|
.takeIf { supportsScoring },
|
||||||
|
|
|
@ -63,7 +63,7 @@ internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composab
|
||||||
it.id = Random.nextLong()
|
it.id = Random.nextLong()
|
||||||
it.manga_id = Random.nextLong()
|
it.manga_id = Random.nextLong()
|
||||||
it.sync_id = Random.nextInt()
|
it.sync_id = Random.nextInt()
|
||||||
it.media_id = Random.nextLong()
|
it.remote_id = Random.nextLong()
|
||||||
it.library_id = Random.nextLong()
|
it.library_id = Random.nextLong()
|
||||||
it.title = lorem((1..10).random()).joinToString()
|
it.title = lorem((1..10).random()).joinToString()
|
||||||
it.last_chapter_read = (0..100).random().toFloat()
|
it.last_chapter_read = (0..100).random().toFloat()
|
||||||
|
|
|
@ -10,7 +10,7 @@ interface Track : Serializable {
|
||||||
|
|
||||||
var sync_id: Int
|
var sync_id: Int
|
||||||
|
|
||||||
var media_id: Long
|
var remote_id: Long
|
||||||
|
|
||||||
var library_id: Long?
|
var library_id: Long?
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ class TrackImpl : Track {
|
||||||
|
|
||||||
override var sync_id: Int = 0
|
override var sync_id: Int = 0
|
||||||
|
|
||||||
override var media_id: Long = 0
|
override var remote_id: Long = 0
|
||||||
|
|
||||||
override var library_id: Long? = null
|
override var library_id: Long? = null
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package eu.kanade.tachiyomi.data.track
|
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.
|
* Tracker that support deleting am entry from a user's list.
|
||||||
*/
|
*/
|
||||||
interface DeletableTracker {
|
interface DeletableTracker {
|
||||||
|
|
||||||
suspend fun delete(track: Track): Track
|
suspend fun delete(track: Track)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
interface Tracker {
|
interface Tracker {
|
||||||
|
|
||||||
|
@ -39,11 +40,11 @@ interface Tracker {
|
||||||
fun getScoreList(): ImmutableList<String>
|
fun getScoreList(): ImmutableList<String>
|
||||||
|
|
||||||
// TODO: Store all scores as 10 point in the future maybe?
|
// 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 indexToScore(index: Int): Float
|
||||||
|
|
||||||
fun displayScore(track: Track): String
|
fun displayScore(track: DomainTrack): String
|
||||||
|
|
||||||
suspend fun update(track: Track, didReadChapter: Boolean = false): Track
|
suspend fun update(track: Track, didReadChapter: Boolean = false): Track
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.track.anilist
|
||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import dev.icerock.moko.resources.StringResource
|
import dev.icerock.moko.resources.StringResource
|
||||||
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
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.BaseTracker
|
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
|
val score = track.score
|
||||||
|
|
||||||
return when (scorePreference.get()) {
|
return when (scorePreference.get()) {
|
||||||
POINT_5 -> when (score) {
|
POINT_5 -> when (score) {
|
||||||
0f -> "0 ★"
|
0.0 -> "0 ★"
|
||||||
else -> "${((score + 10) / 20).toInt()} ★"
|
else -> "${((score + 10) / 20).toInt()} ★"
|
||||||
}
|
}
|
||||||
POINT_3 -> when {
|
POINT_3 -> when {
|
||||||
score == 0f -> "0"
|
score == 0.0 -> "0"
|
||||||
score <= 35 -> "😦"
|
score <= 35 -> "😦"
|
||||||
score <= 60 -> "😐"
|
score <= 60 -> "😐"
|
||||||
else -> "😊"
|
else -> "😊"
|
||||||
|
@ -167,13 +168,13 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
|
||||||
return api.updateLibManga(track)
|
return api.updateLibManga(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun delete(track: Track): Track {
|
override suspend fun delete(track: DomainTrack) {
|
||||||
if (track.library_id == null || track.library_id!! == 0L) {
|
if (track.libraryId == null || track.libraryId == 0L) {
|
||||||
val libManga = api.findLibManga(track, getUsername().toInt()) ?: return track
|
val libManga = api.findLibManga(track.toDbTrack(), getUsername().toInt()) ?: return
|
||||||
track.library_id = libManga.library_id
|
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 {
|
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import java.time.LocalDate
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import kotlin.time.Duration.Companion.minutes
|
import kotlin.time.Duration.Companion.minutes
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
val payload = buildJsonObject {
|
val payload = buildJsonObject {
|
||||||
put("query", query)
|
put("query", query)
|
||||||
putJsonObject("variables") {
|
putJsonObject("variables") {
|
||||||
put("mangaId", track.media_id)
|
put("mangaId", track.remote_id)
|
||||||
put("progress", track.last_chapter_read.toInt())
|
put("progress", track.last_chapter_read.toInt())
|
||||||
put("status", track.toAnilistStatus())
|
put("status", track.toAnilistStatus())
|
||||||
}
|
}
|
||||||
|
@ -113,8 +114,8 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteLibManga(track: Track): Track {
|
suspend fun deleteLibManga(track: DomainTrack) {
|
||||||
return withIOContext {
|
withIOContext {
|
||||||
val query = """
|
val query = """
|
||||||
|mutation DeleteManga(${'$'}listId: Int) {
|
|mutation DeleteManga(${'$'}listId: Int) {
|
||||||
|DeleteMediaListEntry(id: ${'$'}listId) {
|
|DeleteMediaListEntry(id: ${'$'}listId) {
|
||||||
|
@ -126,12 +127,11 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
val payload = buildJsonObject {
|
val payload = buildJsonObject {
|
||||||
put("query", query)
|
put("query", query)
|
||||||
putJsonObject("variables") {
|
putJsonObject("variables") {
|
||||||
put("listId", track.library_id)
|
put("listId", track.libraryId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
authClient.newCall(POST(apiUrl, body = payload.toString().toRequestBody(jsonMime)))
|
authClient.newCall(POST(apiUrl, body = payload.toString().toRequestBody(jsonMime)))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
track
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suspend fun search(search: String): List<TrackSearch> {
|
suspend fun search(search: String): List<TrackSearch> {
|
||||||
|
@ -235,7 +235,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
put("query", query)
|
put("query", query)
|
||||||
putJsonObject("variables") {
|
putJsonObject("variables") {
|
||||||
put("id", userid)
|
put("id", userid)
|
||||||
put("manga_id", track.media_id)
|
put("manga_id", track.remote_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
with(json) {
|
with(json) {
|
||||||
|
@ -258,8 +258,8 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getLibManga(track: Track, userid: Int): Track {
|
suspend fun getLibManga(track: Track, userId: Int): Track {
|
||||||
return findLibManga(track, userid) ?: throw Exception("Could not find manga")
|
return findLibManga(track, userId) ?: throw Exception("Could not find manga")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createOAuth(token: String): OAuth {
|
fun createOAuth(token: String): OAuth {
|
||||||
|
|
|
@ -9,9 +9,10 @@ import kotlinx.serialization.Serializable
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
data class ALManga(
|
data class ALManga(
|
||||||
val media_id: Long,
|
val remote_id: Long,
|
||||||
val title_user_pref: String,
|
val title_user_pref: String,
|
||||||
val image_url_lge: String,
|
val image_url_lge: String,
|
||||||
val description: String?,
|
val description: String?,
|
||||||
|
@ -23,13 +24,13 @@ data class ALManga(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun toTrack() = TrackSearch.create(TrackerManager.ANILIST).apply {
|
fun toTrack() = TrackSearch.create(TrackerManager.ANILIST).apply {
|
||||||
media_id = this@ALManga.media_id
|
remote_id = this@ALManga.remote_id
|
||||||
title = title_user_pref
|
title = title_user_pref
|
||||||
total_chapters = this@ALManga.total_chapters
|
total_chapters = this@ALManga.total_chapters
|
||||||
cover_url = image_url_lge
|
cover_url = image_url_lge
|
||||||
summary = description?.htmlDecode() ?: ""
|
summary = description?.htmlDecode() ?: ""
|
||||||
score = average_score.toFloat()
|
score = average_score.toFloat()
|
||||||
tracking_url = AnilistApi.mangaUrl(media_id)
|
tracking_url = AnilistApi.mangaUrl(remote_id)
|
||||||
publishing_status = this@ALManga.publishing_status
|
publishing_status = this@ALManga.publishing_status
|
||||||
publishing_type = format
|
publishing_type = format
|
||||||
if (start_date_fuzzy != 0L) {
|
if (start_date_fuzzy != 0L) {
|
||||||
|
@ -54,7 +55,7 @@ data class ALUserManga(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun toTrack() = Track.create(TrackerManager.ANILIST).apply {
|
fun toTrack() = Track.create(TrackerManager.ANILIST).apply {
|
||||||
media_id = manga.media_id
|
remote_id = manga.remote_id
|
||||||
title = manga.title_user_pref
|
title = manga.title_user_pref
|
||||||
status = toTrackStatus()
|
status = toTrackStatus()
|
||||||
score = score_raw.toFloat()
|
score = score_raw.toFloat()
|
||||||
|
@ -98,28 +99,28 @@ fun Track.toAnilistStatus() = when (status) {
|
||||||
|
|
||||||
private val preferences: TrackPreferences by injectLazy()
|
private val preferences: TrackPreferences by injectLazy()
|
||||||
|
|
||||||
fun Track.toAnilistScore(): String = when (preferences.anilistScoreType().get()) {
|
fun DomainTrack.toAnilistScore(): String = when (preferences.anilistScoreType().get()) {
|
||||||
// 10 point
|
// 10 point
|
||||||
"POINT_10" -> (score.toInt() / 10).toString()
|
"POINT_10" -> (score.toInt() / 10).toString()
|
||||||
// 100 point
|
// 100 point
|
||||||
"POINT_100" -> score.toInt().toString()
|
"POINT_100" -> score.toInt().toString()
|
||||||
// 5 stars
|
// 5 stars
|
||||||
"POINT_5" -> when {
|
"POINT_5" -> when {
|
||||||
score == 0f -> "0"
|
score == 0.0 -> "0"
|
||||||
score < 30 -> "1"
|
score < 30 -> "1"
|
||||||
score < 50 -> "2"
|
score < 50 -> "2"
|
||||||
score < 70 -> "3"
|
score < 70 -> "3"
|
||||||
score < 90 -> "4"
|
score < 90 -> "4"
|
||||||
else -> "5"
|
else -> "5"
|
||||||
}
|
}
|
||||||
// Smiley
|
// Smiley
|
||||||
"POINT_3" -> when {
|
"POINT_3" -> when {
|
||||||
score == 0f -> "0"
|
score == 0.0 -> "0"
|
||||||
score <= 35 -> ":("
|
score <= 35 -> ":("
|
||||||
score <= 60 -> ":|"
|
score <= 60 -> ":|"
|
||||||
else -> ":)"
|
else -> ":)"
|
||||||
}
|
}
|
||||||
// 10 point decimal
|
// 10 point decimal
|
||||||
"POINT_10_DECIMAL" -> (score / 10).toString()
|
"POINT_10_DECIMAL" -> (score / 10).toString()
|
||||||
else -> throw NotImplementedError("Unknown score type")
|
else -> throw NotImplementedError("Unknown score type")
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
|
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 getScoreList(): ImmutableList<String> = SCORE_LIST
|
||||||
|
|
||||||
override fun displayScore(track: Track): String {
|
override fun displayScore(track: DomainTrack): String {
|
||||||
return track.score.toInt().toString()
|
return track.score.toInt().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class BangumiApi(
|
||||||
.add("rating", track.score.toInt().toString())
|
.add("rating", track.score.toInt().toString())
|
||||||
.add("status", track.toBangumiStatus())
|
.add("status", track.toBangumiStatus())
|
||||||
.build()
|
.build()
|
||||||
authClient.newCall(POST("$apiUrl/collection/${track.media_id}/update", body = body))
|
authClient.newCall(POST("$apiUrl/collection/${track.remote_id}/update", body = body))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
track
|
track
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ class BangumiApi(
|
||||||
.add("rating", track.score.toInt().toString())
|
.add("rating", track.score.toInt().toString())
|
||||||
.add("status", track.toBangumiStatus())
|
.add("status", track.toBangumiStatus())
|
||||||
.build()
|
.build()
|
||||||
authClient.newCall(POST("$apiUrl/collection/${track.media_id}/update", body = sbody))
|
authClient.newCall(POST("$apiUrl/collection/${track.remote_id}/update", body = sbody))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
|
|
||||||
// chapter update
|
// chapter update
|
||||||
|
@ -64,7 +64,7 @@ class BangumiApi(
|
||||||
.build()
|
.build()
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
"$apiUrl/subject/${track.media_id}/update/watched_eps",
|
"$apiUrl/subject/${track.remote_id}/update/watched_eps",
|
||||||
body = body,
|
body = body,
|
||||||
),
|
),
|
||||||
).awaitSuccess()
|
).awaitSuccess()
|
||||||
|
@ -111,7 +111,7 @@ class BangumiApi(
|
||||||
}
|
}
|
||||||
val rating = obj["rating"]?.jsonObject?.get("score")?.jsonPrimitive?.floatOrNull ?: -1f
|
val rating = obj["rating"]?.jsonObject?.get("score")?.jsonPrimitive?.floatOrNull ?: -1f
|
||||||
return TrackSearch.create(trackId).apply {
|
return TrackSearch.create(trackId).apply {
|
||||||
media_id = obj["id"]!!.jsonPrimitive.long
|
remote_id = obj["id"]!!.jsonPrimitive.long
|
||||||
title = obj["name_cn"]!!.jsonPrimitive.content
|
title = obj["name_cn"]!!.jsonPrimitive.content
|
||||||
cover_url = coverUrl
|
cover_url = coverUrl
|
||||||
summary = obj["name"]!!.jsonPrimitive.content
|
summary = obj["name"]!!.jsonPrimitive.content
|
||||||
|
@ -124,7 +124,7 @@ class BangumiApi(
|
||||||
suspend fun findLibManga(track: Track): Track? {
|
suspend fun findLibManga(track: Track): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(GET("$apiUrl/subject/${track.media_id}"))
|
authClient.newCall(GET("$apiUrl/subject/${track.remote_id}"))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
.let { jsonToSearch(it) }
|
.let { jsonToSearch(it) }
|
||||||
|
@ -134,7 +134,7 @@ class BangumiApi(
|
||||||
|
|
||||||
suspend fun statusLibManga(track: Track): Track? {
|
suspend fun statusLibManga(track: Track): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val urlUserRead = "$apiUrl/collection/${track.media_id}"
|
val urlUserRead = "$apiUrl/collection/${track.remote_id}"
|
||||||
val requestUserRead = Request.Builder()
|
val requestUserRead = Request.Builder()
|
||||||
.url(urlUserRead)
|
.url(urlUserRead)
|
||||||
.cacheControl(CacheControl.FORCE_NETWORK)
|
.cacheControl(CacheControl.FORCE_NETWORK)
|
||||||
|
|
|
@ -55,7 +55,7 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker {
|
||||||
|
|
||||||
override fun getScoreList(): ImmutableList<String> = persistentListOf()
|
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 {
|
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
|
||||||
if (track.status != COMPLETED) {
|
if (track.status != COMPLETED) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import kotlinx.serialization.json.Json
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
|
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
|
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.#")
|
val df = DecimalFormat("0.#")
|
||||||
return df.format(track.score)
|
return df.format(track.score)
|
||||||
}
|
}
|
||||||
|
@ -92,15 +93,15 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
|
||||||
return api.updateLibManga(track)
|
return api.updateLibManga(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun delete(track: Track): Track {
|
override suspend fun delete(track: DomainTrack) {
|
||||||
return api.removeLibManga(track)
|
api.removeLibManga(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
||||||
val remoteTrack = api.findLibManga(track, getUserId())
|
val remoteTrack = api.findLibManga(track, getUserId())
|
||||||
return if (remoteTrack != null) {
|
return if (remoteTrack != null) {
|
||||||
track.copyPersonalFrom(remoteTrack)
|
track.copyPersonalFrom(remoteTrack)
|
||||||
track.media_id = remoteTrack.media_id
|
track.remote_id = remoteTrack.remote_id
|
||||||
|
|
||||||
if (track.status != COMPLETED) {
|
if (track.status != COMPLETED) {
|
||||||
track.status = if (hasReadChapters) READING else track.status
|
track.status = if (hasReadChapters) READING else track.status
|
||||||
|
|
|
@ -29,6 +29,7 @@ import tachiyomi.core.util.lang.withIOContext
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) {
|
class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) {
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
putJsonObject("media") {
|
putJsonObject("media") {
|
||||||
putJsonObject("data") {
|
putJsonObject("data") {
|
||||||
put("id", track.media_id)
|
put("id", track.remote_id)
|
||||||
put("type", "manga")
|
put("type", "manga")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +78,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
.parseAs<JsonObject>()
|
.parseAs<JsonObject>()
|
||||||
.let {
|
.let {
|
||||||
track.media_id = it["data"]!!.jsonObject["id"]!!.jsonPrimitive.long
|
track.remote_id = it["data"]!!.jsonObject["id"]!!.jsonPrimitive.long
|
||||||
track
|
track
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +90,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
val data = buildJsonObject {
|
val data = buildJsonObject {
|
||||||
putJsonObject("data") {
|
putJsonObject("data") {
|
||||||
put("type", "libraryEntries")
|
put("type", "libraryEntries")
|
||||||
put("id", track.media_id)
|
put("id", track.remote_id)
|
||||||
putJsonObject("attributes") {
|
putJsonObject("attributes") {
|
||||||
put("status", track.toKitsuStatus())
|
put("status", track.toKitsuStatus())
|
||||||
put("progress", track.last_chapter_read.toInt())
|
put("progress", track.last_chapter_read.toInt())
|
||||||
|
@ -103,7 +104,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
.url("${baseUrl}library-entries/${track.media_id}")
|
.url("${baseUrl}library-entries/${track.remote_id}")
|
||||||
.headers(
|
.headers(
|
||||||
headersOf(
|
headersOf(
|
||||||
"Content-Type",
|
"Content-Type",
|
||||||
|
@ -124,11 +125,12 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun removeLibManga(track: Track): Track {
|
suspend fun removeLibManga(track: DomainTrack) {
|
||||||
return withIOContext {
|
withIOContext {
|
||||||
authClient.newCall(
|
authClient
|
||||||
|
.newCall(
|
||||||
DELETE(
|
DELETE(
|
||||||
"${baseUrl}library-entries/${track.media_id}",
|
"${baseUrl}library-entries/${track.remoteId}",
|
||||||
headers = headersOf(
|
headers = headersOf(
|
||||||
"Content-Type",
|
"Content-Type",
|
||||||
"application/vnd.api+json",
|
"application/vnd.api+json",
|
||||||
|
@ -136,7 +138,6 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
track
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suspend fun search(query: String): List<TrackSearch> {
|
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? {
|
suspend fun findLibManga(track: Track, userId: String): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
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")
|
.appendQueryParameter("include", "manga")
|
||||||
.build()
|
.build()
|
||||||
with(json) {
|
with(json) {
|
||||||
|
@ -210,7 +211,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||||
suspend fun getLibManga(track: Track): Track {
|
suspend fun getLibManga(track: Track): Track {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
val url = "${baseUrl}library-entries".toUri().buildUpon()
|
||||||
.encodedQuery("filter[id]=${track.media_id}")
|
.encodedQuery("filter[id]=${track.remote_id}")
|
||||||
.appendQueryParameter("include", "manga")
|
.appendQueryParameter("include", "manga")
|
||||||
.build()
|
.build()
|
||||||
with(json) {
|
with(json) {
|
||||||
|
|
|
@ -37,12 +37,12 @@ class KitsuSearchManga(obj: JsonObject) {
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply {
|
fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply {
|
||||||
media_id = this@KitsuSearchManga.id
|
remote_id = this@KitsuSearchManga.id
|
||||||
title = canonicalTitle
|
title = canonicalTitle
|
||||||
total_chapters = chapterCount ?: 0
|
total_chapters = chapterCount ?: 0
|
||||||
cover_url = original ?: ""
|
cover_url = original ?: ""
|
||||||
summary = synopsis ?: ""
|
summary = synopsis ?: ""
|
||||||
tracking_url = KitsuApi.mangaUrl(media_id)
|
tracking_url = KitsuApi.mangaUrl(remote_id)
|
||||||
score = rating ?: -1f
|
score = rating ?: -1f
|
||||||
publishing_status = if (endDate == null) {
|
publishing_status = if (endDate == null) {
|
||||||
"Publishing"
|
"Publishing"
|
||||||
|
@ -70,12 +70,12 @@ class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
|
||||||
val progress = obj["attributes"]!!.jsonObject["progress"]!!.jsonPrimitive.int
|
val progress = obj["attributes"]!!.jsonObject["progress"]!!.jsonPrimitive.int
|
||||||
|
|
||||||
fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply {
|
fun toTrack() = TrackSearch.create(TrackerManager.KITSU).apply {
|
||||||
media_id = libraryId
|
remote_id = libraryId
|
||||||
title = canonicalTitle
|
title = canonicalTitle
|
||||||
total_chapters = chapterCount ?: 0
|
total_chapters = chapterCount ?: 0
|
||||||
cover_url = original
|
cover_url = original
|
||||||
summary = synopsis
|
summary = synopsis
|
||||||
tracking_url = KitsuApi.mangaUrl(media_id)
|
tracking_url = KitsuApi.mangaUrl(remote_id)
|
||||||
publishing_status = this@KitsuLibManga.status
|
publishing_status = this@KitsuLibManga.status
|
||||||
publishing_type = type
|
publishing_type = type
|
||||||
start_date = startDate
|
start_date = startDate
|
||||||
|
|
|
@ -52,7 +52,7 @@ class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker {
|
||||||
|
|
||||||
override fun getScoreList(): ImmutableList<String> = persistentListOf()
|
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 {
|
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
|
||||||
if (track.status != COMPLETED) {
|
if (track.status != COMPLETED) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker {
|
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 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 {
|
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
|
||||||
if (track.status != COMPLETE_LIST && didReadChapter) {
|
if (track.status != COMPLETE_LIST && didReadChapter) {
|
||||||
|
@ -70,9 +71,8 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
|
||||||
return track
|
return track
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun delete(track: Track): Track {
|
override suspend fun delete(track: DomainTrack) {
|
||||||
api.deleteSeriesFromList(track)
|
api.deleteSeriesFromList(track)
|
||||||
return track
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import okhttp3.OkHttpClient
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import tachiyomi.core.util.system.logcat
|
import tachiyomi.core.util.system.logcat
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class MangaUpdatesApi(
|
class MangaUpdatesApi(
|
||||||
interceptor: MangaUpdatesInterceptor,
|
interceptor: MangaUpdatesInterceptor,
|
||||||
|
@ -48,7 +49,7 @@ class MangaUpdatesApi(
|
||||||
|
|
||||||
suspend fun getSeriesListItem(track: Track): Pair<ListItem, Rating?> {
|
suspend fun getSeriesListItem(track: Track): Pair<ListItem, Rating?> {
|
||||||
val listItem = with(json) {
|
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()
|
.awaitSuccess()
|
||||||
.parseAs<ListItem>()
|
.parseAs<ListItem>()
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,7 @@ class MangaUpdatesApi(
|
||||||
val body = buildJsonArray {
|
val body = buildJsonArray {
|
||||||
addJsonObject {
|
addJsonObject {
|
||||||
putJsonObject("series") {
|
putJsonObject("series") {
|
||||||
put("id", track.media_id)
|
put("id", track.remote_id)
|
||||||
}
|
}
|
||||||
put("list_id", status)
|
put("list_id", status)
|
||||||
}
|
}
|
||||||
|
@ -87,7 +88,7 @@ class MangaUpdatesApi(
|
||||||
val body = buildJsonArray {
|
val body = buildJsonArray {
|
||||||
addJsonObject {
|
addJsonObject {
|
||||||
putJsonObject("series") {
|
putJsonObject("series") {
|
||||||
put("id", track.media_id)
|
put("id", track.remote_id)
|
||||||
}
|
}
|
||||||
put("list_id", track.status)
|
put("list_id", track.status)
|
||||||
putJsonObject("status") {
|
putJsonObject("status") {
|
||||||
|
@ -106,9 +107,9 @@ class MangaUpdatesApi(
|
||||||
updateSeriesRating(track)
|
updateSeriesRating(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteSeriesFromList(track: Track) {
|
suspend fun deleteSeriesFromList(track: DomainTrack) {
|
||||||
val body = buildJsonArray {
|
val body = buildJsonArray {
|
||||||
add(track.media_id)
|
add(track.remoteId)
|
||||||
}
|
}
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
POST(
|
POST(
|
||||||
|
@ -122,7 +123,7 @@ class MangaUpdatesApi(
|
||||||
private suspend fun getSeriesRating(track: Track): Rating? {
|
private suspend fun getSeriesRating(track: Track): Rating? {
|
||||||
return try {
|
return try {
|
||||||
with(json) {
|
with(json) {
|
||||||
authClient.newCall(GET("$baseUrl/v1/series/${track.media_id}/rating"))
|
authClient.newCall(GET("$baseUrl/v1/series/${track.remote_id}/rating"))
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
.parseAs<Rating>()
|
.parseAs<Rating>()
|
||||||
}
|
}
|
||||||
|
@ -138,7 +139,7 @@ class MangaUpdatesApi(
|
||||||
}
|
}
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
PUT(
|
PUT(
|
||||||
url = "$baseUrl/v1/series/${track.media_id}/rating",
|
url = "$baseUrl/v1/series/${track.remote_id}/rating",
|
||||||
body = body.toString().toRequestBody(contentType),
|
body = body.toString().toRequestBody(contentType),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -146,7 +147,7 @@ class MangaUpdatesApi(
|
||||||
} else {
|
} else {
|
||||||
authClient.newCall(
|
authClient.newCall(
|
||||||
DELETE(
|
DELETE(
|
||||||
url = "$baseUrl/v1/series/${track.media_id}/rating",
|
url = "$baseUrl/v1/series/${track.remote_id}/rating",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
|
|
|
@ -25,7 +25,7 @@ data class Record(
|
||||||
|
|
||||||
fun Record.toTrackSearch(id: Long): TrackSearch {
|
fun Record.toTrackSearch(id: Long): TrackSearch {
|
||||||
return TrackSearch.create(id).apply {
|
return TrackSearch.create(id).apply {
|
||||||
media_id = this@toTrackSearch.seriesId ?: 0L
|
remote_id = this@toTrackSearch.seriesId ?: 0L
|
||||||
title = this@toTrackSearch.title?.htmlDecode() ?: ""
|
title = this@toTrackSearch.title?.htmlDecode() ?: ""
|
||||||
total_chapters = 0
|
total_chapters = 0
|
||||||
cover_url = this@toTrackSearch.image?.url?.original ?: ""
|
cover_url = this@toTrackSearch.image?.url?.original ?: ""
|
||||||
|
|
|
@ -10,7 +10,7 @@ class TrackSearch : Track {
|
||||||
|
|
||||||
override var sync_id: Int = 0
|
override var sync_id: Int = 0
|
||||||
|
|
||||||
override var media_id: Long = 0
|
override var remote_id: Long = 0
|
||||||
|
|
||||||
override var library_id: Long? = null
|
override var library_id: Long? = null
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class TrackSearch : Track {
|
||||||
|
|
||||||
if (manga_id != other.manga_id) return false
|
if (manga_id != other.manga_id) return false
|
||||||
if (sync_id != other.sync_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
|
return true
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ class TrackSearch : Track {
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = manga_id.hashCode()
|
var result = manga_id.hashCode()
|
||||||
result = 31 * result + sync_id
|
result = 31 * result + sync_id
|
||||||
result = 31 * result + media_id.hashCode()
|
result = 31 * result + remote_id.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
|
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 getScoreList(): ImmutableList<String> = SCORE_LIST
|
||||||
|
|
||||||
override fun displayScore(track: Track): String {
|
override fun displayScore(track: DomainTrack): String {
|
||||||
return track.score.toInt().toString()
|
return track.score.toInt().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,15 +92,15 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
|
||||||
return api.updateItem(track)
|
return api.updateItem(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun delete(track: Track): Track {
|
override suspend fun delete(track: DomainTrack) {
|
||||||
return api.deleteItem(track)
|
api.deleteItem(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
||||||
val remoteTrack = api.findListItem(track)
|
val remoteTrack = api.findListItem(track)
|
||||||
return if (remoteTrack != null) {
|
return if (remoteTrack != null) {
|
||||||
track.copyPersonalFrom(remoteTrack)
|
track.copyPersonalFrom(remoteTrack)
|
||||||
track.media_id = remoteTrack.media_id
|
track.remote_id = remoteTrack.remote_id
|
||||||
|
|
||||||
if (track.status != COMPLETED) {
|
if (track.status != COMPLETED) {
|
||||||
val isRereading = track.status == REREADING
|
val isRereading = track.status == REREADING
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
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.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||||
|
@ -31,6 +32,7 @@ import tachiyomi.core.util.lang.withIOContext
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class MyAnimeListApi(
|
class MyAnimeListApi(
|
||||||
private val trackId: Long,
|
private val trackId: Long,
|
||||||
|
@ -114,7 +116,7 @@ class MyAnimeListApi(
|
||||||
.let {
|
.let {
|
||||||
val obj = it.jsonObject
|
val obj = it.jsonObject
|
||||||
TrackSearch.create(trackId).apply {
|
TrackSearch.create(trackId).apply {
|
||||||
media_id = obj["id"]!!.jsonPrimitive.long
|
remote_id = obj["id"]!!.jsonPrimitive.long
|
||||||
title = obj["title"]!!.jsonPrimitive.content
|
title = obj["title"]!!.jsonPrimitive.content
|
||||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||||
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||||
|
@ -122,7 +124,7 @@ class MyAnimeListApi(
|
||||||
cover_url =
|
cover_url =
|
||||||
obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content
|
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 =
|
publishing_status =
|
||||||
obj["status"]!!.jsonPrimitive.content.replace("_", " ")
|
obj["status"]!!.jsonPrimitive.content.replace("_", " ")
|
||||||
publishing_type =
|
publishing_type =
|
||||||
|
@ -154,7 +156,7 @@ class MyAnimeListApi(
|
||||||
}
|
}
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(mangaUrl(track.media_id).toString())
|
.url(mangaUrl(track.remote_id).toString())
|
||||||
.put(formBodyBuilder.build())
|
.put(formBodyBuilder.build())
|
||||||
.build()
|
.build()
|
||||||
with(json) {
|
with(json) {
|
||||||
|
@ -166,24 +168,18 @@ class MyAnimeListApi(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteItem(track: Track): Track {
|
suspend fun deleteItem(track: DomainTrack) {
|
||||||
return withIOContext {
|
withIOContext {
|
||||||
val request = Request.Builder()
|
authClient
|
||||||
.url(mangaUrl(track.media_id).toString())
|
.newCall(DELETE(mangaUrl(track.remoteId).toString()))
|
||||||
.delete()
|
|
||||||
.build()
|
|
||||||
with(json) {
|
|
||||||
authClient.newCall(request)
|
|
||||||
.awaitSuccess()
|
.awaitSuccess()
|
||||||
track
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findListItem(track: Track): Track? {
|
suspend fun findListItem(track: Track): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val uri = "$baseApiUrl/manga".toUri().buildUpon()
|
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}")
|
.appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}")
|
||||||
.build()
|
.build()
|
||||||
with(json) {
|
with(json) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
|
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 getScoreList(): ImmutableList<String> = SCORE_LIST
|
||||||
|
|
||||||
override fun displayScore(track: Track): String {
|
override fun displayScore(track: DomainTrack): String {
|
||||||
return track.score.toInt().toString()
|
return track.score.toInt().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +60,8 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
|
||||||
return api.updateLibManga(track, getUsername())
|
return api.updateLibManga(track, getUsername())
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun delete(track: Track): Track {
|
override suspend fun delete(track: DomainTrack) {
|
||||||
return api.deleteLibManga(track)
|
api.deleteLibManga(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
override suspend fun bind(track: Track, hasReadChapters: Boolean): Track {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import okhttp3.OkHttpClient
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import tachiyomi.core.util.lang.withIOContext
|
import tachiyomi.core.util.lang.withIOContext
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||||
|
|
||||||
class ShikimoriApi(
|
class ShikimoriApi(
|
||||||
private val trackId: Long,
|
private val trackId: Long,
|
||||||
|
@ -44,7 +45,7 @@ class ShikimoriApi(
|
||||||
val payload = buildJsonObject {
|
val payload = buildJsonObject {
|
||||||
putJsonObject("user_rate") {
|
putJsonObject("user_rate") {
|
||||||
put("user_id", userId)
|
put("user_id", userId)
|
||||||
put("target_id", track.media_id)
|
put("target_id", track.remote_id)
|
||||||
put("target_type", "Manga")
|
put("target_type", "Manga")
|
||||||
put("chapters", track.last_chapter_read.toInt())
|
put("chapters", track.last_chapter_read.toInt())
|
||||||
put("score", track.score.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 updateLibManga(track: Track, userId: String): Track = addLibManga(track, userId)
|
||||||
|
|
||||||
suspend fun deleteLibManga(track: Track): Track {
|
suspend fun deleteLibManga(track: DomainTrack) {
|
||||||
return withIOContext {
|
withIOContext {
|
||||||
authClient.newCall(
|
authClient
|
||||||
DELETE(
|
.newCall(DELETE("$apiUrl/v2/user_rates/${track.libraryId}"))
|
||||||
"$apiUrl/v2/user_rates/${track.library_id}",
|
.awaitSuccess()
|
||||||
),
|
|
||||||
).awaitSuccess()
|
|
||||||
track
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +100,7 @@ class ShikimoriApi(
|
||||||
|
|
||||||
private fun jsonToSearch(obj: JsonObject): TrackSearch {
|
private fun jsonToSearch(obj: JsonObject): TrackSearch {
|
||||||
return TrackSearch.create(trackId).apply {
|
return TrackSearch.create(trackId).apply {
|
||||||
media_id = obj["id"]!!.jsonPrimitive.long
|
remote_id = obj["id"]!!.jsonPrimitive.long
|
||||||
title = obj["name"]!!.jsonPrimitive.content
|
title = obj["name"]!!.jsonPrimitive.content
|
||||||
total_chapters = obj["chapters"]!!.jsonPrimitive.int
|
total_chapters = obj["chapters"]!!.jsonPrimitive.int
|
||||||
cover_url = baseUrl + obj["image"]!!.jsonObject["preview"]!!.jsonPrimitive.content
|
cover_url = baseUrl + obj["image"]!!.jsonObject["preview"]!!.jsonPrimitive.content
|
||||||
|
@ -118,7 +116,7 @@ class ShikimoriApi(
|
||||||
private fun jsonToTrack(obj: JsonObject, mangas: JsonObject): Track {
|
private fun jsonToTrack(obj: JsonObject, mangas: JsonObject): Track {
|
||||||
return Track.create(trackId).apply {
|
return Track.create(trackId).apply {
|
||||||
title = mangas["name"]!!.jsonPrimitive.content
|
title = mangas["name"]!!.jsonPrimitive.content
|
||||||
media_id = obj["id"]!!.jsonPrimitive.long
|
remote_id = obj["id"]!!.jsonPrimitive.long
|
||||||
total_chapters = mangas["chapters"]!!.jsonPrimitive.int
|
total_chapters = mangas["chapters"]!!.jsonPrimitive.int
|
||||||
library_id = obj["id"]!!.jsonPrimitive.long
|
library_id = obj["id"]!!.jsonPrimitive.long
|
||||||
last_chapter_read = obj["chapters"]!!.jsonPrimitive.float
|
last_chapter_read = obj["chapters"]!!.jsonPrimitive.float
|
||||||
|
@ -131,7 +129,7 @@ class ShikimoriApi(
|
||||||
suspend fun findLibManga(track: Track, userId: String): Track? {
|
suspend fun findLibManga(track: Track, userId: String): Track? {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
||||||
.appendPath(track.media_id.toString())
|
.appendPath(track.remote_id.toString())
|
||||||
.build()
|
.build()
|
||||||
val mangas = with(json) {
|
val mangas = with(json) {
|
||||||
authClient.newCall(GET(urlMangas.toString()))
|
authClient.newCall(GET(urlMangas.toString()))
|
||||||
|
@ -141,7 +139,7 @@ class ShikimoriApi(
|
||||||
|
|
||||||
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
|
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
|
||||||
.appendQueryParameter("user_id", userId)
|
.appendQueryParameter("user_id", userId)
|
||||||
.appendQueryParameter("target_id", track.media_id.toString())
|
.appendQueryParameter("target_id", track.remote_id.toString())
|
||||||
.appendQueryParameter("target_type", "Manga")
|
.appendQueryParameter("target_type", "Manga")
|
||||||
.build()
|
.build()
|
||||||
with(json) {
|
with(json) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
|
||||||
|
|
||||||
override fun getScoreList(): ImmutableList<String> = persistentListOf()
|
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 {
|
override suspend fun update(track: Track, didReadChapter: Boolean): Track {
|
||||||
if (track.status != COMPLETED) {
|
if (track.status != COMPLETED) {
|
||||||
|
|
|
@ -399,7 +399,7 @@ private data class TrackScoreSelectorScreen(
|
||||||
private class Model(
|
private class Model(
|
||||||
private val track: Track,
|
private val track: Track,
|
||||||
private val tracker: Tracker,
|
private val tracker: Tracker,
|
||||||
) : StateScreenModel<Model.State>(State(tracker.displayScore(track.toDbTrack()))) {
|
) : StateScreenModel<Model.State>(State(tracker.displayScore(track))) {
|
||||||
|
|
||||||
fun getSelections(): ImmutableList<String> {
|
fun getSelections(): ImmutableList<String> {
|
||||||
return tracker.getScoreList()
|
return tracker.getScoreList()
|
||||||
|
@ -816,7 +816,7 @@ private data class TrackerRemoveScreen(
|
||||||
|
|
||||||
fun deleteMangaFromService() {
|
fun deleteMangaFromService() {
|
||||||
screenModelScope.launchNonCancellable {
|
screenModelScope.launchNonCancellable {
|
||||||
(tracker as DeletableTracker).delete(track.toDbTrack())
|
(tracker as DeletableTracker).delete(track)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ data class DummyTracker(
|
||||||
|
|
||||||
override fun indexToScore(index: Int): Float = getScoreList()[index].toFloat()
|
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()
|
track.score.toString()
|
||||||
|
|
||||||
override suspend fun update(
|
override suspend fun update(
|
||||||
|
|
Loading…
Reference in a new issue