Skip to content

Commit

Permalink
Feat: Add like function in comic screen
Browse files Browse the repository at this point in the history
  • Loading branch information
SeokgyuYun committed Sep 15, 2023
1 parent 7bc84cd commit edc0be0
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 27 deletions.
1 change: 1 addition & 0 deletions core/data/src/main/java/kr/toongether/data/model/Comic.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import kr.toongether.model.Comic
import kr.toongether.network.model.ComicResponse

fun ComicResponse.asModel(): Comic = Comic(
id = id,
title = title,
thumbnail = thumbnail,
imageUrl = imageUrl,
Expand Down
1 change: 1 addition & 0 deletions core/model/src/main/java/kr/toongether/model/Comic.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package kr.toongether.model
import kotlinx.datetime.LocalDateTime

data class Comic(
val id: Long,
val title: String,
val thumbnail: String,
val imageUrl: List<String>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import kotlinx.serialization.Serializable

@Serializable
data class ComicResponse(
@SerialName("id")
val id: Long,
@SerialName("title")
val title: String,
@SerialName("thumbnail")
Expand Down
3 changes: 2 additions & 1 deletion core/ui/src/main/java/kr/toongether/ui/ShortsCard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import kr.toongether.common.toRelativeDateTime
import kr.toongether.designsystem.icon.ToongetherIcons
import kr.toongether.designsystem.icon.icons.FilledHeart
import kr.toongether.designsystem.icon.icons.OutlinedHeart
import kr.toongether.designsystem.theme.Red
import kr.toongether.designsystem.theme.TransparentBlack80
import kr.toongether.designsystem.theme.pretendard
import kr.toongether.designsystem.utils.NoRippleInteractionSource
Expand Down Expand Up @@ -148,7 +149,7 @@ fun ShortsCard(
),
imageVector = if (isLiked.not()) ToongetherIcons.OutlinedHeart else ToongetherIcons.FilledHeart,
contentDescription = null,
tint = Color.White
tint = if (isLiked.not()) Color.White else Red
)

Spacer(modifier = modifier.width(5.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import kr.toongether.model.Comic

data class ComicState(
val comic: Comic = Comic(
id = 0L,
title = "",
thumbnail = "",
imageUrl = emptyList(),
Expand All @@ -22,7 +23,9 @@ data class ComicState(
liked = false
),
val error: Throwable? = null,
val isLoading: Boolean = false
val likeCount: Int = comic.likeCount,
val liked: Boolean = comic.liked,
val isLoading: Boolean = false,
)

sealed class ComicSideEffect {
Expand Down
46 changes: 30 additions & 16 deletions feature/comic/src/main/java/kr/toongether/comic/ComicScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand Down Expand Up @@ -59,16 +58,17 @@ import kr.toongether.designsystem.theme.TransparentBlack
import kr.toongether.designsystem.theme.pretendard
import kr.toongether.designsystem.utils.NoRippleInteractionSource
import org.orbitmvi.orbit.compose.collectAsState
import org.orbitmvi.orbit.compose.collectSideEffect
import java.time.LocalTime
import kotlin.concurrent.timer

@Composable
internal fun ComicRoute(
episodeId: Long,
episodeNumber: Long,
seriesId: Long,
navController: NavController,
modifier: Modifier = Modifier,
viewModel: ComicViewModel = hiltViewModel()
viewModel: ComicViewModel = hiltViewModel(),
) {
val comicState by viewModel.collectAsState()
val lazyListState = rememberLazyListState()
Expand Down Expand Up @@ -99,9 +99,9 @@ internal fun ComicRoute(

LaunchedEffect(Unit) {
if (seriesId == -1L) {
viewModel.getComic(episodeId)
viewModel.getComic(episodeNumber)
} else {
viewModel.getComic(seriesId = seriesId, episodeId = episodeId)
viewModel.getComic(seriesId = seriesId, episodeId = episodeNumber)
}
showTabs()
}
Expand All @@ -115,26 +115,40 @@ internal fun ComicRoute(
isShowTabs = isShowTabs || isTopOrBottom,
recomposition = {
isTopOrBottom = lazyListState.layoutInfo.visibleItemsInfo.firstOrNull()?.index == 0 ||
lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ==
lazyListState.layoutInfo.totalItemsCount - 1
lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ==
lazyListState.layoutInfo.totalItemsCount - 1
},
onClickLike = {
if (seriesId == -1L) {
viewModel.likeShorts(episodeNumber)
} else {
viewModel.likeSeries(comicState.comic.id)
}
},
onClickLike = { },
/* onClickComment = { }, */
liked = comicState.comic.liked,
likeCount = comicState.comic.likeCount,
liked = comicState.liked,
likeCount = comicState.likeCount,
/* commentCount = comicState.comic.commentCount, */
onClickAfter = {
navController.navigateToComic(
seriesId = seriesId,
episodeId = comicState.comic.nextEpisode!!,
navOptions { this.popUpTo(kr.toongether.comic.navigation.ComicRoute) { inclusive = true } }
episodeNumber = comicState.comic.nextEpisode!!,
navOptions {
this.popUpTo(kr.toongether.comic.navigation.ComicRoute) {
inclusive = true
}
}
)
},
onClickBefore = {
navController.navigateToComic(
seriesId = seriesId,
episodeId = comicState.comic.beforeEpisode!!,
navOptions { this.popUpTo(kr.toongether.comic.navigation.ComicRoute) { inclusive = true } }
episodeNumber = comicState.comic.beforeEpisode!!,
navOptions {
this.popUpTo(kr.toongether.comic.navigation.ComicRoute) {
inclusive = true
}
}
)
},
isNext = comicState.comic.nextEpisode != null,
Expand All @@ -159,7 +173,7 @@ internal fun ComicScreen(
onClickBefore: () -> Unit,
onClickAfter: () -> Unit,
isNext: Boolean,
isBefore: Boolean
isBefore: Boolean,
) {
val minHeight: Dp
val lastHeight: Dp
Expand Down Expand Up @@ -371,7 +385,7 @@ internal fun ComicScreen(
private fun ComicItem(
modifier: Modifier = Modifier,
height: Dp,
imageUrl: String
imageUrl: String,
) {
Box(
modifier = modifier
Expand Down
40 changes: 37 additions & 3 deletions feature/comic/src/main/java/kr/toongether/comic/ComicViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kr.toongether.domain.GetSeriesEpisodeUseCase
import kr.toongether.domain.GetShortsEpisodeUseCase
import kr.toongether.domain.LikeSeriesUseCase
import kr.toongether.domain.LikeShortsUseCase
import org.orbitmvi.orbit.ContainerHost
import org.orbitmvi.orbit.syntax.simple.intent
import org.orbitmvi.orbit.syntax.simple.postSideEffect
Expand All @@ -14,7 +16,9 @@ import javax.inject.Inject
@HiltViewModel
class ComicViewModel @Inject constructor(
private val getShortsEpisodeUseCase: GetShortsEpisodeUseCase,
private val getSeriesEpisodeUseCase: GetSeriesEpisodeUseCase
private val getSeriesEpisodeUseCase: GetSeriesEpisodeUseCase,
private val likeShortsUseCase: LikeShortsUseCase,
private val likeSeriesUseCase: LikeSeriesUseCase,
) : ContainerHost<ComicState, ComicSideEffect>, ViewModel() {

override val container = container<ComicState, ComicSideEffect>(ComicState())
Expand All @@ -28,7 +32,9 @@ class ComicViewModel @Inject constructor(
reduce {
state.copy(
isLoading = false,
comic = it
comic = it,
liked = it.liked,
likeCount = it.likeCount
)
}
}.onFailure {
Expand All @@ -53,7 +59,9 @@ class ComicViewModel @Inject constructor(
reduce {
state.copy(
isLoading = false,
comic = it
comic = it,
liked = it.liked,
likeCount = it.likeCount
)
}
}.onFailure {
Expand All @@ -66,4 +74,30 @@ class ComicViewModel @Inject constructor(
}
}
}

fun likeShorts(shortsId: Long) = intent {
likeShortsUseCase.invoke(shortsId)
.onSuccess {
if (it) {
reduce { state.copy(likeCount = state.likeCount + 1, liked = true) }
} else {
reduce { state.copy(likeCount = state.likeCount - 1, liked = false) }
}
}.onFailure {
postSideEffect(ComicSideEffect.Toast(it.message!!))
}
}

fun likeSeries(seriesId: Long) = intent {
likeSeriesUseCase.invoke(seriesId)
.onSuccess {
if (it) {
reduce { state.copy(likeCount = state.likeCount + 1, liked = true) }
} else {
reduce { state.copy(likeCount = state.likeCount - 1, liked = false) }
}
}.onFailure {
postSideEffect(ComicSideEffect.Toast(it.message!!))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ import androidx.navigation.navArgument
import com.google.accompanist.navigation.animation.composable
import kr.toongether.comic.ComicRoute

const val ComicRoute = "comic_route/{seriesId}/{episodeId}"
const val ComicRoute = "comic_route/{seriesId}/{episodeNumber}"

fun NavController.navigateToComic(shortsId: Long, navOptions: NavOptions? = null) {
this.navigate("comic_route/-1/$shortsId", navOptions)
}

fun NavController.navigateToComic(
seriesId: Long,
episodeId: Long,
episodeNumber: Long,
navOptions: NavOptions? = null
) {
this.navigate("comic_route/$seriesId/$episodeId", navOptions)
this.navigate("comic_route/$seriesId/$episodeNumber", navOptions)
}

@OptIn(ExperimentalAnimationApi::class)
Expand All @@ -31,7 +31,7 @@ fun NavGraphBuilder.comicScreen(navController: NavController) {
route = ComicRoute,
arguments = listOf(
navArgument("seriesId") { type = NavType.LongType },
navArgument("episodeId") { type = NavType.LongType }
navArgument("episodeNumber") { type = NavType.LongType },
),
enterTransition = {
when (initialState.destination.route) {
Expand Down Expand Up @@ -64,7 +64,7 @@ fun NavGraphBuilder.comicScreen(navController: NavController) {
ComicRoute(
navController = navController,
seriesId = it.arguments?.getLong("seriesId") ?: 0L,
episodeId = it.arguments?.getLong("episodeId") ?: 0L
episodeNumber = it.arguments?.getLong("episodeNumber") ?: 0L,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ internal fun EpisodeRoute(
onItemClick = {
navController.navigateToComic(
seriesId = id,
episodeId = it.episodeNumber.toLong()
episodeNumber = it.episodeNumber.toLong(),
)
},
onClickBack = navController::popBackStack,
Expand Down

0 comments on commit edc0be0

Please sign in to comment.