Skip to content

Commit

Permalink
prepare next navigation implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed May 5, 2024
1 parent c8f53d7 commit 6fcc17a
Show file tree
Hide file tree
Showing 14 changed files with 345 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ import androidx.compose.ui.graphics.vector.ImageVector
import com.arkivanov.decompose.ExperimentalDecomposeApi
import com.arkivanov.decompose.router.pages.ChildPages
import com.arkivanov.decompose.value.Value
import dev.datlag.aniflow.anilist.type.MediaType
import dev.datlag.aniflow.ui.navigation.Component
import dev.icerock.moko.resources.StringResource
import kotlinx.coroutines.flow.Flow

interface InitialComponent : Component {

val viewing: Flow<MediaType>
val pagerItems: List<PagerItem>
val selectedPage: Value<Int>

@OptIn(ExperimentalDecomposeApi::class)
val pages: Value<ChildPages<View, Component>>

fun selectPage(index: Int)
fun viewAnime()
fun viewManga()

data class PagerItem(
val label: StringResource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.datlag.aniflow.ui.navigation.screen.initial

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Settings
import androidx.compose.runtime.Composable
Expand All @@ -12,27 +13,39 @@ import com.arkivanov.decompose.value.Value
import com.arkivanov.decompose.value.operator.map
import dev.datlag.aniflow.SharedRes
import dev.datlag.aniflow.anilist.model.Medium
import dev.datlag.aniflow.anilist.type.MediaType
import dev.datlag.aniflow.common.onRender
import dev.datlag.aniflow.model.coroutines.Executor
import dev.datlag.aniflow.settings.Settings
import dev.datlag.aniflow.ui.navigation.Component
import dev.datlag.aniflow.ui.navigation.ContentHolderComponent
import dev.datlag.aniflow.ui.navigation.screen.initial.favorites.FavoritesScreenComponent
import dev.datlag.aniflow.ui.navigation.screen.initial.home.HomeScreenComponent
import dev.datlag.aniflow.ui.navigation.screen.initial.settings.SettingsScreenComponent
import kotlinx.coroutines.flow.map
import org.kodein.di.DI
import org.kodein.di.instance

class InitialScreenComponent(
componentContext: ComponentContext,
override val di: DI,
private val onMediumDetails: (Medium) -> Unit
) : InitialComponent, ComponentContext by componentContext {

private val appSettings by di.instance<Settings.PlatformAppSettings>()

override val pagerItems: List<InitialComponent.PagerItem> = listOf(
InitialComponent.PagerItem(
label = SharedRes.strings.profile,
icon = Icons.Filled.AccountCircle
),
InitialComponent.PagerItem(
label = SharedRes.strings.home,
icon = Icons.Default.Home
),
InitialComponent.PagerItem(
label = SharedRes.strings.settings,
icon = Icons.Filled.AccountCircle
label = SharedRes.strings.favorites,
icon = Icons.Filled.Favorite
)
)

Expand All @@ -46,10 +59,11 @@ class InitialScreenComponent(
initialPages = {
Pages(
items = listOf(
View.Settings,
View.Home,
View.Settings
View.Favorites
),
selectedIndex = 0
selectedIndex = 1
)
},
childFactory = ::createChild
Expand All @@ -58,6 +72,16 @@ class InitialScreenComponent(
@OptIn(ExperimentalDecomposeApi::class)
override val selectedPage: Value<Int> = pages.map { it.selectedIndex }

private val viewTypeExecutor = Executor()

override val viewing = appSettings.viewManga.map {
if (it) {
MediaType.MANGA
} else {
MediaType.ANIME
}
}

@Composable
override fun render() {
onRender {
Expand All @@ -79,6 +103,10 @@ class InitialScreenComponent(
componentContext = componentContext,
di = di
)
is View.Favorites -> FavoritesScreenComponent(
componentContext = componentContext,
di = di
)
}
}

Expand All @@ -90,4 +118,20 @@ class InitialScreenComponent(
}
}
}

override fun viewAnime() {
launchIO {
viewTypeExecutor.enqueue {
appSettings.setViewManga(false)
}
}
}

override fun viewManga() {
launchIO {
viewTypeExecutor.enqueue {
appSettings.setViewManga(true)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ sealed class View {

@Serializable
data object Settings : View()

@Serializable
data object Favorites : View()
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package dev.datlag.aniflow.ui.navigation.screen.initial.component

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.MenuBook
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.CameraEnhance
import androidx.compose.material.icons.filled.PlayCircleFilled
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import com.arkivanov.decompose.ExperimentalDecomposeApi
import com.arkivanov.decompose.extensions.compose.pages.Pages
import com.arkivanov.decompose.extensions.compose.subscribeAsState
Expand All @@ -21,16 +24,41 @@ import dev.datlag.aniflow.LocalHaze
import dev.datlag.aniflow.LocalPaddingValues
import dev.datlag.aniflow.common.isScrollingUp
import dev.datlag.aniflow.ui.navigation.screen.initial.InitialComponent
import dev.datlag.aniflow.ui.navigation.screen.initial.home.component.CollapsingToolbar
import dev.datlag.aniflow.ui.navigation.screen.initial.model.FABConfig
import dev.icerock.moko.resources.compose.stringResource

@OptIn(ExperimentalFoundationApi::class, ExperimentalDecomposeApi::class, ExperimentalHazeMaterialsApi::class)
@OptIn(ExperimentalFoundationApi::class, ExperimentalDecomposeApi::class, ExperimentalHazeMaterialsApi::class,
ExperimentalMaterial3Api::class
)
@Composable
fun CompactScreen(component: InitialComponent) {
val selectedPage by component.selectedPage.subscribeAsState()
val appBarState = rememberTopAppBarState()
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
state = appBarState
)

Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
CollapsingToolbar(
state = appBarState,
scrollBehavior = scrollBehavior,
viewTypeFlow = component.viewing,
onProfileClick = {

},
onAnimeClick = {
component.viewAnime()
},
onMangaClick = {
component.viewManga()
}
)
},
bottomBar = {
val selectedPage by component.selectedPage.subscribeAsState()

NavigationBar(
modifier = Modifier.hazeChild(
state = LocalHaze.current,
Expand Down Expand Up @@ -89,6 +117,8 @@ fun CompactScreen(component: InitialComponent) {
Box(
modifier = Modifier.fillMaxSize()
) {
val selectedPage by component.selectedPage.subscribeAsState()

Pages(
pages = component.pages,
onPageSelected = { index ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dev.datlag.aniflow.ui.navigation.screen.initial.favorites

import dev.datlag.aniflow.ui.navigation.Component

interface FavoritesComponent : Component {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.datlag.aniflow.ui.navigation.screen.initial.favorites

import androidx.compose.runtime.Composable

@Composable
fun FavoritesScreen(component: FavoritesComponent) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.datlag.aniflow.ui.navigation.screen.initial.favorites

import androidx.compose.runtime.Composable
import com.arkivanov.decompose.ComponentContext
import dev.datlag.aniflow.common.onRender
import org.kodein.di.DI

class FavoritesScreenComponent(
componentContext: ComponentContext,
override val di: DI
) : FavoritesComponent, ComponentContext by componentContext {

@Composable
override fun render() {
onRender {
FavoritesScreen(this)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import kotlinx.coroutines.flow.StateFlow
import dev.datlag.aniflow.settings.model.TitleLanguage as SettingsTitle

interface HomeComponent : ContentHolderComponent {
val viewing: Flow<MediaType>
val titleLanguage: Flow<SettingsTitle?>

val airingState: Flow<AiringTodayRepository.State>
Expand All @@ -31,6 +30,4 @@ interface HomeComponent : ContentHolderComponent {

fun details(medium: Medium)
fun trace(channel: ByteArray)
fun viewAnime()
fun viewManga()
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,76 +140,26 @@ private fun MainView(component: HomeComponent, modifier: Modifier = Modifier) {
else -> { }
}

val type by component.viewing.collectAsStateWithLifecycle(MediaType.UNKNOWN__)
val isManga = remember(type) {
type == MediaType.MANGA
}

LazyColumn(
state = listState,
modifier = modifier.haze(state = LocalHaze.current),
contentPadding = LocalPaddingValues.current?.plus(padding) ?: padding,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
item {
Box(
modifier = Modifier.fillParentMaxWidth().height(200.dp),
contentAlignment = Alignment.BottomEnd
) {
Row(
modifier = Modifier.padding(16.dp).background(Color.Black.copy(alpha = 0.3F), CircleShape),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround
) {
IconButton(
onClick = {
component.viewAnime()
}
) {
Icon(
imageVector = Icons.Default.PlayCircleFilled,
contentDescription = null,
tint = if (isManga) {
LocalContentColor.current
} else {
MaterialTheme.colorScheme.primary
}
)
}
IconButton(
onClick = {
component.viewManga()
}
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.MenuBook,
contentDescription = null,
tint = if (isManga) {
MaterialTheme.colorScheme.primary
} else {
LocalContentColor.current
}
)
}
}
}
Text(
modifier = Modifier.padding(horizontal = 16.dp),
text = "Schedule",
style = MaterialTheme.typography.headlineMedium,
fontWeight = FontWeight.Bold
)
}
if (!isManga) {
item {
Text(
modifier = Modifier.padding(horizontal = 16.dp),
text = "Schedule",
style = MaterialTheme.typography.headlineMedium,
fontWeight = FontWeight.Bold
)
}
item {
AiringOverview(
state = component.airingState,
titleLanguage = titleLanguage,
onClick = component::details
)
}
item {
AiringOverview(
state = component.airingState,
titleLanguage = titleLanguage,
onClick = component::details
)
}
item {
Text(
Expand Down
Loading

0 comments on commit 6fcc17a

Please sign in to comment.