Skip to content

Commit

Permalink
prepare favorite toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Apr 25, 2024
1 parent 352c1df commit 623122b
Show file tree
Hide file tree
Showing 17 changed files with 219 additions and 37 deletions.
1 change: 1 addition & 0 deletions anilist/src/commonMain/graphql/AiringQuery.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ query AiringQuery(
media {
id,
idMal,
type,
status(version: $statusVersion),
description(asHtml: $html),
episodes,
Expand Down
4 changes: 3 additions & 1 deletion anilist/src/commonMain/graphql/CharacterQuery.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ query CharacterQuery($id: Int, $html: Boolean) {
month
day
},
bloodType
bloodType,
isFavourite,
isFavouriteBlocked,
}
}
1 change: 1 addition & 0 deletions anilist/src/commonMain/graphql/MediumQuery.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ query MediumQuery($id: Int, $statusVersion: Int, $html: Boolean) {
Media(id: $id) {
id,
idMal,
type,
status(version: $statusVersion),
description(asHtml: $html),
episodes,
Expand Down
1 change: 1 addition & 0 deletions anilist/src/commonMain/graphql/SeasonQuery.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ query SeasonQuery(
media(sort: $sort, seasonYear: $year, season: $season, genre_not_in: $preventGenres, type: $type, isAdult: $adultContent) {
id,
idMal,
type,
status(version: $statusVersion),
description(asHtml: $html),
episodes,
Expand Down
1 change: 1 addition & 0 deletions anilist/src/commonMain/graphql/TrendingQuery.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ query TrendingQuery(
) {
id,
idMal,
type,
status(version: $statusVersion),
description(asHtml: $html),
episodes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,22 @@ data class Character(
/**
* The character's birthdate
*/
val birthDate: Character.BirthDate?,
val birthDate: BirthDate?,

/**
* A general description of the character
*/
val description: String?,

/**
* If the character is marked as favourite by the currently authenticated user
*/
val isFavorite: Boolean,

/**
* If the character is blocked from being added to favourites
*/
val isFavoriteBlocked: Boolean
) {

@Serializable
Expand Down Expand Up @@ -223,7 +233,9 @@ data class Character(
gender = null,
bloodType = null,
birthDate = null,
description = null
description = null,
isFavorite = false,
isFavoriteBlocked = true
)
}

Expand All @@ -238,7 +250,9 @@ data class Character(
gender = null,
bloodType = null,
birthDate = null,
description = null
description = null,
isFavorite = false,
isFavoriteBlocked = true,
)
}

Expand All @@ -253,7 +267,9 @@ data class Character(
gender = character.gender?.ifBlank { null },
bloodType = character.bloodType?.ifBlank { null },
birthDate = character.dateOfBirth?.let { BirthDate(it) },
description = character.description?.ifBlank { null }
description = character.description?.ifBlank { null },
isFavorite = character.isFavourite,
isFavoriteBlocked = character.isFavouriteBlocked
)
}

Expand All @@ -268,7 +284,9 @@ data class Character(
gender = null,
bloodType = null,
birthDate = null,
description = null
description = null,
isFavorite = false,
isFavoriteBlocked = true
)
}

Expand All @@ -283,7 +301,9 @@ data class Character(
gender = null,
bloodType = null,
birthDate = null,
description = null
description = null,
isFavorite = false,
isFavoriteBlocked = true
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import dev.datlag.aniflow.anilist.common.lastMonth
import dev.datlag.aniflow.anilist.type.MediaFormat
import dev.datlag.aniflow.anilist.type.MediaRankType
import dev.datlag.aniflow.anilist.type.MediaStatus
import dev.datlag.aniflow.anilist.type.MediaType
import kotlinx.datetime.Month
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
Expand All @@ -14,6 +15,7 @@ import kotlinx.serialization.Transient
data class Medium(
val id: Int,
val idMal: Int? = null,
val type: MediaType = MediaType.UNKNOWN__,
val status: MediaStatus = MediaStatus.UNKNOWN__,
val description: String? = null,
val episodes: Int = -1,
Expand All @@ -23,18 +25,31 @@ data class Medium(
val genres: Set<String> = emptySet(),
val countryOfOrigin: String? = null,
val averageScore: Int = -1,
val title: Title,
val title: Title = Title(
english = null,
native = null,
romaji = null,
userPreferred = null
),
val bannerImage: String? = null,
val coverImage: CoverImage,
val coverImage: CoverImage = CoverImage(
medium = null,
large = null,
extraLarge = null,
color = null
),
val nextAiringEpisode: NextAiring? = null,
val ranking: Set<Ranking> = emptySet(),
private val _characters: Set<Character> = emptySet(),
val entry: Entry? = null,
val trailer: Trailer? = null
val trailer: Trailer? = null,
val isFavorite: Boolean = false,
private val _isFavoriteBlocked: Boolean = true
) {
constructor(trending: TrendingQuery.Medium) : this(
id = trending.id,
idMal = trending.idMal,
type = trending.type ?: MediaType.UNKNOWN__,
status = trending.status ?: MediaStatus.UNKNOWN__,
description = trending.description?.ifBlank { null },
episodes = trending.episodes ?: -1,
Expand Down Expand Up @@ -74,12 +89,15 @@ data class Medium(
thumbnail = thumbnail,
)
}
}
},
isFavorite = trending.isFavourite,
_isFavoriteBlocked = trending.isFavouriteBlocked
)

constructor(airing: AiringQuery.Media) : this(
id = airing.id,
idMal = airing.idMal,
type = airing.type ?: MediaType.UNKNOWN__,
status = airing.status ?: MediaStatus.UNKNOWN__,
description = airing.description?.ifBlank { null },
episodes = airing.episodes ?: -1,
Expand Down Expand Up @@ -119,12 +137,15 @@ data class Medium(
thumbnail = thumbnail,
)
}
}
},
isFavorite = airing.isFavourite,
_isFavoriteBlocked = airing.isFavouriteBlocked
)

