Skip to content

Commit

Permalink
load other season
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Nov 13, 2023
1 parent 16c87c0 commit 06cdba1
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dev.datlag.burningseries.ui.navigation

interface DialogComponent : Component {
fun dismiss()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.datlag.burningseries.ui.screen.initial.series

import com.arkivanov.essenty.parcelable.Parcelable
import com.arkivanov.essenty.parcelable.Parcelize
import dev.datlag.burningseries.model.Series

@Parcelize
sealed class DialogConfig : Parcelable {

@Parcelize
data class Season(
val selected: Series.Season,
val seasons: List<Series.Season>
) : DialogConfig()
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package dev.datlag.burningseries.ui.screen.initial.series

import com.arkivanov.decompose.router.slot.ChildSlot
import com.arkivanov.decompose.value.Value
import dev.datlag.burningseries.model.state.SeriesState
import dev.datlag.burningseries.ui.navigation.Component
import dev.datlag.burningseries.ui.navigation.DialogComponent
import kotlinx.coroutines.flow.StateFlow

interface SeriesComponent : Component {

val seriesState: StateFlow<SeriesState>
val dialog: Value<ChildSlot<DialogConfig, DialogComponent>>

val title: StateFlow<String>
val href: StateFlow<String>
Expand All @@ -15,4 +19,6 @@ interface SeriesComponent : Component {
fun retryLoadingSeries(): Any?

fun goBack()

fun showDialog(config: DialogConfig)
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState
import dev.datlag.burningseries.common.diagonalShape
import dev.datlag.burningseries.common.lifecycle.collectAsStateWithLifecycle
import dev.datlag.burningseries.common.onClick
Expand Down Expand Up @@ -64,6 +65,7 @@ import kotlin.math.abs
@Composable
fun SeriesScreen(component: SeriesComponent) {
val href by component.href.collectAsStateWithLifecycle()
val dialogState by component.dialog.subscribeAsState()

SchemeTheme.setCommon(href)
when (calculateWindowSizeClass().widthSizeClass) {
Expand All @@ -77,6 +79,8 @@ fun SeriesScreen(component: SeriesComponent) {
SchemeTheme.setCommon(null, scope)
}
}

dialogState.child?.instance?.render()
}

@Composable
Expand Down Expand Up @@ -303,7 +307,11 @@ private fun DefaultScreen(component: SeriesComponent) {
selectedLanguage = current.series.currentLanguage,
seasons = current.series.seasons,
languages = current.series.languages,
onSeasonClick = { },
onSeasonClick = { season ->
season?.let {
component.showDialog(DialogConfig.Season(it, current.series.seasons))
}
},
onLanguageClick = { }
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ package dev.datlag.burningseries.ui.screen.initial.series

import androidx.compose.runtime.Composable
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.router.slot.*
import com.arkivanov.decompose.value.Value
import com.arkivanov.essenty.backhandler.BackCallback
import com.arkivanov.essenty.backhandler.BackHandler
import dev.datlag.burningseries.common.defaultScope
import dev.datlag.burningseries.common.ioDispatcher
import dev.datlag.burningseries.common.ioScope
import dev.datlag.burningseries.common.launchIO
import dev.datlag.burningseries.model.BSUtil
import dev.datlag.burningseries.model.Series
import dev.datlag.burningseries.model.state.SeriesAction
import dev.datlag.burningseries.model.state.SeriesState
import dev.datlag.burningseries.network.state.SeriesStateMachine
import dev.datlag.burningseries.ui.navigation.DialogComponent
import dev.datlag.burningseries.ui.screen.initial.series.dialog.season.SeasonDialogComponent
import io.ktor.client.*
import kotlinx.coroutines.flow.*
import org.kodein.di.DI
Expand All @@ -29,9 +35,29 @@ class SeriesScreenComponent(
private val seriesStateMachine = SeriesStateMachine(httpClient, initialHref)
override val seriesState: StateFlow<SeriesState> = seriesStateMachine.state.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.Lazily, SeriesState.Loading(initialHref))

override val title: StateFlow<String> = seriesState.mapNotNull { it as? SeriesState.Success }.map { it.series.title }.stateIn(ioScope(), SharingStarted.Lazily, initialTitle)
override val href: StateFlow<String> = seriesState.mapNotNull { it as? SeriesState.Success }.map { it.series.href }.stateIn(ioScope(), SharingStarted.Lazily, BSUtil.fixSeriesHref(initialHref))
override val coverHref: StateFlow<String?> = seriesState.mapNotNull { it as? SeriesState.Success }.mapNotNull { it.series.coverHref }.stateIn(ioScope(), SharingStarted.Lazily, initialCoverHref)
private val currentSeries = seriesState.mapNotNull { it as? SeriesState.Success }.map { it.series }.stateIn(ioScope(), SharingStarted.Lazily, null)
override val title: StateFlow<String> = currentSeries.mapNotNull { it?.title }.stateIn(ioScope(), SharingStarted.Lazily, initialTitle)
override val href: StateFlow<String> = currentSeries.mapNotNull { it?.href }.stateIn(ioScope(), SharingStarted.Lazily, BSUtil.fixSeriesHref(initialHref))
override val coverHref: StateFlow<String?> = currentSeries.mapNotNull { it?.coverHref }.stateIn(ioScope(), SharingStarted.Lazily, initialCoverHref)

private val dialogNavigation = SlotNavigation<DialogConfig>()
private val _dialog = childSlot(
source = dialogNavigation
) { config, slotContext ->
when (config) {
is DialogConfig.Season -> SeasonDialogComponent(
componentContext = slotContext,
di = di,
defaultSeason = config.selected,
seasons = config.seasons,
onDismissed = dialogNavigation::dismiss,
onSelected = {
loadNewSeason(it)
}
)
}
}
override val dialog: Value<ChildSlot<DialogConfig, DialogComponent>> = _dialog

private val backCallback = BackCallback(priority = Int.MAX_VALUE) {
onGoBack()
Expand All @@ -53,4 +79,14 @@ class SeriesScreenComponent(
override fun goBack() {
onGoBack()
}

override fun showDialog(config: DialogConfig) {
dialogNavigation.activate(config)
}

private fun loadNewSeason(season: Series.Season) = ioScope().launchIO {
(currentSeries.value ?: currentSeries.firstOrNull())?.let { series ->
seriesStateMachine.dispatch(SeriesAction.Load(series.hrefBuilder(season.value)))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ fun SeasonAndLanguageButtons(
selectedLanguage: Series.Language?,
seasons: List<Series.Season>,
languages: List<Series.Language>,
onSeasonClick: () -> Unit,
onLanguageClick: () -> Unit,
onSeasonClick: (Series.Season?) -> Unit,
onLanguageClick: (Series.Language?) -> Unit,
modifier: Modifier = Modifier
) {
FlowRow(
Expand All @@ -34,7 +34,7 @@ fun SeasonAndLanguageButtons(
if (selectedSeason != null) {
Button(
onClick = {
onSeasonClick()
onSeasonClick(selectedSeason)
},
enabled = seasons.size > 1,
modifier = Modifier.weight(1F)
Expand All @@ -50,7 +50,7 @@ fun SeasonAndLanguageButtons(
if (selectedLanguage != null) {
Button(
onClick = {
onLanguageClick()
onLanguageClick(selectedLanguage)
},
enabled = languages.size > 1,
modifier = Modifier.weight(1F)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dev.datlag.burningseries.ui.screen.initial.series.dialog.season

import dev.datlag.burningseries.model.Series
import dev.datlag.burningseries.ui.navigation.DialogComponent

interface SeasonComponent : DialogComponent {

val defaultSeason: Series.Season
val seasons: List<Series.Season>

fun onConfirm(season: Series.Season)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package dev.datlag.burningseries.ui.screen.initial.series.dialog.season

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import dev.datlag.burningseries.shared.SharedRes
import dev.icerock.moko.resources.compose.stringResource

@Composable
fun SeasonDialog(component: SeasonComponent) {
var selectedItem by remember { mutableStateOf(component.defaultSeason) }

AlertDialog(
onDismissRequest = {
component.dismiss()
},
title = {
Text(
text = stringResource(SharedRes.strings.select_season),
style = MaterialTheme.typography.headlineMedium,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
softWrap = true
)
},
text = {
Column(
modifier = Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
component.seasons.forEach {
val selected = selectedItem == it
Row(
modifier = Modifier.selectable(
selected = selected,
role = Role.RadioButton,
onClick = { selectedItem = it }
).fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = selected,
onClick = null
)
val seasonText = if (it.title.toIntOrNull() != null) {
stringResource(SharedRes.strings.season_placeholder, it.title)
} else {
it.title
}
Text(
text = seasonText,
overflow = TextOverflow.Ellipsis,
softWrap = true
)
}
}
}
},
confirmButton = {
Button(
onClick = {
if (component.defaultSeason != selectedItem) {
component.onConfirm(selectedItem)
} else {
component.dismiss()
}
}
) {
Icon(
imageVector = Icons.Default.Check,
contentDescription = stringResource(SharedRes.strings.confirm),
modifier = Modifier.size(ButtonDefaults.IconSize)
)
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
Text(text = stringResource(SharedRes.strings.confirm))
}
},
dismissButton = {
Button(
onClick = {
component.dismiss()
},
modifier = Modifier.padding(bottom = 8.dp),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.onErrorContainer
)
) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = stringResource(SharedRes.strings.close),
modifier = Modifier.size(ButtonDefaults.IconSize)
)
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
Text(text = stringResource(SharedRes.strings.close))
}
}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dev.datlag.burningseries.ui.screen.initial.series.dialog.season

import androidx.compose.runtime.Composable
import com.arkivanov.decompose.ComponentContext
import dev.datlag.burningseries.model.Series
import org.kodein.di.DI

class SeasonDialogComponent(
componentContext: ComponentContext,
override val di: DI,
override val defaultSeason: Series.Season,
override val seasons: List<Series.Season>,
private val onDismissed: () -> Unit,
private val onSelected: (Series.Season) -> Unit
) : SeasonComponent, ComponentContext by componentContext {

@Composable
override fun render() {
SeasonDialog(this)
}

override fun dismiss() {
onDismissed()
}

override fun onConfirm(season: Series.Season) {
onSelected(season)
onDismissed()
}
}
3 changes: 3 additions & 0 deletions app/shared/src/commonMain/resources/MR/base/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@
<string name="downloading_text">Downloading required packages for your platform, please wait</string>
<string name="loading_search">Loading search information, please wait</string>
<string name="error_loading_search">Error while loading search information</string>
<string name="select_season">Select Season</string>
<string name="confirm">Confirm</string>
<string name="close">Close</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ data object BSUtil {
return rebuildHrefFromData(hrefDataFromHref(normalizeHref(href)))
}

private fun hrefDataFromHref(href: String): Triple<String, String?, String?> {
fun hrefDataFromHref(href: String): Triple<String, String?, String?> {
fun getTitle(): String {
val newHref = if (href.startsWith("series/")) {
href.substringAfter("series/")
Expand Down Expand Up @@ -85,7 +85,7 @@ data object BSUtil {
)
}

private fun rebuildHrefFromData(hrefData: Triple<String, String?, String?>): String {
fun rebuildHrefFromData(hrefData: Triple<String, String?, String?>): String {
return if (hrefData.second != null && hrefData.third != null) {
"serie/${hrefData.first}/${hrefData.second}/${hrefData.third}"
} else if (hrefData.second != null) {
Expand Down
Loading

0 comments on commit 06cdba1

Please sign in to comment.