diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/common/ExtendCompose.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/common/ExtendCompose.kt index f000ba33..2bc55073 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/common/ExtendCompose.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/common/ExtendCompose.kt @@ -9,8 +9,10 @@ import androidx.compose.foundation.lazy.grid.LazyGridScope import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.composed +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput +import dev.datlag.burningseries.ui.theme.shape.DiagonalShape inline fun Modifier.ifTrue(predicate: Boolean, builder: Modifier.() -> Modifier) = then(if (predicate) builder() else Modifier) inline fun Modifier.ifFalse(predicate: Boolean, builder: Modifier.() -> Modifier) = then(if (!predicate) builder() else Modifier) @@ -58,4 +60,9 @@ fun Modifier.pressClick(maxTranslation: Float = 10F) = composed { } } } -} \ No newline at end of file +} + +fun Modifier.diagonalShape( + angle: Float, + position: DiagonalShape.POSITION = DiagonalShape.POSITION.TOP +) = this.clip(DiagonalShape(angle, position)) \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/custom/DefaultCollapsingToolbar.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/custom/DefaultCollapsingToolbar.kt index 3cc3e5f0..61338768 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/custom/DefaultCollapsingToolbar.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/custom/DefaultCollapsingToolbar.kt @@ -1,15 +1,13 @@ package dev.datlag.burningseries.ui.custom -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material.TopAppBar +import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import dev.datlag.burningseries.common.launchMain @@ -24,7 +22,7 @@ fun DefaultCollapsingToolbar( state: CollapsingToolbarScaffoldState = rememberCollapsingToolbarScaffoldState(), expandedBody: @Composable CollapsingToolbarScope.(CollapsingToolbarScaffoldState) -> Unit, title: @Composable (CollapsingToolbarScaffoldState) -> Unit, - navigationIcon: @Composable (CollapsingToolbarScaffoldState) -> Unit = { }, + navigationIcon: (@Composable (CollapsingToolbarScaffoldState) -> Unit)? = null, actions: @Composable RowScope.(CollapsingToolbarScaffoldState) -> Unit = { }, content: @Composable CollapsingToolbarScaffoldScope.() -> Unit ) { @@ -34,7 +32,7 @@ fun DefaultCollapsingToolbar( var expanded by remember { mutableStateOf(false) } CollapsingToolbarScaffold( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxSize(), state = state, scrollStrategy = ScrollStrategy.ExitUntilCollapsed, toolbarModifier = Modifier.fillMaxWidth().defaultMinSize(minHeight = 56.dp).verticalScroll(rememberScrollState()), @@ -44,18 +42,16 @@ fun DefaultCollapsingToolbar( TopAppBar( modifier = Modifier.pin(), - colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.surface.copy(alpha = reversedProgress) - ), + backgroundColor = MaterialTheme.colorScheme.surface.copy(alpha = reversedProgress), + contentColor = MaterialTheme.colorScheme.onSurface, title = { title(state) }, + navigationIcon = if (navigationIcon == null) null else { { navigationIcon(state) } }, actions = { actions(state) }, - navigationIcon = { - navigationIcon(state) - } + elevation = 0.dp ) } ) { diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/home/HomeScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/home/HomeScreenComponent.kt index 750ad4e0..138d9935 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/home/HomeScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/home/HomeScreenComponent.kt @@ -2,10 +2,7 @@ package dev.datlag.burningseries.ui.screen.initial.home import androidx.compose.runtime.Composable import com.arkivanov.decompose.ComponentContext -import com.arkivanov.decompose.router.slot.ChildSlot -import com.arkivanov.decompose.router.slot.SlotNavigation -import com.arkivanov.decompose.router.slot.activate -import com.arkivanov.decompose.router.slot.childSlot +import com.arkivanov.decompose.router.slot.* import com.arkivanov.decompose.value.MutableValue import com.arkivanov.decompose.value.Value import dev.datlag.burningseries.common.ioDispatcher @@ -39,7 +36,8 @@ class HomeScreenComponent( di = di, initialTitle = config.title, initialHref = config.href, - initialCoverHref = config.coverHref + initialCoverHref = config.coverHref, + onGoBack = navigation::dismiss ) } } diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesComponent.kt index 53532ceb..8a7373f7 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesComponent.kt @@ -12,4 +12,6 @@ interface SeriesComponent : Component { val seriesState: StateFlow fun retryLoadingSeries(): Any? + + fun goBack() } \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.kt index bf6de256..5de742fc 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreen.kt @@ -1,9 +1,15 @@ package dev.datlag.burningseries.ui.screen.initial.series import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBackIos +import androidx.compose.material.icons.filled.ArrowBackIosNew import androidx.compose.material3.* import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass @@ -13,10 +19,14 @@ import androidx.compose.runtime.saveable.rememberSaveable 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.graphics.drawscope.Stroke import androidx.compose.ui.layout.ContentScale +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 dev.datlag.burningseries.common.diagonalShape import dev.datlag.burningseries.common.lifecycle.collectAsStateWithLifecycle import dev.datlag.burningseries.common.onClick import dev.datlag.burningseries.model.BSUtil @@ -31,6 +41,7 @@ import dev.datlag.burningseries.ui.custom.readmore.ToggleArea import dev.datlag.burningseries.ui.custom.state.ErrorState import dev.datlag.burningseries.ui.custom.state.LoadingState import dev.datlag.burningseries.ui.screen.initial.series.component.SeasonAndLanguageButtons +import dev.datlag.burningseries.ui.theme.shape.DiagonalShape import dev.icerock.moko.resources.compose.stringResource import io.kamel.core.Resource import io.kamel.image.asyncPainterResource @@ -55,7 +66,11 @@ private fun CompactScreen(component: SeriesComponent) { is Resource.Loading, is Resource.Failure -> { } is Resource.Success -> { Image( - modifier = Modifier.fillMaxWidth().defaultMinSize(minHeight = 320.dp).parallax(0.5F), + modifier = Modifier + .fillMaxWidth() + .defaultMinSize(minHeight = 320.dp) + .parallax(0.5F) + .diagonalShape(-10F, DiagonalShape.POSITION.BOTTOM), painter = resource.value, contentDescription = component.initialTitle, contentScale = ContentScale.FillWidth, @@ -85,30 +100,49 @@ private fun CompactScreen(component: SeriesComponent) { ) }, title = { state -> - val reversedProgress by remember { - derivedStateOf { (abs(1F - state.toolbarState.progress)) } - } - Text( - text = component.initialTitle, - color = LocalContentColor.current.copy(alpha = run { - val alpha = reversedProgress - if (alpha < 0.7F) { - if (alpha < 0.3F) { - 0F + Row( + modifier = Modifier.fillMaxSize(), + verticalAlignment = Alignment.CenterVertically + ) { + val reversedProgress by remember { + derivedStateOf { (abs(1F - state.toolbarState.progress)) } + } + + Text( + text = component.initialTitle, + color = LocalContentColor.current.copy(alpha = run { + val alpha = reversedProgress + if (alpha < 0.7F) { + if (alpha < 0.3F) { + 0F + } else { + alpha + } } else { - alpha + 1F } - } else { - 1F - } - }), - maxLines = 1, - overflow = TextOverflow.Ellipsis, - softWrap = true - ) + }), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + softWrap = true + ) + } }, - navigationIcon = { - + navigationIcon = { state -> + IconButton( + onClick = { + component.goBack() + }, + modifier = Modifier.background( + color = if (state.toolbarState.progress == 1F) Color.Black.copy(alpha = 0.5F) else Color.Black.copy(alpha = state.toolbarState.progress / 10F), + shape = CircleShape + ) + ) { + Icon( + imageVector = Icons.Default.ArrowBackIosNew, + contentDescription = stringResource(SharedRes.strings.back) + ) + } } ) { when (val current = seriesState) { @@ -122,14 +156,38 @@ private fun CompactScreen(component: SeriesComponent) { } is SeriesState.Success -> { LazyColumn( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(horizontal = 16.dp) ) { + item { + var expanded by remember { mutableStateOf(false) } + + ReadMoreText( + text = current.series.description, + expanded = expanded, + onExpandedChange = { + expanded = it + }, + modifier = Modifier.fillMaxWidth(), + readMoreText = stringResource(SharedRes.strings.read_more), + readMoreColor = MaterialTheme.colorScheme.primary, + readMoreFontWeight = FontWeight.SemiBold, + readMoreMaxLines = 2, + readMoreOverflow = ReadMoreTextOverflow.Ellipsis, + readLessText = stringResource(SharedRes.strings.read_less), + readLessColor = MaterialTheme.colorScheme.primary, + readLessFontWeight = FontWeight.SemiBold, + toggleArea = ToggleArea.All + ) + } + item { SeasonAndLanguageButtons( - current.series.currentSeason, - current.series.currentLanguage, - current.series.seasons, - current.series.languages, + modifier = Modifier.padding(vertical = 16.dp), + selectedSeason = current.series.currentSeason, + selectedLanguage = current.series.currentLanguage, + seasons = current.series.seasons, + languages = current.series.languages, onSeasonClick = { }, onLanguageClick = { } ) @@ -208,25 +266,20 @@ private fun DefaultScreen(component: SeriesComponent) { } private fun LazyListScope.SeriesContent(content: Series) { - item { - var expanded by remember { mutableStateOf(false) } - - ReadMoreText( - text = content.description, - expanded = expanded, - onExpandedChange = { - expanded = it - }, + items(content.episodes) { episode -> + Row( modifier = Modifier.fillMaxWidth(), - readMoreText = stringResource(SharedRes.strings.read_more), - readMoreColor = MaterialTheme.colorScheme.primary, - readMoreFontWeight = FontWeight.SemiBold, - readMoreMaxLines = 2, - readMoreOverflow = ReadMoreTextOverflow.Ellipsis, - readLessText = stringResource(SharedRes.strings.read_less), - readLessColor = MaterialTheme.colorScheme.primary, - readLessFontWeight = FontWeight.SemiBold, - toggleArea = ToggleArea.All - ) + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = episode.number, + fontWeight = FontWeight.SemiBold + ) + Text( + text = episode.title, + maxLines = 1 + ) + } } } \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreenComponent.kt index 3b2265ef..73f4506a 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/SeriesScreenComponent.kt @@ -2,6 +2,7 @@ package dev.datlag.burningseries.ui.screen.initial.series import androidx.compose.runtime.Composable import com.arkivanov.decompose.ComponentContext +import com.arkivanov.essenty.backhandler.BackHandler import dev.datlag.burningseries.common.ioDispatcher import dev.datlag.burningseries.common.ioScope import dev.datlag.burningseries.common.launchIO @@ -21,7 +22,8 @@ class SeriesScreenComponent( override val di: DI, override val initialTitle: String, val initialHref: String, - override val initialCoverHref: String? + override val initialCoverHref: String?, + private val onGoBack: () -> Unit ) : SeriesComponent, ComponentContext by componentContext { private val httpClient by di.instance() @@ -36,4 +38,8 @@ class SeriesScreenComponent( override fun retryLoadingSeries(): Any? = ioScope().launchIO { seriesStateMachine.dispatch(SeriesAction.Retry) } + + override fun goBack() { + onGoBack() + } } \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/component/SeasonAndLanguageButtons.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/component/SeasonAndLanguageButtons.kt index 3d22736a..81c36970 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/component/SeasonAndLanguageButtons.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/screen/initial/series/component/SeasonAndLanguageButtons.kt @@ -24,8 +24,10 @@ fun SeasonAndLanguageButtons( languages: List, onSeasonClick: () -> Unit, onLanguageClick: () -> Unit, + modifier: Modifier = Modifier ) { FlowRow( + modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/theme/shape/DiagonalShape.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/theme/shape/DiagonalShape.kt new file mode 100644 index 00000000..46dece2d --- /dev/null +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/ui/theme/shape/DiagonalShape.kt @@ -0,0 +1,108 @@ +package dev.datlag.burningseries.ui.theme.shape + +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Outline +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.LayoutDirection +import kotlin.math.PI +import kotlin.math.abs +import kotlin.math.tan + +data class DiagonalShape( + internal val angle: Float = 0F, + internal val position: POSITION = POSITION.TOP +) : Shape { + + private val direction: DIRECTION + get() = if (angle > 0) DIRECTION.LEFT else DIRECTION.RIGHT + + override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline { + return Outline.Generic(Path().apply { + val angleAbs = abs(angle) + val perpendicularHeight = (size.width * tan(angleAbs / 180 * PI)).toFloat() + + when (position) { + is POSITION.START -> { + when (direction) { + is DIRECTION.LEFT -> { + this.moveTo(perpendicularHeight, 0F) + this.lineTo(size.width, 0F) + this.lineTo(size.width, size.height) + this.lineTo(0F, size.height) + } + is DIRECTION.RIGHT -> { + this.moveTo(0F, 0F) + this.lineTo(size.width, 0F) + this.lineTo(size.width, size.height) + this.lineTo(perpendicularHeight, size.height) + } + } + } + is POSITION.TOP -> { + when (direction) { + is DIRECTION.LEFT -> { + this.moveTo(size.width, size.height) + this.lineTo(size.width, perpendicularHeight) + this.lineTo(0F, 0F) + this.lineTo(0F, size.height) + } + is DIRECTION.RIGHT -> { + this.moveTo(size.width, size.height) + this.lineTo(size.width, 0F) + this.lineTo(0F, perpendicularHeight) + this.lineTo(0F, size.height) + } + } + } + is POSITION.END -> { + when (direction) { + is DIRECTION.LEFT -> { + this.moveTo(0F, 0F) + this.lineTo(size.width, 0F) + this.lineTo(size.width - perpendicularHeight, size.height) + this.lineTo(0F, size.height) + } + is DIRECTION.RIGHT -> { + this.moveTo(0F, 0F) + this.lineTo(size.width - perpendicularHeight, 0F) + this.lineTo(size.width, size.height) + this.lineTo(0F, size.height) + } + } + } + is POSITION.BOTTOM -> { + when (direction) { + is DIRECTION.LEFT -> { + this.moveTo(0F, 0F) + this.lineTo(size.width, 0F) + this.lineTo(size.width, size.height - perpendicularHeight) + this.lineTo(0F, size.height) + } + is DIRECTION.RIGHT -> { + this.moveTo(size.width, size.height) + this.lineTo(0F, size.height - perpendicularHeight) + this.lineTo(0F, 0F) + this.lineTo(size.width, 0F) + } + } + } + } + + this.close() + }) + } + + sealed interface POSITION { + data object START : POSITION + data object TOP : POSITION + data object END : POSITION + data object BOTTOM : POSITION + } + + private sealed interface DIRECTION { + data object LEFT : DIRECTION + data object RIGHT : DIRECTION + } +} \ No newline at end of file diff --git a/app/shared/src/commonMain/resources/MR/base/strings.xml b/app/shared/src/commonMain/resources/MR/base/strings.xml index 2f7a061e..c041c00a 100644 --- a/app/shared/src/commonMain/resources/MR/base/strings.xml +++ b/app/shared/src/commonMain/resources/MR/base/strings.xml @@ -14,4 +14,5 @@ Loading series information, please wait Error while loading series information Season %s + Back \ No newline at end of file diff --git a/app/shared/src/iosMain/kotlin/main.ios.kt b/app/shared/src/iosMain/kotlin/main.ios.kt index fa15dc6b..3ba07f8e 100644 --- a/app/shared/src/iosMain/kotlin/main.ios.kt +++ b/app/shared/src/iosMain/kotlin/main.ios.kt @@ -20,6 +20,12 @@ import io.kamel.image.config.LocalKamelConfig import org.kodein.di.DI import platform.UIKit.UIViewController +private val di: DI by lazy(LazyThreadSafetyMode.NONE) { + DI { + import(NetworkModule.di) + } +} + fun MainViewController(): UIViewController { val lifecycleRegistry = LifecycleRegistry() @@ -27,10 +33,6 @@ fun MainViewController(): UIViewController { override val lifecycle: Lifecycle = lifecycleRegistry } - val di = DI { - import(NetworkModule.di) - } - val root = NavHostComponent( componentContext = DefaultComponentContext(lifecycleOwner.lifecycle), di = di diff --git a/model/src/commonMain/kotlin/dev/datlag/burningseries/model/Series.kt b/model/src/commonMain/kotlin/dev/datlag/burningseries/model/Series.kt index a5a753cf..999b1dee 100644 --- a/model/src/commonMain/kotlin/dev/datlag/burningseries/model/Series.kt +++ b/model/src/commonMain/kotlin/dev/datlag/burningseries/model/Series.kt @@ -12,6 +12,7 @@ data class Series( @SerialName("selectedLanguage") val selectedLanguage: String, @SerialName("seasons") val seasons: List, @SerialName("languages") val languages: List, + @SerialName("episodes") val episodes: List ) { val currentSeason: Season? by lazy(LazyThreadSafetyMode.NONE) { @@ -44,4 +45,11 @@ data class Series( @SerialName("value") val value: String, @SerialName("title") val title: String ) + + @Serializable + data class Episode( + @SerialName("number") val number: String, + @SerialName("title") val title: String, + @SerialName("href") val href: String + ) } \ No newline at end of file diff --git a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/scraper/BurningSeries.kt b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/scraper/BurningSeries.kt index 0266e253..103d159a 100644 --- a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/scraper/BurningSeries.kt +++ b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/scraper/BurningSeries.kt @@ -3,6 +3,7 @@ package dev.datlag.burningseries.network.scraper import dev.datlag.burningseries.model.BSUtil import dev.datlag.burningseries.model.Home import dev.datlag.burningseries.model.Series +import dev.datlag.burningseries.model.common.getDigitsOrNull import dev.datlag.burningseries.model.common.suspendCatching import dev.datlag.burningseries.network.common.getHref import dev.datlag.burningseries.network.common.getSrc @@ -170,13 +171,39 @@ data object BurningSeries { val selectedSeason = if (splitTitle.size >= 2) splitTitle[1].trim() else seasons.firstOrNull()?.title ?: String() + val episodesDoc = doc.querySelector(".serie")?.querySelector(".episodes")?.querySelectorAll("tr") ?: emptyList() + val episodeInfoList = episodesDoc.mapNotNull { episodesElement -> + val episodeList = episodesElement.querySelectorAll("td").mapNotNull { it.querySelector("a") }.mapNotNull { data -> + val text = data.querySelector("a")?.textContent() ?: String() + val episodeHref = BSUtil.normalizeHref(data.querySelector("a")?.getHref() ?: String()) + + text.trim() to episodeHref + } + + val episodeHref = when { + episodeList.isEmpty() -> return@mapNotNull null + episodeList[0].second.isNotBlank() -> episodeList[0].second + episodeList.size > 1 && episodeList[1].second.isNotBlank() -> episodeList[1].second + else -> String() + } + + val episodeTitle = if (episodeList.size > 1) episodeList[1].first.trim() else String() + + Series.Episode( + number = episodeList[0].first.trim(), + title = episodeTitle, + href = episodeHref + ) + } + return Series( title = normalizedTitle.trim(), description = description, seasonTitle = selectedSeason.trim(), seasons = seasons, selectedLanguage = selectedLanguage?.trim() ?: return null, - languages = languages + languages = languages, + episodes = episodeInfoList ) }