Skip to content

Commit

Permalink
Add graphql mutation for library progress updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Drumber committed Dec 28, 2024
1 parent ab36131 commit 784a793
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fragment LibraryEntryWithNextUnitFragment on LibraryEntry {
...LibraryEntryFragment
nextUnit {
id
number
thumbnail {
original {
url
}
}
titles {
...TitlesFragment
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mutation UpdateLibraryEntryProgress($entryId: ID!, $progress: Int!) {
libraryEntry {
updateProgressById(input: { id: $entryId, progress: $progress }) {
libraryEntry {
...LibraryEntryWithNextUnitFragment
}
}
}
}
14 changes: 1 addition & 13 deletions app/src/main/graphql/query/GetLibraryEntriesWithNextUnit.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,7 @@ query GetLibraryEntriesWithNextUnit(
}
) {
nodes {
...LibraryEntryFragment
nextUnit {
id
number
thumbnail {
original {
url
}
}
titles {
...TitlesFragment
}
}
...LibraryEntryWithNextUnitFragment
}
pageInfo {
hasNextPage
Expand Down
Original file line number Diff line number Diff line change
@@ -1,67 +1,10 @@
package io.github.drumber.kitsune.data.mapper.graphql

import io.github.drumber.kitsune.data.common.Image
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntryWithModification
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntryWithModificationAndNextUnit
import io.github.drumber.kitsune.data.presentation.model.media.unit.Chapter
import io.github.drumber.kitsune.data.presentation.model.media.unit.Episode
import io.github.drumber.kitsune.data.source.graphql.GetLibraryEntriesWithNextUnitQuery

fun GetLibraryEntriesWithNextUnitQuery.All.toLibraryEntriesWithModificationAndNextUnit() = nodes
fun GetLibraryEntriesWithNextUnitQuery.All.toLibraryEntriesWithNextUnit() = nodes
?.filterNotNull()
?.map(GetLibraryEntriesWithNextUnitQuery.Node::toLibraryEntriesWithModificationAndNextUnit)
?.map(GetLibraryEntriesWithNextUnitQuery.Node::toLibraryEntryWithNextUnit)

fun GetLibraryEntriesWithNextUnitQuery.Node.toLibraryEntriesWithModificationAndNextUnit() =
LibraryEntryWithModificationAndNextUnit(
LibraryEntryWithModification(
libraryEntryFragment.toLibraryEntry(),
null
),
nextUnit?.toMediaUnit(libraryEntryFragment.media.libraryMediaFragment.type)
)

fun GetLibraryEntriesWithNextUnitQuery.NextUnit.toMediaUnit(mediaType: String) =
when (mediaType) {
"Anime" -> toEpisode()
"Manga" -> toChapter()
else -> null
}

fun GetLibraryEntriesWithNextUnitQuery.NextUnit.toEpisode() = Episode(
id = id,
description = null,
titles = titles.titlesFragment.toTitles(),
canonicalTitle = titles.titlesFragment.canonical,
number = number,
seasonNumber = null,
relativeNumber = null,
length = null,
airdate = null,
thumbnail = Image(
tiny = null,
small = null,
medium = null,
large = null,
original = thumbnail?.original?.url,
meta = null
)
)

fun GetLibraryEntriesWithNextUnitQuery.NextUnit.toChapter() = Chapter(
id = id,
description = null,
titles = titles.titlesFragment.toTitles(),
canonicalTitle = titles.titlesFragment.canonical,
number = number,
volumeNumber = null,
length = null,
thumbnail = Image(
tiny = null,
small = null,
medium = null,
large = null,
original = thumbnail?.original?.url,
meta = null
),
published = null
)
fun GetLibraryEntriesWithNextUnitQuery.Node.toLibraryEntryWithNextUnit() =
libraryEntryWithNextUnitFragment.toLibraryEntryWithNextUnit()
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.github.drumber.kitsune.data.mapper.graphql

import io.github.drumber.kitsune.data.common.Image
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntryWithNextUnit
import io.github.drumber.kitsune.data.presentation.model.media.unit.Chapter
import io.github.drumber.kitsune.data.presentation.model.media.unit.Episode
import io.github.drumber.kitsune.data.source.graphql.fragment.LibraryEntryWithNextUnitFragment

fun LibraryEntryWithNextUnitFragment.toLibraryEntryWithNextUnit() = LibraryEntryWithNextUnit(
libraryEntry = libraryEntryFragment.toLibraryEntry(),
nextUnit = nextUnit?.toMediaUnit(libraryEntryFragment.media.libraryMediaFragment.type)
)

fun LibraryEntryWithNextUnitFragment.NextUnit.toMediaUnit(mediaType: String) =
when (mediaType) {
"Anime" -> toEpisode()
"Manga" -> toChapter()
else -> null
}

fun LibraryEntryWithNextUnitFragment.NextUnit.toEpisode() = Episode(
id = id,
description = null,
titles = titles.titlesFragment.toTitles(),
canonicalTitle = titles.titlesFragment.canonical,
number = number,
seasonNumber = null,
relativeNumber = null,
length = null,
airdate = null,
thumbnail = Image(
tiny = null,
small = null,
medium = null,
large = null,
original = thumbnail?.original?.url,
meta = null
)
)

fun LibraryEntryWithNextUnitFragment.NextUnit.toChapter() = Chapter(
id = id,
description = null,
titles = titles.titlesFragment.toTitles(),
canonicalTitle = titles.titlesFragment.canonical,
number = number,
volumeNumber = null,
length = null,
thumbnail = Image(
tiny = null,
small = null,
medium = null,
large = null,
original = thumbnail?.original?.url,
meta = null
),
published = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.github.drumber.kitsune.data.presentation.model.library

import io.github.drumber.kitsune.data.presentation.model.media.unit.MediaUnit

data class LibraryEntryWithNextUnit(
val libraryEntry: LibraryEntry,
val nextUnit: MediaUnit?
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import androidx.paging.RemoteMediator
import io.github.drumber.kitsune.data.common.exception.NoDataException
import io.github.drumber.kitsune.data.common.library.LibraryFilterOptions
import io.github.drumber.kitsune.data.mapper.LibraryMapper.toLocalLibraryEntry
import io.github.drumber.kitsune.data.mapper.graphql.toLibraryEntriesWithModificationAndNextUnit
import io.github.drumber.kitsune.data.mapper.graphql.toLibraryEntriesWithNextUnit
import io.github.drumber.kitsune.data.mapper.graphql.toLocalNextMediaUnit
import io.github.drumber.kitsune.data.source.graphql.library.LibraryApolloDataSource
import io.github.drumber.kitsune.data.source.local.library.LibraryLocalDataSource
Expand Down Expand Up @@ -46,7 +46,7 @@ class LibraryEntryWithNextMediaUnitRemoteMediator(
) ?: throw NoDataException("Received data is 'null'.")

val pageInfo = pageData.pageInfo
val data = pageData.toLibraryEntriesWithModificationAndNextUnit()
val data = pageData.toLibraryEntriesWithNextUnit()
?: throw NoDataException("Received data is 'null'.")

localDataSource.runDatabaseTransaction {
Expand All @@ -55,14 +55,14 @@ class LibraryEntryWithNextMediaUnitRemoteMediator(
}

data.forEach {
localDataSource.insertLibraryEntryIfUpdatedAtIsNewer(it.libraryEntryWithModification.libraryEntry.toLocalLibraryEntry())
localDataSource.insertLibraryEntryIfUpdatedAtIsNewer(it.libraryEntry.toLocalLibraryEntry())
if (it.nextUnit != null) {
localDataSource.insertNextMediaUnit(it.nextUnit.toLocalNextMediaUnit(it.libraryEntryWithModification.id))
localDataSource.insertNextMediaUnit(it.nextUnit.toLocalNextMediaUnit(it.libraryEntry.id))
}
}

val remoteKeys = data
.map { it.libraryEntryWithModification.libraryEntry.toLocalLibraryEntry() }
.map { it.libraryEntry.toLocalLibraryEntry() }
.map {
RemoteKeyEntity(
it.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import io.github.drumber.kitsune.data.mapper.LibraryMapper.toLocalLibraryEntryMo
import io.github.drumber.kitsune.data.mapper.LibraryMapper.toLocalLibraryModificationState
import io.github.drumber.kitsune.data.mapper.LibraryMapper.toLocalLibraryStatus
import io.github.drumber.kitsune.data.mapper.LibraryMapper.toNetworkLibraryStatus
import io.github.drumber.kitsune.data.mapper.graphql.toLibraryEntryWithNextUnit
import io.github.drumber.kitsune.data.mapper.graphql.toLocalNextMediaUnit
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntry
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntryFilter
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntryModification
Expand All @@ -22,6 +24,7 @@ import io.github.drumber.kitsune.data.presentation.model.library.LibraryStatus
import io.github.drumber.kitsune.data.presentation.model.media.Anime
import io.github.drumber.kitsune.data.presentation.model.media.Manga
import io.github.drumber.kitsune.data.presentation.model.media.Media
import io.github.drumber.kitsune.data.source.graphql.library.LibraryApolloDataSource
import io.github.drumber.kitsune.data.source.local.library.LibraryLocalDataSource
import io.github.drumber.kitsune.data.source.local.library.model.LocalLibraryEntry
import io.github.drumber.kitsune.data.source.local.library.model.LocalLibraryEntryModification
Expand All @@ -37,6 +40,7 @@ import retrofit2.HttpException

class LibraryRepository(
private val remoteLibraryDataSource: LibraryNetworkDataSource,
private val apolloLibraryDataSource: LibraryApolloDataSource,
private val localLibraryDataSource: LibraryLocalDataSource,
private val libraryChangeListener: LibraryChangeListener,
private val coroutineScope: CoroutineScope
Expand Down Expand Up @@ -137,6 +141,52 @@ class LibraryRepository(
}
}

suspend fun updateLibraryEntryProgress(libraryEntryId: String, progress: Int): LibraryEntry {
val modification = LibraryEntryModification.withIdAndNulls(libraryEntryId).copy(
progress = progress,
state = LibraryModificationState.SYNCHRONIZING
)
var libraryEntry: LibraryEntry? = null

return try {
coroutineScope.async {
localLibraryDataSource.insertLibraryEntryModification(modification.toLocalLibraryEntryModification())
}.await()

val updatedLibraryEntryWithNextUnit =
apolloLibraryDataSource.updateProgress(libraryEntryId, progress)
?.toLibraryEntryWithNextUnit()
?: throw NoDataException("Received library entry for ID '${libraryEntryId}' is 'null'.")
coroutineScope.async {
if (isLibraryEntryNotOlderThanInDatabase(updatedLibraryEntryWithNextUnit.libraryEntry.toLocalLibraryEntry())) {
localLibraryDataSource.updateLibraryEntryAndDeleteModification(
updatedLibraryEntryWithNextUnit.libraryEntry.toLocalLibraryEntry(),
modification.toLocalLibraryEntryModification()
)
}
if (updatedLibraryEntryWithNextUnit.nextUnit != null) {
localLibraryDataSource.insertNextMediaUnit(
updatedLibraryEntryWithNextUnit.nextUnit.toLocalNextMediaUnit(
libraryEntryId
)
)
}
}.await()
updatedLibraryEntryWithNextUnit.libraryEntry.also { libraryEntry = it }
} catch (e: NotFoundException) {
localLibraryDataSource.deleteLibraryEntryAndAnyModification(modification.id)
throw e
} catch (e: Exception) {
insertLocalModificationOrDeleteIfSameAsLibraryEntry(
modification.copy(state = LibraryModificationState.NOT_SYNCHRONIZED)
.toLocalLibraryEntryModification()
)
throw e
} finally {
libraryChangeListener.onUpdateLibraryEntry(modification, libraryEntry)
}
}

suspend fun fetchAndStoreLibraryEntryForMedia(userId: String, media: Media): LibraryEntry? {
val requestFilter = filterForFullLibraryEntry.copy()
.filter("user_id", userId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import io.github.drumber.kitsune.data.mapper.graphql.toMediaTypeEnum
import io.github.drumber.kitsune.data.mapper.graphql.toSortDirection
import io.github.drumber.kitsune.data.presentation.model.library.LibraryStatus
import io.github.drumber.kitsune.data.source.graphql.GetLibraryEntriesWithNextUnitQuery
import io.github.drumber.kitsune.data.source.graphql.UpdateLibraryEntryProgressMutation
import io.github.drumber.kitsune.data.source.graphql.fragment.LibraryEntryWithNextUnitFragment
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

Expand All @@ -34,4 +36,15 @@ class LibraryApolloDataSource(
).execute().data?.currentProfile?.library?.all
}
}

suspend fun updateProgress(
libraryEntryId: String,
progress: Int
): LibraryEntryWithNextUnitFragment? {
return withContext(Dispatchers.IO) {
val mutation = UpdateLibraryEntryProgressMutation(libraryEntryId, progress)
client.mutation(mutation)
.execute().data?.libraryEntry?.updateProgressById?.libraryEntry?.libraryEntryWithNextUnitFragment
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ val dataModule = module {
get(),
get(),
get(),
get(),
CoroutineScope(SupervisorJob() + Dispatchers.Default)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ val domainModule = module {
factory { GetLibraryEntriesWithModificationsPagerUseCase(get(), get()) }
factory { SearchLibraryEntriesWithLocalModificationsPagerUseCase(get(), get()) }
factory { SynchronizeLocalLibraryModificationsUseCase(get(), get()) }
factory { UpdateLibraryEntryProgressUseCase(get()) }
factory { UpdateLibraryEntryProgressUseCase(get(), get()) }
factory { UpdateLibraryEntryRatingUseCase(get()) }
factory { UpdateLibraryEntryUseCase(get()) }
factory { FetchLibraryEntriesForWidgetUseCase(get(), get()) }
Expand Down
Loading

0 comments on commit 784a793

Please sign in to comment.