mirror of
https://github.com/Suwayomi/Tachidesk.git
synced 2025-12-10 06:42:07 +01:00
feat(kosync): add mutations for manual progress push and pull (#1625)
Exposes the existing push and pull functionality from the KoreaderSyncService via the GraphQL API. This change introduces two new mutations: - `pushKoSyncProgress`: Manually sends the current chapter's reading progress to the KOReader sync server. - `pullKoSyncProgress`: Manually fetches and applies the latest reading progress from the KOReader sync server. These mutations enable clients and WebUIs to implement manual sync triggers, providing users with more direct control over their reading progress synchronization, similar to the functionality offered by the official KOReader plugin and other clients like Readest.
This commit is contained in:
@@ -1,14 +1,21 @@
|
|||||||
package suwayomi.tachidesk.graphql.mutations
|
package suwayomi.tachidesk.graphql.mutations
|
||||||
|
|
||||||
|
import graphql.execution.DataFetcherResult
|
||||||
import graphql.schema.DataFetchingEnvironment
|
import graphql.schema.DataFetchingEnvironment
|
||||||
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.sql.update
|
||||||
|
import suwayomi.tachidesk.graphql.asDataFetcherResult
|
||||||
import suwayomi.tachidesk.graphql.server.getAttribute
|
import suwayomi.tachidesk.graphql.server.getAttribute
|
||||||
|
import suwayomi.tachidesk.graphql.types.ChapterType
|
||||||
import suwayomi.tachidesk.graphql.types.KoSyncConnectPayload
|
import suwayomi.tachidesk.graphql.types.KoSyncConnectPayload
|
||||||
import suwayomi.tachidesk.graphql.types.LogoutKoSyncAccountPayload
|
import suwayomi.tachidesk.graphql.types.LogoutKoSyncAccountPayload
|
||||||
import suwayomi.tachidesk.graphql.types.SettingsType
|
import suwayomi.tachidesk.graphql.types.SettingsType
|
||||||
|
import suwayomi.tachidesk.graphql.types.SyncConflictInfoType
|
||||||
import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService
|
import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService
|
||||||
|
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
|
||||||
import suwayomi.tachidesk.server.user.requireUser
|
import suwayomi.tachidesk.server.user.requireUser
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
@@ -53,4 +60,100 @@ class KoreaderSyncMutation {
|
|||||||
settings = SettingsType(),
|
settings = SettingsType(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class PushKoSyncProgressInput(
|
||||||
|
val clientMutationId: String? = null,
|
||||||
|
val chapterId: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class PushKoSyncProgressPayload(
|
||||||
|
val clientMutationId: String?,
|
||||||
|
val success: Boolean,
|
||||||
|
val chapter: ChapterType?,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun pushKoSyncProgress(
|
||||||
|
dataFetchingEnvironment: DataFetchingEnvironment,
|
||||||
|
input: PushKoSyncProgressInput,
|
||||||
|
): CompletableFuture<DataFetcherResult<PushKoSyncProgressPayload?>> =
|
||||||
|
future {
|
||||||
|
asDataFetcherResult {
|
||||||
|
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
|
||||||
|
|
||||||
|
KoreaderSyncService.pushProgress(input.chapterId)
|
||||||
|
|
||||||
|
val chapter =
|
||||||
|
transaction {
|
||||||
|
ChapterTable
|
||||||
|
.selectAll()
|
||||||
|
.where { ChapterTable.id eq input.chapterId }
|
||||||
|
.firstOrNull()
|
||||||
|
?.let { ChapterType(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
PushKoSyncProgressPayload(
|
||||||
|
clientMutationId = input.clientMutationId,
|
||||||
|
success = true,
|
||||||
|
chapter = chapter,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class PullKoSyncProgressInput(
|
||||||
|
val clientMutationId: String? = null,
|
||||||
|
val chapterId: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class PullKoSyncProgressPayload(
|
||||||
|
val clientMutationId: String?,
|
||||||
|
val chapter: ChapterType?,
|
||||||
|
val syncConflict: SyncConflictInfoType?,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun pullKoSyncProgress(
|
||||||
|
dataFetchingEnvironment: DataFetchingEnvironment,
|
||||||
|
input: PullKoSyncProgressInput,
|
||||||
|
): CompletableFuture<DataFetcherResult<PullKoSyncProgressPayload?>> =
|
||||||
|
future {
|
||||||
|
asDataFetcherResult {
|
||||||
|
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
|
||||||
|
|
||||||
|
val syncResult = KoreaderSyncService.checkAndPullProgress(input.chapterId)
|
||||||
|
var syncConflictInfo: SyncConflictInfoType? = null
|
||||||
|
|
||||||
|
if (syncResult != null) {
|
||||||
|
if (syncResult.isConflict) {
|
||||||
|
syncConflictInfo =
|
||||||
|
SyncConflictInfoType(
|
||||||
|
deviceName = syncResult.device,
|
||||||
|
remotePage = syncResult.pageRead,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncResult.shouldUpdate) {
|
||||||
|
transaction {
|
||||||
|
ChapterTable.update({ ChapterTable.id eq input.chapterId }) {
|
||||||
|
it[lastPageRead] = syncResult.pageRead
|
||||||
|
it[lastReadAt] = syncResult.timestamp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val chapter =
|
||||||
|
transaction {
|
||||||
|
ChapterTable
|
||||||
|
.selectAll()
|
||||||
|
.where { ChapterTable.id eq input.chapterId }
|
||||||
|
.firstOrNull()
|
||||||
|
?.let { ChapterType(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
PullKoSyncProgressPayload(
|
||||||
|
clientMutationId = input.clientMutationId,
|
||||||
|
chapter = chapter,
|
||||||
|
syncConflict = syncConflictInfo,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user