Skip to content

Commit

Permalink
added list info
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed May 17, 2024
1 parent e160b5e commit 789eadf
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.api.Optional
import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.anilist.model.User
import dev.datlag.aniflow.anilist.type.MediaListSort
import dev.datlag.aniflow.anilist.type.MediaType
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
Expand All @@ -17,6 +18,7 @@ class ListRepository(

private val page = MutableStateFlow(0)
private val _type = MutableStateFlow(MediaType.UNKNOWN__)
private val sort = MutableStateFlow(MediaListSort.UPDATED_TIME_DESC)

@OptIn(ExperimentalCoroutinesApi::class)
private val type = _type.transformLatest {
Expand All @@ -36,12 +38,14 @@ class ListRepository(
private val query = combine(
page,
type,
sort,
user.filterNotNull().distinctUntilChanged(),
) { p, t, u ->
) { p, t, s, u ->
Query(
page = p,
type = t,
userId = u.id
userId = u.id,
sort = s
)
}

Expand Down Expand Up @@ -86,7 +90,8 @@ class ListRepository(
private data class Query(
val page: Int,
val type: MediaType,
val userId: Int
val userId: Int,
val sort: MediaListSort
) {
fun toGraphQL() = ListQuery(
page = Optional.present(page),
Expand All @@ -95,7 +100,12 @@ class ListRepository(
} else {
Optional.present(type)
},
userId = Optional.present(userId)
userId = Optional.present(userId),
sort = if (sort == MediaListSort.UNKNOWN__) {
Optional.absent()
} else {
Optional.present(listOf(sort))
}
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,12 @@ data class Medium(
} ?: -1
}

val episodesOrChapters: Int
get() = when (type) {
MediaType.MANGA -> chapters
else -> episodes
}

@Serializable
data class Title(
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class RootComponent(
componentContext = componentContext,
di = di,
onMediumDetails = {
navigation.push(RootConfig.Details(it))
navigation.bringToFront(RootConfig.Details(it))
},
onDiscover = {
// navigation.replaceCurrent(RootConfig.Wallpaper)
Expand All @@ -67,6 +67,9 @@ class RootComponent(
},
onHome = {
navigation.replaceCurrent(RootConfig.Home)
},
onMedium = {
navigation.bringToFront(RootConfig.Details(it))
}
)
is RootConfig.Nekos -> NekosScreenComponent(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.datlag.aniflow.ui.navigation.screen.favorites

import dev.datlag.aniflow.anilist.ListRepository
import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.settings.model.TitleLanguage
import dev.datlag.aniflow.ui.navigation.Component
import kotlinx.coroutines.flow.Flow
Expand All @@ -12,4 +13,6 @@ interface FavoritesComponent : Component {

fun viewDiscover()
fun viewHome()

fun details(medium: Medium)
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fun FavoritesScreen(component: FavoritesComponent) {
floatingActionButton = {
ExtendedFloatingActionButton(
onClick = {},
expanded = listState.isScrollingUp() && listState.canScrollForward,
expanded = listState.isScrollingUp(),
icon = {
Icon(
imageVector = Icons.Rounded.SwapVert,
Expand All @@ -77,7 +77,7 @@ fun FavoritesScreen(component: FavoritesComponent) {
},
bottomBar = {
HidingNavigationBar(
visible = listState.isScrollingUp() && listState.canScrollForward,
visible = listState.isScrollingUp(),
selected = NavigationBarState.Favorite,
loggedIn = flowOf(true),
onDiscover = component::viewDiscover,
Expand Down Expand Up @@ -108,14 +108,15 @@ fun FavoritesScreen(component: FavoritesComponent) {
LazyColumn(
state = listState,
modifier = Modifier.fillMaxSize().haze(state = LocalHaze.current),
contentPadding = padding.plus(PaddingValues(8.dp)),
verticalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = padding.merge(PaddingValues(16.dp)),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
items(current.medium.toList()) {
items(current.medium.toList(), key = { it.id }) {
ListCard(
medium = it,
titleLanguage = titleLanguage,
modifier = Modifier.fillParentMaxWidth().height(150.dp)
modifier = Modifier.fillParentMaxWidth().height(150.dp),
onClick = component::details
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.arkivanov.decompose.ComponentContext
import dev.chrisbanes.haze.HazeState
import dev.datlag.aniflow.LocalHaze
import dev.datlag.aniflow.anilist.ListRepository
import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.common.onRender
import dev.datlag.aniflow.other.UserHelper
import dev.datlag.aniflow.settings.Settings
Expand All @@ -23,6 +24,7 @@ class FavoritesScreenComponent(
override val di: DI,
private val onDiscover: () -> Unit,
private val onHome: () -> Unit,
private val onMedium: (Medium) -> Unit
) : FavoritesComponent, ComponentContext by componentContext {

private val appSettings by instance<Settings.PlatformAppSettings>()
Expand Down Expand Up @@ -57,4 +59,8 @@ class FavoritesScreenComponent(
override fun viewHome() {
onHome()
}

override fun details(medium: Medium) {
onMedium(medium)
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package dev.datlag.aniflow.ui.navigation.screen.favorites.component

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.PlayArrow
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
Expand All @@ -16,52 +20,112 @@ import androidx.compose.ui.unit.max
import coil3.compose.AsyncImage
import coil3.compose.rememberAsyncImagePainter
import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.common.preferred
import dev.datlag.aniflow.common.*
import dev.datlag.aniflow.settings.model.TitleLanguage
import dev.datlag.aniflow.ui.theme.SchemeTheme
import dev.datlag.aniflow.ui.theme.rememberSchemeThemeDominantColorState
import dev.icerock.moko.resources.compose.stringResource
import kotlin.math.max
import kotlin.math.min

@OptIn(ExperimentalStdlibApi::class)
@Composable
fun ListCard(
medium: Medium,
titleLanguage: TitleLanguage?,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
onClick: (Medium) -> Unit
) {
val defaultColor = remember(medium.coverImage.color) {
medium.coverImage.color?.substringAfter('#')?.let {
val colorValue = it.hexToLong() or 0x00000000FF000000
Color(colorValue)
}
}

val updater = SchemeTheme.create(
key = medium.id,
defaultColor = defaultColor,
)

ElevatedCard(
onClick = { },
onClick = { onClick(medium) },
modifier = modifier
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
AsyncImage(
modifier = Modifier.widthIn(min = 100.dp, max = 120.dp).fillMaxHeight().clip(MaterialTheme.shapes.medium),
model = medium.coverImage.extraLarge,
contentDescription = medium.preferred(titleLanguage),
contentScale = ContentScale.Crop,
error = rememberAsyncImagePainter(
model = medium.coverImage.large,
Box(
modifier = Modifier
.widthIn(min = 100.dp, max = 120.dp)
.fillMaxHeight()
.clip(MaterialTheme.shapes.medium)
) {
val colorState = rememberSchemeThemeDominantColorState(
key = medium.id,
applyMinContrast = true,
minContrastBackgroundColor = MaterialTheme.colorScheme.surfaceVariant,
defaultColor = defaultColor ?: MaterialTheme.colorScheme.primary,
defaultOnColor = defaultColor?.plainOnColor ?: MaterialTheme.colorScheme.onPrimary
)

AsyncImage(
modifier = Modifier.fillMaxSize(),
model = medium.coverImage.extraLarge,
contentDescription = medium.preferred(titleLanguage),
contentScale = ContentScale.Crop,
error = rememberAsyncImagePainter(
model = medium.coverImage.medium,
model = medium.coverImage.large,
contentScale = ContentScale.Crop,
error = rememberAsyncImagePainter(
model = medium.coverImage.medium,
contentScale = ContentScale.Crop,
onSuccess = { state ->
updater?.update(state.painter)
}
),
onSuccess = { state ->
updater?.update(state.painter)
}
),
onSuccess = { state ->
updater?.update(state.painter)
}
)
medium.entry?.let { entry ->
Row(
modifier = Modifier
.align(Alignment.BottomStart)
.fillMaxWidth()
.bottomShadowBrush(colorState.primary)
.padding(8.dp)
.padding(top = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Icon(
imageVector = entry.status.icon(),
contentDescription = null,
tint = colorState.onPrimary
)
Text(
text = stringResource(entry.status.stringRes(medium.type)),
color = colorState.onPrimary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
softWrap = true
)
}
),
onSuccess = { state ->
}
)
}
Column(
modifier = Modifier.weight(1F).padding(top = 16.dp, end = 16.dp, bottom = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
val progress = medium.entry?.progress ?: 0
val maxProgress = max(progress, medium.episodes)
var progress by remember(medium.entry?.progress) { mutableStateOf(medium.entry?.progress ?: 0) }
val totalEpisodes = max(medium.episodesOrChapters, 0)
val maxProgress = max(max(progress, totalEpisodes), 0)

Text(
text = medium.preferred(titleLanguage),
Expand All @@ -73,21 +137,44 @@ fun ListCard(
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Bottom
) {
LinearProgressIndicator(
progress = { 1F },
modifier = Modifier
.fillMaxWidth(
fraction = (progress.toFloat() / maxProgress.toFloat())
Text(text = "$progress/$totalEpisodes")
AnimatedVisibility(
visible = progress < totalEpisodes
) {
Button(
onClick = {
progress++
},
enabled = progress < totalEpisodes
) {
Text(text = "+1")
}
}
}
if (maxProgress > 0) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalAlignment = Alignment.CenterVertically,
) {
LinearProgressIndicator(
progress = { 1F },
modifier = Modifier
.fillMaxWidth(
fraction = (progress.toFloat() / maxProgress.toFloat())
)
.clip(CircleShape)
)
if (progress < maxProgress) {
LinearProgressIndicator(
progress = { 0F },
modifier = Modifier.weight(1F).clip(CircleShape)
)
.clip(CircleShape)
)
LinearProgressIndicator(
progress = { 0F },
modifier = Modifier.weight(1F).clip(CircleShape)
)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ fun HomeScreen(component: HomeComponent) {
onClick = {
imagePicker.launch()
},
expanded = listState.isScrollingUp() && listState.canScrollForward,
expanded = listState.isScrollingUp(),
icon = {
Icon(
imageVector = Icons.Filled.CameraEnhance,
Expand All @@ -168,7 +168,7 @@ fun HomeScreen(component: HomeComponent) {
},
bottomBar = {
HidingNavigationBar(
visible = listState.isScrollingUp() && listState.canScrollForward,
visible = listState.isScrollingUp(),
selected = NavigationBarState.Home,
loggedIn = component.loggedIn,
onDiscover = component::viewDiscover,
Expand Down
Loading

0 comments on commit 789eadf

Please sign in to comment.