Skip to content

Commit

Permalink
feat: improve non-nullables in responses
Browse files Browse the repository at this point in the history
  • Loading branch information
alvr committed Apr 22, 2024
1 parent 674da5e commit 1f5ba84
Show file tree
Hide file tree
Showing 20 changed files with 115 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ internal class KatanaMultiplatformDataRemotePlugin : Plugin<Project> {
context(Project)
private fun ApolloExtension.configureApollo() {
service("anilist") {
decapitalizeFields = true
generateAsInternal = true
packageName = fullPackageName
generateMethods = listOf("equalsHashCode")
generateOptionalOperationVariables = false
packageName = fullPackageName
warnOnDeprecatedUsages = true

if (path == CORE_PROJECT) {
generateApolloMetadata = true
Expand Down
4 changes: 2 additions & 2 deletions common/user/data/src/commonMain/graphql/QueryUserId.graphql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
query UserIdQuery {
viewer: Viewer {
id
Viewer @nonnull {
id @nonnull
}
}
8 changes: 4 additions & 4 deletions common/user/data/src/commonMain/graphql/QueryUserInfo.graphql
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
query UserInfoQuery {
user: Viewer {
name
avatar {
medium
Viewer @nonnull {
name @nonnull
avatar @nonnull {
large @nonnull
}
bannerImage
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package dev.alvr.katana.common.user.data.mappers.responses
import dev.alvr.katana.common.user.data.UserIdQuery
import dev.alvr.katana.common.user.domain.models.UserId

internal operator fun UserIdQuery.Data?.invoke(): UserId = UserId(
id = checkNotNull(this?.viewer?.id) { "ViewerId is required." },
internal operator fun UserIdQuery.Data.invoke(): UserId = UserId(
id = viewer.id,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package dev.alvr.katana.common.user.data.mappers.responses
import dev.alvr.katana.common.user.data.UserInfoQuery
import dev.alvr.katana.common.user.domain.models.UserInfo

internal operator fun UserInfoQuery.Data?.invoke() = UserInfo(
username = this?.user?.name.orEmpty(),
avatar = this?.user?.avatar?.medium.orEmpty(),
banner = this?.user?.bannerImage.orEmpty(),
internal operator fun UserInfoQuery.Data.invoke() = UserInfo(
username = viewer.name,
avatar = viewer.avatar.large,
banner = viewer.bannerImage,
)
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ internal class UserIdRemoteSourceImpl(
.query(UserIdQuery())
.fetchPolicy(policy)
.execute()
.data()
.dataAssertNoErrors()
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal class UserInfoRemoteSourceImpl(
client.query(UserInfoQuery())
.fetchPolicy(FetchPolicy.CacheAndNetwork)
.watch()
.map { res -> res.data().right() as Either<Failure, UserInfo> }
.map { res -> res.dataAssertNoErrors().right() as Either<Failure, UserInfo> }
.catch { error ->
Logger.e(error) { "Was not possible to get the user info" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package dev.alvr.katana.common.user.domain.models
data class UserInfo(
val username: String,
val avatar: String,
val banner: String,
val banner: String?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import com.apollographql.apollo3.exception.ApolloHttpException
import com.apollographql.apollo3.exception.ApolloNetworkException
import com.apollographql.apollo3.exception.ApolloParseException
import com.apollographql.apollo3.exception.CacheMissException
import com.apollographql.apollo3.exception.DefaultApolloException
import com.apollographql.apollo3.exception.HttpCacheMissException
import com.apollographql.apollo3.exception.JsonDataException
import com.apollographql.apollo3.exception.JsonEncodingException
import com.apollographql.apollo3.exception.NoDataException
import dev.alvr.katana.core.domain.failures.Failure

fun <A, B> Either<A, B>.optional() = Optional.presentIfNotNull(getOrNull())
Expand All @@ -20,11 +22,13 @@ fun Throwable.toFailure(
unknown: Failure = Failure.Unknown,
): Failure = when (this) {
is ApolloHttpException,
is ApolloNetworkException -> network
is ApolloNetworkException,
is DefaultApolloException -> network
is CacheMissException,
is HttpCacheMissException -> cache
is ApolloParseException,
is JsonDataException,
is JsonEncodingException -> response
is JsonEncodingException,
is NoDataException -> response
else -> unknown
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import dev.alvr.katana.core.common.empty
internal data class UserInfoUi(
val username: String = String.empty,
val avatar: String = String.empty,
val banner: String = String.empty,
val banner: String? = null,
)
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
fragment MediaEntry on Media {
id
title {
userPreferred
fragment mediaEntry on Media {
id @nonnull
title @nonnull {
userPreferred @nonnull
}
episodes
chapters
volumes
format
coverImage {
large
coverImage @nonnull {
large @nonnull
}
nextAiringEpisode {
airingAt
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
fragment MediaListEntry on MediaList {
id
score
fragment mediaListEntry on MediaList {
id @nonnull
score @nonnull
progress
progressVolumes
repeat
private
notes
hiddenFromStatusLists
updatedAt
startedAt {
year
month
Expand All @@ -17,5 +18,7 @@ fragment MediaListEntry on MediaList {
month
day
}
updatedAt
media @nonnull {
...mediaEntry
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mutation MediaListEntries(
hiddenFromStatusLists: $hiddenFromStatusLists,
startedAt: $startedAt,
completedAt: $completedAt,
) {
...MediaListEntry
) @nonnull {
...mediaListEntry
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
query MediaListCollection($user: Int, $type: MediaType!) {
collection: MediaListCollection(userId: $user, type: $type) @nonnull {
MediaListCollection(userId: $user, type: $type) @nonnull {
lists @nonnull {
name @nonnull
entries @nonnull {
...MediaListEntry
media @nonnull {
...MediaEntry
}
...mediaListEntry
}
name
}
user {
mediaListOptions {
animeList {
sectionOrder
user @nonnull {
mediaListOptions @nonnull {
animeList @nonnull {
sectionOrder @nonnull
}
mangaList {
sectionOrder
mangaList @nonnull {
sectionOrder @nonnull
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package dev.alvr.katana.features.lists.data.mappers.requests

import com.apollographql.apollo3.api.Optional
import dev.alvr.katana.features.lists.data.MediaListEntriesMutation
import dev.alvr.katana.features.lists.domain.models.lists.MediaList

internal fun MediaList.toMutation() = MediaListEntriesMutation(
id = id,
score = Optional.presentIfNotNull(score),
progress = Optional.presentIfNotNull(progress),
progressVolumes = Optional.presentIfNotNull(progressVolumes),
repeat = Optional.presentIfNotNull(repeat),
private = Optional.presentIfNotNull(private),
notes = Optional.presentIfNotNull(notes),
hiddenFromStatusLists = Optional.presentIfNotNull(hiddenFromStatusLists),
startedAt = Optional.presentIfNotNull(startedAt.toFuzzyDate().takeIfValid()),
completedAt = Optional.presentIfNotNull(completedAt.toFuzzyDate().takeIfValid()),
score = score,
progress = progress,
progressVolumes = progressVolumes,
repeat = repeat,
private = private,
notes = notes,
hiddenFromStatusLists = hiddenFromStatusLists,
startedAt = startedAt.toFuzzyDate().takeIfValid(),
completedAt = completedAt.toFuzzyDate().takeIfValid(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ package dev.alvr.katana.features.lists.data.mappers.responses
import dev.alvr.katana.features.lists.domain.models.entries.MediaEntry
import dev.alvr.katana.features.lists.data.fragment.MediaEntry as MediaEntryFragment

internal fun MediaEntryFragment?.animeEntry() = let { entry ->
MediaEntry.Anime(
entry = mediaEntry(),
episodes = entry?.episodes,
nextEpisode = entry?.nextAiringEpisode?.let { next ->
MediaEntry.Anime.NextEpisode(
number = next.episode,
at = next.airingAt.toLocalDateTime(),
)
},
)
}
internal fun MediaEntryFragment.animeEntry() = MediaEntry.Anime(
entry = mediaEntry(),
episodes = episodes,
nextEpisode = nextAiringEpisode?.let { next ->
MediaEntry.Anime.NextEpisode(
number = next.episode,
at = next.airingAt.toLocalDateTime(),
)
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package dev.alvr.katana.features.lists.data.mappers.responses
import dev.alvr.katana.features.lists.domain.models.entries.MediaEntry
import dev.alvr.katana.features.lists.data.fragment.MediaEntry as MediaEntryFragment

internal fun MediaEntryFragment?.mangaEntry() = let { entry ->
MediaEntry.Manga(
entry = mediaEntry(),
chapters = entry?.chapters,
volumes = entry?.volumes,
)
}
internal fun MediaEntryFragment.mangaEntry() = MediaEntry.Manga(
entry = mediaEntry(),
chapters = chapters,
volumes = volumes,
)
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package dev.alvr.katana.features.lists.data.mappers.responses

import dev.alvr.katana.core.common.orZero
import dev.alvr.katana.core.remote.type.MediaFormat
import dev.alvr.katana.features.lists.domain.models.entries.CommonMediaEntry
import dev.alvr.katana.features.lists.data.fragment.MediaEntry as MediaEntryFragment

internal fun MediaEntryFragment?.mediaEntry() = let { entry ->
internal fun MediaEntryFragment.mediaEntry() = let { entry ->
CommonMediaEntry(
id = entry?.id.orZero(),
title = entry?.title?.userPreferred.orEmpty(),
coverImage = entry?.coverImage?.large.orEmpty(),
format = entry?.format.toFormat(),
id = entry.id,
title = entry.title.userPreferred,
coverImage = entry.coverImage.large,
format = entry.format.toFormat(),
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.alvr.katana.features.lists.data.mappers.responses

import dev.alvr.katana.core.common.orZero
import dev.alvr.katana.core.common.zero
import dev.alvr.katana.core.remote.type.MediaType
import dev.alvr.katana.features.lists.data.MediaListCollectionQuery
import dev.alvr.katana.features.lists.domain.models.entries.MediaEntry
Expand All @@ -9,40 +10,35 @@ import dev.alvr.katana.features.lists.domain.models.lists.MediaListEntry
import dev.alvr.katana.features.lists.domain.models.lists.MediaListGroup
import dev.alvr.katana.features.lists.data.fragment.MediaEntry as MediaEntryFragment

internal fun <T : MediaEntry> MediaListCollectionQuery.Data.mediaList(type: MediaType): List<MediaListGroup<T>> =
collection.lists.asSequence().map { list ->
val entries = list?.entries.orEmpty().asSequence().mapNotNull { entry ->
entry?.toModel<T>(type)
}.toList()

internal operator fun <T : MediaEntry> MediaListCollectionQuery.Data.invoke(type: MediaType): List<MediaListGroup<T>> =
mediaListCollection.listsFilterNotNull().map { list ->
MediaListGroup(
name = list?.name.orEmpty(),
entries = entries,
name = list.name,
entries = list.entriesFilterNotNull().map { entry -> entry.toModel<T>(type) }.toList(),
)
}.sortedBy { sortLists(type, it.name) }.toList()
}.sortedBy { sortLists(type, it.name) }

@Suppress("UNCHECKED_CAST")
private fun <T : MediaEntry> MediaListCollectionQuery.Entry.toModel(type: MediaType) =
mediaListEntry.let { entry ->
val list = MediaList(
id = entry.id,
score = entry.score.orZero(),
progress = entry.progress.orZero(),
progressVolumes = entry.progressVolumes,
repeat = entry.repeat.orZero(),
private = entry.private ?: false,
notes = entry.notes.orEmpty(),
hiddenFromStatusLists = entry.hiddenFromStatusLists ?: false,
startedAt = entry.startedAt?.let { date ->
dateMapper(date.day, date.month, date.year)
},
completedAt = entry.completedAt?.let { date ->
dateMapper(date.day, date.month, date.year)
},
updatedAt = entry.updatedAt?.toLocalDateTime(),
)
with(mediaListEntry) {
MediaListEntry(
list = list,
list = MediaList(
id = id,
score = score,
progress = progress.orZero(),
progressVolumes = progressVolumes,
repeat = repeat.orZero(),
private = private ?: false,
notes = notes.orEmpty(),
hiddenFromStatusLists = hiddenFromStatusLists ?: false,
startedAt = startedAt?.let { date ->
dateMapper(date.day, date.month, date.year)
},
completedAt = completedAt?.let { date ->
dateMapper(date.day, date.month, date.year)
},
updatedAt = updatedAt?.toLocalDateTime(),
),
entry = media.mediaEntry.toMedia(type) as T,
)
}
Expand All @@ -53,15 +49,12 @@ private fun MediaEntryFragment.toMedia(type: MediaType) = type.onMediaEntry(
)

private fun MediaListCollectionQuery.Data.sortLists(type: MediaType, listName: String) =
with(collection.user?.mediaListOptions) {
with(mediaListCollection.user.mediaListOptions) {
type.onMediaEntry(
anime = { this?.animeList?.sectionOrder.orEmpty().listPosition(listName) },
manga = { this?.mangaList?.sectionOrder.orEmpty().listPosition(listName) },
anime = { animeList.sectionOrder.listPosition(listName) },
manga = { mangaList.sectionOrder.listPosition(listName) },
)
}

private fun List<String?>.listPosition(listName: String) = if (listName.isEmpty()) {
size
} else {
indexOf(listName)
}
private fun List<String?>.listPosition(listName: String) =
indexOf(listName).takeIf { it >= Int.zero } ?: size
Loading

0 comments on commit 1f5ba84

Please sign in to comment.