constructor(season: SeasonQuery.Medium) : this(
id = season.id,
idMal = season.idMal,
type = season.type ?: MediaType.UNKNOWN__,
status = season.status ?: MediaStatus.UNKNOWN__,
description = season.description?.ifBlank { null },
episodes = season.episodes ?: -1,
Expand Down Expand Up @@ -164,12 +185,15 @@ data class Medium(
thumbnail = thumbnail,
)
}
}
},
isFavorite = season.isFavourite,
_isFavoriteBlocked = season.isFavouriteBlocked
)

constructor(query: MediumQuery.Media) : this(
id = query.id,
idMal = query.idMal,
type = query.type ?: MediaType.UNKNOWN__,
status = query.status ?: MediaStatus.UNKNOWN__,
description = query.description?.ifBlank { null },
episodes = query.episodes ?: -1,
Expand Down Expand Up @@ -209,7 +233,9 @@ data class Medium(
thumbnail = thumbnail
)
}
}
},
isFavorite = query.isFavourite,
_isFavoriteBlocked = query.isFavouriteBlocked
)

@Transient
Expand All @@ -220,6 +246,9 @@ data class Medium(
@Transient
val characters: Set<Character> = _characters.filterNot { it.id == 36309 }.toSet()

@Transient
val isFavoriteBlocked: Boolean = _isFavoriteBlocked || type == MediaType.UNKNOWN__

@Serializable
data class Title(
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,6 @@ fun SearchResponse.Result.AniList.asMedium(): Medium {
id = this.id,
idMal = this.idMal,
_isAdult = this.isAdult,
coverImage = Medium.CoverImage(
color = null,
medium = null,
large = null,
extraLarge = null
),
title = this.title.asMediumTitle()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ interface MediumComponent : ContentHolderComponent {
val rating: StateFlow<Int>
val alreadyAdded: StateFlow<Boolean>
val trailer: StateFlow<Medium.Trailer?>
val isFavorite: StateFlow<Boolean>
val isFavoriteBlocked: StateFlow<Boolean>

val bsAvailable: Boolean

Expand All @@ -47,4 +49,5 @@ interface MediumComponent : ContentHolderComponent {
fun rate(value: Int)
fun descriptionTranslation(text: String?)
fun showCharacter(character: Character)
fun toggleFavorite()
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ fun MediumScreen(component: MediumComponent) {
bannerImageFlow = component.bannerImage,
coverImage = coverImage,
titleFlow = component.title,
onBack = { component.back() }
isFavoriteFlow = component.isFavorite,
isFavoriteBlockedFlow = component.isFavoriteBlocked,
onBack = { component.back() },
onToggleFavorite = { component.toggleFavorite() }
)
},
floatingActionButton = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,32 @@ class MediumScreenComponent(
initialValue = initialMedium.entry != null
)

private val changedFavorite = MutableStateFlow<Boolean?>(null)
override val isFavorite: StateFlow<Boolean> = combine(
mediumSuccessState.mapNotNull {
it?.data?.isFavorite
}.flowOn(ioDispatcher()),
changedFavorite
) { default, changed ->
changed ?: default
}.flowOn(
context = ioDispatcher()
).stateIn(
scope = ioScope(),
started = SharingStarted.WhileSubscribed(),
initialValue = initialMedium.isFavorite
)

override val isFavoriteBlocked: StateFlow<Boolean> = mediumSuccessState.mapNotNull {
it?.data?.isFavoriteBlocked
}.flowOn(
context = ioDispatcher()
).stateIn(
scope = ioScope(),
started = SharingStarted.WhileSubscribed(),
initialValue = initialMedium.isFavoriteBlocked
)

private val userSettings by di.instance<Settings.PlatformUserSettings>()
private val characterStateMachine by di.instance<CharacterStateMachine>()
private val burningSeriesResolver by di.instance<BurningSeriesResolver>()
Expand Down Expand Up @@ -426,4 +452,13 @@ class MediumScreenComponent(
override fun showCharacter(character: Character) {
dialogNavigation.activate(DialogConfig.Character(character))
}

override fun toggleFavorite() {
launchIO {
changedFavorite.update {
!(it ?: isFavorite.saveFirstOrNull() ?: isFavorite.value)
}
// Call toggle on api
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBackIosNew
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
Expand Down Expand Up @@ -41,7 +43,10 @@ fun CollapsingToolbar(
bannerImageFlow: StateFlow<String?>,
coverImage: Medium.CoverImage,
titleFlow: StateFlow<Medium.Title>,
onBack: () -> Unit
isFavoriteFlow: StateFlow<Boolean>,
isFavoriteBlockedFlow: StateFlow<Boolean>,
onBack: () -> Unit,
onToggleFavorite: () -> Unit
) {
Box(
modifier = Modifier.fillMaxWidth()
Expand Down Expand Up @@ -131,6 +136,30 @@ fun CollapsingToolbar(
}
}
},
actions = {
val isFavoriteBlocked by isFavoriteBlockedFlow.collectAsStateWithLifecycle()

IconButton(
modifier = if (isCollapsed) {
Modifier
} else {
Modifier.background(MaterialTheme.colorScheme.surface.copy(alpha = 0.75F), CircleShape)
},
onClick = onToggleFavorite,
enabled = !isFavoriteBlocked
) {
val isFavorite by isFavoriteFlow.collectAsStateWithLifecycle()

Icon(
imageVector = if (isFavorite) {
Icons.Default.Favorite
} else {
Icons.Default.FavoriteBorder
},
contentDescription = null
)
}
},
scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors(
containerColor = Color.Transparent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ interface CharacterComponent : DialogComponent {
val birthDate: StateFlow<Character.BirthDate?>
val description: StateFlow<String?>
val translatedDescription: StateFlow<String?>
val isFavorite: StateFlow<Boolean>
val isFavoriteBlocked: StateFlow<Boolean>

fun descriptionTranslation(text: String?)
fun retry()
fun toggleFavorite()
}
Loading

0 comments on commit 623122b

Please sign in to comment.