diff --git a/composeApp/src/androidMain/kotlin/dev/datlag/aniflow/App.kt b/composeApp/src/androidMain/kotlin/dev/datlag/aniflow/App.kt index 21a429b..378a1cc 100644 --- a/composeApp/src/androidMain/kotlin/dev/datlag/aniflow/App.kt +++ b/composeApp/src/androidMain/kotlin/dev/datlag/aniflow/App.kt @@ -1,6 +1,7 @@ package dev.datlag.aniflow import android.content.Context +import android.os.StrictMode import androidx.multidex.MultiDexApplication import coil3.ImageLoader import coil3.SingletonImageLoader @@ -27,6 +28,14 @@ class App : MultiDexApplication(), DIAware { super.onCreate() if (BuildConfig.DEBUG) { + StrictMode.setThreadPolicy( + StrictMode.ThreadPolicy.Builder() + .detectAll() + .permitDiskReads() + .penaltyLog() + .penaltyDialog() + .build() + ) Napier.base(DebugAntilog()) } StateSaver.sekretLibraryLoaded = NativeLoader.loadLibrary("sekret") diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootComponent.kt index 9f176e1..e3f5566 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootComponent.kt @@ -8,6 +8,7 @@ import androidx.compose.ui.layout.layout import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.ExperimentalDecomposeApi import com.arkivanov.decompose.extensions.compose.stack.Children +import com.arkivanov.decompose.extensions.compose.stack.animation.fade import com.arkivanov.decompose.extensions.compose.stack.animation.predictiveback.predictiveBackAnimation import com.arkivanov.decompose.extensions.compose.stack.animation.slide import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation @@ -16,11 +17,12 @@ import com.arkivanov.decompose.router.stack.* import dev.datlag.aniflow.common.onRender import dev.datlag.aniflow.model.ifValueOrNull import dev.datlag.aniflow.other.UserHelper +import dev.datlag.aniflow.ui.navigation.screen.favorites.FavoritesScreenComponent import dev.datlag.aniflow.ui.navigation.screen.home.HomeScreenComponent -import dev.datlag.aniflow.ui.navigation.screen.initial.InitialScreenComponent import dev.datlag.aniflow.ui.navigation.screen.medium.MediumScreenComponent import dev.datlag.aniflow.ui.navigation.screen.settings.SettingsScreen import dev.datlag.aniflow.ui.navigation.screen.settings.SettingsScreenComponent +import dev.datlag.aniflow.ui.navigation.screen.wallpaper.WallpaperScreenComponent import io.github.aakira.napier.Napier import org.kodein.di.DI import org.kodein.di.instance @@ -52,6 +54,12 @@ class RootComponent( }, onProfile = { navigation.push(RootConfig.Settings) + }, + onWallpaper = { + navigation.replaceCurrent(RootConfig.Wallpaper) + }, + onFavorites = { + navigation.replaceCurrent(RootConfig.Favorites) } ) is RootConfig.Details -> MediumScreenComponent( @@ -64,6 +72,26 @@ class RootComponent( componentContext = componentContext, di = di ) + is RootConfig.Favorites -> FavoritesScreenComponent( + componentContext = componentContext, + di = di, + onWallpaper = { + navigation.replaceCurrent(RootConfig.Wallpaper) + }, + onHome = { + navigation.replaceCurrent(RootConfig.Home) + } + ) + is RootConfig.Wallpaper -> WallpaperScreenComponent( + componentContext = componentContext, + di = di, + onHome = { + navigation.replaceCurrent(RootConfig.Home) + }, + onFavorites = { + navigation.replaceCurrent(RootConfig.Favorites) + } + ) } } @@ -75,40 +103,7 @@ class RootComponent( stack = stack, animation = predictiveBackAnimation( backHandler = this.backHandler, - fallbackAnimation = stackAnimation { child -> - when (child.configuration) { - is RootConfig.Settings -> stackAnimator(tween()) { factor, _, content -> - content( - Modifier.layout { measurable, constraints -> - val placeable = measurable.measure(constraints) - - layout(placeable.width, placeable.height) { - placeable.placeRelative(y = -(placeable.height.toFloat() * factor).toInt(), x = 0) - } - } - ) - } - is RootConfig.Home -> { - val current = stack.value.active - - when (current.configuration) { - is RootConfig.Settings -> stackAnimator(tween()) { factor, _, content -> - content( - Modifier.layout { measurable, constraints -> - val placeable = measurable.measure(constraints) - - layout(placeable.width, placeable.height) { - placeable.placeRelative(y = -(placeable.height.toFloat() * factor).toInt(), x = 0) - } - } - ) - } - else -> slide() - } - } - else -> slide() - } - }, + fallbackAnimation = stackAnimation(fade()), onBack = { navigation.pop() } diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootConfig.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootConfig.kt index 78858a3..38a9df0 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootConfig.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootConfig.kt @@ -16,4 +16,10 @@ sealed class RootConfig { @Serializable data object Settings : RootConfig() + + @Serializable + data object Favorites : RootConfig() + + @Serializable + data object Wallpaper : RootConfig() } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/component/HidingNavigationBar.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/component/HidingNavigationBar.kt index 8c2daf2..764d728 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/component/HidingNavigationBar.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/component/HidingNavigationBar.kt @@ -9,10 +9,17 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.FavoriteBorder import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Wallpaper +import androidx.compose.material.icons.outlined.Home +import androidx.compose.material.icons.rounded.Favorite +import androidx.compose.material.icons.rounded.FavoriteBorder +import androidx.compose.material.icons.rounded.Home +import androidx.compose.material.icons.rounded.Wallpaper import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import dev.chrisbanes.haze.hazeChild @@ -21,12 +28,19 @@ import dev.chrisbanes.haze.materials.HazeMaterials import dev.datlag.aniflow.LocalHaze import dev.datlag.aniflow.SharedRes import dev.datlag.aniflow.common.isScrollingUp +import dev.datlag.aniflow.ui.navigation.RootConfig import dev.icerock.moko.resources.compose.stringResource +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient @OptIn(ExperimentalHazeMaterialsApi::class) @Composable fun HidingNavigationBar( visible: Boolean, + selected: NavigationBarState, + onWallpaper: () -> Unit, + onHome: () -> Unit, + onFavorites: () -> Unit ) { val density = LocalDensity.current @@ -58,11 +72,32 @@ fun HidingNavigationBar( contentColor = MaterialTheme.colorScheme.contentColorFor(NavigationBarDefaults.containerColor) ) { NavigationBarItem( - onClick = { }, - selected = true, + onClick = { + if (selected !is NavigationBarState.Wallpaper) { + onWallpaper() + } + }, + selected = selected is NavigationBarState.Wallpaper, + icon = { + Icon( + imageVector = selected.wallpaperIcon, + contentDescription = null + ) + }, + label = { + Text(text = "Wallpapers") + } + ) + NavigationBarItem( + onClick = { + if (selected !is NavigationBarState.Home) { + onHome() + } + }, + selected = selected is NavigationBarState.Home, icon = { Icon( - imageVector = Icons.Filled.Home, + imageVector = selected.homeIcon, contentDescription = null ) }, @@ -71,11 +106,15 @@ fun HidingNavigationBar( } ) NavigationBarItem( - onClick = { }, - selected = false, + onClick = { + if (selected !is NavigationBarState.Favorite) { + onFavorites() + } + }, + selected = selected is NavigationBarState.Favorite, icon = { Icon( - imageVector = Icons.Default.FavoriteBorder, + imageVector = selected.favoriteIcon, contentDescription = null ) }, @@ -85,4 +124,56 @@ fun HidingNavigationBar( ) } } +} + +@Serializable +sealed interface NavigationBarState { + @Transient + val unselectedIcon: ImageVector + + @Transient + val selectedIcon: ImageVector + get() = unselectedIcon + + val wallpaperIcon: ImageVector + get() = when (this) { + is Wallpaper -> selectedIcon + else -> Wallpaper.unselectedIcon + } + + val homeIcon: ImageVector + get() = when (this) { + is Home -> selectedIcon + else -> Home.unselectedIcon + } + + val favoriteIcon: ImageVector + get() = when (this) { + is Favorite -> selectedIcon + else -> Favorite.unselectedIcon + } + + @Serializable + data object Wallpaper : NavigationBarState { + override val unselectedIcon: ImageVector + get() = Icons.Rounded.Wallpaper + } + + @Serializable + data object Home : NavigationBarState { + override val unselectedIcon: ImageVector + get() = Icons.Outlined.Home + + override val selectedIcon: ImageVector + get() = Icons.Rounded.Home + } + + @Serializable + data object Favorite : NavigationBarState { + override val unselectedIcon: ImageVector + get() = Icons.Rounded.FavoriteBorder + + override val selectedIcon: ImageVector + get() = Icons.Rounded.Favorite + } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesComponent.kt new file mode 100644 index 0000000..82f11f0 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesComponent.kt @@ -0,0 +1,9 @@ +package dev.datlag.aniflow.ui.navigation.screen.favorites + +import dev.datlag.aniflow.ui.navigation.Component + +interface FavoritesComponent : Component { + + fun viewWallpaper() + fun viewHome() +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesScreen.kt new file mode 100644 index 0000000..302de11 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesScreen.kt @@ -0,0 +1,23 @@ +package dev.datlag.aniflow.ui.navigation.screen.favorites + +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import dev.datlag.aniflow.ui.navigation.screen.component.HidingNavigationBar +import dev.datlag.aniflow.ui.navigation.screen.component.NavigationBarState + +@Composable +fun FavoritesScreen(component: FavoritesComponent) { + Scaffold( + bottomBar = { + HidingNavigationBar( + visible = true, + selected = NavigationBarState.Favorite, + onWallpaper = component::viewWallpaper, + onHome = component::viewHome, + onFavorites = { } + ) + } + ) { + + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesScreenComponent.kt new file mode 100644 index 0000000..253b917 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/favorites/FavoritesScreenComponent.kt @@ -0,0 +1,39 @@ +package dev.datlag.aniflow.ui.navigation.screen.favorites + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember +import com.arkivanov.decompose.ComponentContext +import dev.chrisbanes.haze.HazeState +import dev.datlag.aniflow.LocalHaze +import dev.datlag.aniflow.common.onRender +import org.kodein.di.DI + +class FavoritesScreenComponent( + componentContext: ComponentContext, + override val di: DI, + private val onWallpaper: () -> Unit, + private val onHome: () -> Unit, +) : FavoritesComponent, ComponentContext by componentContext { + + @Composable + override fun render() { + val haze = remember { HazeState() } + + CompositionLocalProvider( + LocalHaze provides haze + ) { + onRender { + FavoritesScreen(this) + } + } + } + + override fun viewWallpaper() { + onWallpaper() + } + + override fun viewHome() { + onHome() + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeComponent.kt index df11915..0069afc 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeComponent.kt @@ -22,6 +22,8 @@ interface HomeComponent : Component { fun viewProfile() fun viewAnime() fun viewManga() + fun viewWallpaper() + fun viewFavorites() fun details(medium: Medium) fun trace(byteArray: ByteArray) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeScreen.kt index 2ef4cc1..b504b1c 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeScreen.kt @@ -6,24 +6,28 @@ import androidx.compose.animation.core.LinearOutSlowInEasing import androidx.compose.animation.core.tween import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CameraEnhance import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember +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 androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import com.maxkeppeker.sheets.core.models.base.Header +import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState +import com.maxkeppeler.sheets.option.OptionDialog +import com.maxkeppeler.sheets.option.models.DisplayMode +import com.maxkeppeler.sheets.option.models.Option +import com.maxkeppeler.sheets.option.models.OptionConfig +import com.maxkeppeler.sheets.option.models.OptionSelection import dev.chrisbanes.haze.haze import dev.chrisbanes.haze.hazeChild import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi @@ -31,17 +35,18 @@ import dev.chrisbanes.haze.materials.HazeMaterials import dev.datlag.aniflow.LocalHaze import dev.datlag.aniflow.LocalPaddingValues import dev.datlag.aniflow.anilist.type.MediaType -import dev.datlag.aniflow.common.LocalPadding -import dev.datlag.aniflow.common.isScrollingUp +import dev.datlag.aniflow.common.* import dev.datlag.aniflow.other.StateSaver import dev.datlag.aniflow.other.rememberImagePickerState import dev.datlag.aniflow.trace.TraceRepository import dev.datlag.aniflow.ui.navigation.screen.component.CollapsingToolbar import dev.datlag.aniflow.ui.navigation.screen.component.HidingNavigationBar +import dev.datlag.aniflow.ui.navigation.screen.component.NavigationBarState import dev.datlag.aniflow.ui.navigation.screen.home.component.AllLoadingView import dev.datlag.aniflow.ui.navigation.screen.home.component.DefaultOverview import dev.datlag.aniflow.ui.navigation.screen.home.component.ScheduleOverview import dev.datlag.tooling.decompose.lifecycle.collectAsStateWithLifecycle +import io.github.aakira.napier.Napier @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -69,6 +74,48 @@ fun HomeScreen(component: HomeComponent) { }, floatingActionButton = { val traceState by component.traceState.collectAsStateWithLifecycle(TraceRepository.State.None) + val results = remember(traceState) { + (traceState as? TraceRepository.State.Success)?.response?.combinedResults.orEmpty().toList() + } + + val dialogState = rememberUseCaseState( + visible = results.isNotEmpty(), + onCloseRequest = { component.clearTrace() }, + onDismissRequest = { component.clearTrace() }, + onFinishedRequest = { component.clearTrace() } + ) + + LaunchedEffect(results) { + if (results.isNotEmpty()) { + dialogState.show() + } + } + + OptionDialog( + state = dialogState, + config = OptionConfig( + mode = DisplayMode.LIST + ), + header = Header.Custom { padding -> + Text( + modifier = Modifier.padding(padding.merge(PaddingValues(16.dp))).fillMaxWidth(), + text = "Matching Anime", + textAlign = TextAlign.Center, + fontWeight = FontWeight.SemiBold, + style = MaterialTheme.typography.titleLarge + ) + }, + selection = OptionSelection.Single( + options = results.map { + Option( + titleText = it.aniList.asMedium().preferred(null) + ) + }, + onSelectOption = { option, _ -> + component.details(results[option].aniList.asMedium()) + } + ) + ) ExtendedFloatingActionButton( onClick = { @@ -88,7 +135,11 @@ fun HomeScreen(component: HomeComponent) { }, bottomBar = { HidingNavigationBar( - visible = listState.isScrollingUp() && listState.canScrollForward + visible = listState.isScrollingUp() && listState.canScrollForward, + selected = NavigationBarState.Home, + onWallpaper = component::viewWallpaper, + onHome = { }, + onFavorites = component::viewFavorites ) } ) { diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeScreenComponent.kt index 52b3121..74886e3 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/home/HomeScreenComponent.kt @@ -30,7 +30,9 @@ class HomeScreenComponent( componentContext: ComponentContext, override val di: DI, private val onMediumDetails: (Medium) -> Unit, - private val onProfile: () -> Unit + private val onProfile: () -> Unit, + private val onWallpaper: () -> Unit, + private val onFavorites: () -> Unit ) : HomeComponent, ComponentContext by componentContext { private val appSettings by instance() @@ -122,6 +124,14 @@ class HomeScreenComponent( } } + override fun viewWallpaper() { + onWallpaper() + } + + override fun viewFavorites() { + onFavorites() + } + override fun details(medium: Medium) { onMediumDetails(medium) } diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialComponent.kt deleted file mode 100644 index 62a22bd..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialComponent.kt +++ /dev/null @@ -1,29 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial - -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 - val pagerItems: List - val selectedPage: Value - - @OptIn(ExperimentalDecomposeApi::class) - val pages: Value> - - fun selectPage(index: Int) - fun viewProfile() - fun viewAnime() - fun viewManga() - - data class PagerItem( - val label: StringResource, - val icon: ImageVector - ) -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialScreen.kt deleted file mode 100644 index 35ce9fa..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialScreen.kt +++ /dev/null @@ -1,41 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi -import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass -import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import com.arkivanov.decompose.ExperimentalDecomposeApi -import com.arkivanov.decompose.extensions.compose.pages.Pages -import dev.chrisbanes.haze.HazeState -import dev.datlag.aniflow.LocalHaze -import dev.datlag.aniflow.ui.navigation.screen.initial.component.CompactScreen -import dev.datlag.aniflow.ui.navigation.screen.initial.component.ExpandedScreen -import dev.datlag.aniflow.ui.navigation.screen.initial.component.MediumScreen - -@OptIn(ExperimentalFoundationApi::class, ExperimentalDecomposeApi::class, - ExperimentalMaterial3WindowSizeClassApi::class -) -@Composable -fun InitialScreen(component: InitialComponent) { - val haze = remember { HazeState() } - - CompositionLocalProvider( - LocalHaze provides haze - ) { - Box( - modifier = Modifier.fillMaxSize() - ) { - when (calculateWindowSizeClass().widthSizeClass) { - WindowWidthSizeClass.Compact -> CompactScreen(component) - WindowWidthSizeClass.Medium -> MediumScreen(component) - WindowWidthSizeClass.Expanded -> ExpandedScreen(component) - } - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialScreenComponent.kt deleted file mode 100644 index 74c8091..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/InitialScreenComponent.kt +++ /dev/null @@ -1,128 +0,0 @@ -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 -import com.arkivanov.decompose.ComponentContext -import com.arkivanov.decompose.ExperimentalDecomposeApi -import com.arkivanov.decompose.router.pages.* -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.other.StateSaver -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.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, - private val onProfile: () -> Unit -) : InitialComponent, ComponentContext by componentContext { - - private val appSettings by di.instance() - - override val pagerItems: List = listOf( - InitialComponent.PagerItem( - label = SharedRes.strings.home, - icon = Icons.Default.Home - ), - InitialComponent.PagerItem( - label = SharedRes.strings.favorites, - icon = Icons.Filled.Favorite - ) - ) - - @OptIn(ExperimentalDecomposeApi::class) - private val pagesNavigation = PagesNavigation() - - @OptIn(ExperimentalDecomposeApi::class) - override val pages: Value> = childPages( - source = pagesNavigation, - serializer = View.serializer(), - initialPages = { - Pages( - items = listOf( - View.Home, - View.Favorites - ), - selectedIndex = 0 - ) - }, - childFactory = ::createChild - ) - - @OptIn(ExperimentalDecomposeApi::class) - override val selectedPage: Value = 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 { - InitialScreen(this) - } - } - - private fun createChild( - view: View, - componentContext: ComponentContext - ): Component { - return FavoritesScreenComponent( - componentContext = componentContext, - di = di - ) - } - - @OptIn(ExperimentalDecomposeApi::class) - override fun selectPage(index: Int) { - pagesNavigation.select(index = index) { new, old -> - if (new.items[new.selectedIndex] == old.items[old.selectedIndex]) { - (pages.value.items[pages.value.selectedIndex].instance as? ContentHolderComponent)?.dismissContent() - } - } - } - - override fun viewProfile() { - onProfile() - } - - override fun viewAnime() { - StateSaver.Home.updateAllLoading() - launchIO { - viewTypeExecutor.enqueue { - appSettings.setViewManga(false) - } - } - } - - override fun viewManga() { - StateSaver.Home.updateAllLoading() - launchIO { - viewTypeExecutor.enqueue { - appSettings.setViewManga(true) - } - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/View.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/View.kt deleted file mode 100644 index 4ac5437..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/View.kt +++ /dev/null @@ -1,12 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial - -import kotlinx.serialization.Serializable - -@Serializable -sealed class View { - @Serializable - data object Home : View() - - @Serializable - data object Favorites : View() -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/CompactScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/CompactScreen.kt deleted file mode 100644 index a30a800..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/CompactScreen.kt +++ /dev/null @@ -1,140 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial.component - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.CameraEnhance -import androidx.compose.material3.* -import androidx.compose.runtime.* -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 -import dev.chrisbanes.haze.hazeChild -import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi -import dev.chrisbanes.haze.materials.HazeMaterials -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.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, - ExperimentalMaterial3Api::class -) -@Composable -fun CompactScreen(component: InitialComponent) { - 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 = { - component.viewProfile() - }, - onAnimeClick = { - component.viewAnime() - }, - onMangaClick = { - component.viewManga() - } - ) - }, - bottomBar = { - val selectedPage by component.selectedPage.subscribeAsState() - - NavigationBar( - modifier = Modifier.hazeChild( - state = LocalHaze.current, - style = HazeMaterials.thin(NavigationBarDefaults.containerColor) - ).fillMaxWidth(), - containerColor = Color.Transparent, - contentColor = MaterialTheme.colorScheme.contentColorFor(NavigationBarDefaults.containerColor) - ) { - component.pagerItems.forEachIndexed { index, pagerItem -> - NavigationBarItem( - selected = selectedPage == index, - icon = { - NavIcon(pagerItem) - }, - onClick = { - component.selectPage(index) - }, - label = { - Text(text = stringResource(pagerItem.label)) - }, - alwaysShowLabel = true - ) - } - } - }, - floatingActionButton = { - val state by FABConfig.state - - when (val current = state) { - is FABConfig.Scan -> { - if (!current.loading) { - ExtendedFloatingActionButton( - onClick = current.onClick, - icon = { - Icon( - imageVector = Icons.Filled.CameraEnhance, - contentDescription = null - ) - }, - text = { - Text( - text = "Scan" - ) - }, - expanded = current.listState.isScrollingUp(), - ) - } - } - else -> { } - } - } - ) { - CompositionLocalProvider( - LocalPaddingValues provides it - ) { - Box( - modifier = Modifier.fillMaxSize() - ) { - val selectedPage by component.selectedPage.subscribeAsState() - - Pages( - pages = component.pages, - onPageSelected = { index -> - if (selectedPage != index) { - component.selectPage(index) - } - }, - pager = { modifier, pagerState, key, pageContent -> - HorizontalPager( - modifier = modifier, - state = pagerState, - key = key, - pageContent = pageContent, - userScrollEnabled = false - ) - } - ) { _, page -> - page.render() - } - } - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/ExpandedScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/ExpandedScreen.kt deleted file mode 100644 index 621683c..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/ExpandedScreen.kt +++ /dev/null @@ -1,110 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial.component - -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.CameraEnhance -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.unit.dp -import com.arkivanov.decompose.ExperimentalDecomposeApi -import com.arkivanov.decompose.extensions.compose.subscribeAsState -import dev.datlag.aniflow.common.isScrollingUp -import dev.datlag.aniflow.ui.custom.ExpandedPages -import dev.datlag.aniflow.ui.navigation.screen.initial.InitialComponent -import dev.datlag.aniflow.ui.navigation.screen.component.CollapsingToolbar -import dev.datlag.aniflow.ui.navigation.screen.initial.model.FABConfig -import dev.datlag.tooling.compose.EndCornerShape -import dev.icerock.moko.resources.compose.stringResource - -@OptIn(ExperimentalDecomposeApi::class, ExperimentalMaterial3Api::class) -@Composable -fun ExpandedScreen(component: InitialComponent) { - 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 = { - component.viewProfile() - }, - onAnimeClick = { - component.viewAnime() - }, - onMangaClick = { - component.viewManga() - } - ) - }, - floatingActionButton = { - val state by FABConfig.state - - when (val current = state) { - is FABConfig.Scan -> { - if (!current.loading) { - ExtendedFloatingActionButton( - onClick = current.onClick, - icon = { - Icon( - imageVector = Icons.Filled.CameraEnhance, - contentDescription = null - ) - }, - text = { - Text( - text = "Scan" - ) - }, - expanded = current.listState.isScrollingUp(), - ) - } - } - else -> { } - } - } - ) { - PermanentNavigationDrawer( - modifier = Modifier.padding(it), - drawerContent = { - PermanentDrawerSheet( - drawerShape = EndCornerShape(otherCorner = 0.dp) - ) { - val selectedPage by component.selectedPage.subscribeAsState() - - Spacer(modifier = Modifier.weight(1F)) - component.pagerItems.forEachIndexed { index, pagerItem -> - NavigationDrawerItem( - selected = selectedPage == index, - icon = { - NavIcon(pagerItem) - }, - onClick = { - component.selectPage(index) - }, - label = { - Text(text = stringResource(pagerItem.label)) - } - ) - } - Spacer(modifier = Modifier.weight(1F)) - } - } - ) { - ExpandedPages( - pages = component.pages - ) { _, page -> - page.render() - } - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/MediumScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/MediumScreen.kt deleted file mode 100644 index db72d58..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/MediumScreen.kt +++ /dev/null @@ -1,107 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial.component - -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.CameraEnhance -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.nestedScroll -import com.arkivanov.decompose.ExperimentalDecomposeApi -import com.arkivanov.decompose.extensions.compose.subscribeAsState -import dev.datlag.aniflow.common.isScrollingUp -import dev.datlag.aniflow.ui.custom.ExpandedPages -import dev.datlag.aniflow.ui.navigation.screen.initial.InitialComponent -import dev.datlag.aniflow.ui.navigation.screen.component.CollapsingToolbar -import dev.datlag.aniflow.ui.navigation.screen.initial.model.FABConfig -import dev.icerock.moko.resources.compose.stringResource - -@OptIn(ExperimentalDecomposeApi::class, ExperimentalMaterial3Api::class) -@Composable -fun MediumScreen(component: InitialComponent) { - 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 = { - component.viewProfile() - }, - onAnimeClick = { - component.viewAnime() - }, - onMangaClick = { - component.viewManga() - } - ) - }, - floatingActionButton = { - val state by FABConfig.state - - when (val current = state) { - is FABConfig.Scan -> { - if (!current.loading) { - ExtendedFloatingActionButton( - onClick = current.onClick, - icon = { - Icon( - imageVector = Icons.Filled.CameraEnhance, - contentDescription = null - ) - }, - text = { - Text( - text = "Scan" - ) - }, - expanded = current.listState.isScrollingUp(), - ) - } - } - else -> { } - } - } - ) { - Row( - modifier = Modifier.padding(it) - ) { - NavigationRail { - val selectedPage by component.selectedPage.subscribeAsState() - - Spacer(modifier = Modifier.weight(1F)) - component.pagerItems.forEachIndexed { index, pagerItem -> - NavigationRailItem( - selected = selectedPage == index, - icon = { - NavIcon(pagerItem) - }, - onClick = { - component.selectPage(index) - }, - label = { - Text(text = stringResource(pagerItem.label)) - }, - alwaysShowLabel = true - ) - } - Spacer(modifier = Modifier.weight(1F)) - } - - ExpandedPages( - pages = component.pages - ) { _, page -> - page.render() - } - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/NavIcon.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/NavIcon.kt deleted file mode 100644 index 7395bff..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/component/NavIcon.kt +++ /dev/null @@ -1,20 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial.component - -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Icon -import androidx.compose.material3.LocalContentColor -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import dev.datlag.aniflow.ui.navigation.screen.initial.InitialComponent -import dev.icerock.moko.resources.compose.stringResource - -@Composable -fun NavIcon(item: InitialComponent.PagerItem) { - Icon( - imageVector = item.icon, - contentDescription = stringResource(item.label), - modifier = Modifier.size(24.dp), - tint = LocalContentColor.current - ) -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesComponent.kt deleted file mode 100644 index 7a9d4d5..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesComponent.kt +++ /dev/null @@ -1,6 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial.favorites - -import dev.datlag.aniflow.ui.navigation.Component - -interface FavoritesComponent : Component { -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesScreen.kt deleted file mode 100644 index d4857ad..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesScreen.kt +++ /dev/null @@ -1,8 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial.favorites - -import androidx.compose.runtime.Composable - -@Composable -fun FavoritesScreen(component: FavoritesComponent) { - -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesScreenComponent.kt deleted file mode 100644 index 4ed6fcc..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/favorites/FavoritesScreenComponent.kt +++ /dev/null @@ -1,19 +0,0 @@ -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) - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/model/FABConfig.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/model/FABConfig.kt deleted file mode 100644 index 7f79510..0000000 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/model/FABConfig.kt +++ /dev/null @@ -1,17 +0,0 @@ -package dev.datlag.aniflow.ui.navigation.screen.initial.model - -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.runtime.mutableStateOf - -sealed interface FABConfig { - - data class Scan( - val listState: LazyListState, - val loading: Boolean = false, - val onClick: () -> Unit - ) : FABConfig - - companion object { - val state = mutableStateOf(null) - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/settings/SettingsScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/settings/SettingsScreen.kt index 6c6278d..6c844ec 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/settings/SettingsScreen.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/settings/SettingsScreen.kt @@ -20,6 +20,7 @@ import dev.chrisbanes.haze.haze import dev.datlag.aniflow.LocalHaze import dev.datlag.aniflow.LocalPaddingValues import dev.datlag.aniflow.SharedRes +import dev.datlag.aniflow.common.merge import dev.datlag.aniflow.common.plus import dev.datlag.aniflow.other.Constants import dev.datlag.aniflow.other.StateSaver @@ -30,143 +31,145 @@ import dev.icerock.moko.resources.compose.painterResource @Composable fun SettingsScreen(component: SettingsComponent) { - val padding = PaddingValues(16.dp) - val listState = rememberLazyListState( - initialFirstVisibleItemIndex = StateSaver.List.settingsOverview, - initialFirstVisibleItemScrollOffset = StateSaver.List.settingsOverviewOffset - ) + Scaffold { + val padding = it.merge(PaddingValues(16.dp)) + val listState = rememberLazyListState( + initialFirstVisibleItemIndex = StateSaver.List.settingsOverview, + initialFirstVisibleItemScrollOffset = StateSaver.List.settingsOverviewOffset + ) - LazyColumn( - state = listState, - modifier = Modifier.fillMaxWidth(), - contentPadding = LocalPaddingValues.current?.plus(padding) ?: padding, - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - item { - UserSection( - userFlow = component.user, - loginUri = component.loginUri, - modifier = Modifier.fillParentMaxWidth() - ) - } - item { - ColorSection( - selectedColorFlow = component.selectedColor, - modifier = Modifier.fillParentMaxWidth(), - onChange = component::changeProfileColor - ) - } - item { - TitleSection( - titleFlow = component.selectedTitleLanguage, - modifier = Modifier.fillParentMaxWidth(), - onChange = component::changeTitleLanguage - ) - } - item { - CharacterSection( - characterFlow = component.selectedCharLanguage, - modifier = Modifier.fillParentMaxWidth(), - onChanged = component::changeCharLanguage - ) - } - item { - AdultSection( - adultFlow = component.adultContent, - modifier = Modifier.fillParentMaxWidth(), - onChange = component::changeAdultContent - ) - } - item { - DomainSection( - modifier = Modifier.fillParentMaxWidth() - ) - } - item { - val uriHandler = LocalUriHandler.current - val isLoggedIn by component.isLoggedIn.collectAsStateWithLifecycle(false) + LazyColumn( + state = listState, + modifier = Modifier.fillMaxWidth(), + contentPadding = padding, + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + item { + UserSection( + userFlow = component.user, + loginUri = component.loginUri, + modifier = Modifier.fillParentMaxWidth() + ) + } + item { + ColorSection( + selectedColorFlow = component.selectedColor, + modifier = Modifier.fillParentMaxWidth(), + onChange = component::changeProfileColor + ) + } + item { + TitleSection( + titleFlow = component.selectedTitleLanguage, + modifier = Modifier.fillParentMaxWidth(), + onChange = component::changeTitleLanguage + ) + } + item { + CharacterSection( + characterFlow = component.selectedCharLanguage, + modifier = Modifier.fillParentMaxWidth(), + onChanged = component::changeCharLanguage + ) + } + item { + AdultSection( + adultFlow = component.adultContent, + modifier = Modifier.fillParentMaxWidth(), + onChange = component::changeAdultContent + ) + } + item { + DomainSection( + modifier = Modifier.fillParentMaxWidth() + ) + } + item { + val uriHandler = LocalUriHandler.current + val isLoggedIn by component.isLoggedIn.collectAsStateWithLifecycle(false) - Row( - modifier = Modifier - .fillParentMaxWidth() - .defaultMinSize(minHeight = ButtonDefaults.MinHeight) - .clip(MaterialTheme.shapes.small) - .onClick { - if (isLoggedIn) { - component.logout() - } else { - uriHandler.openUri(component.loginUri) - } - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - if (isLoggedIn) { - Icon( - imageVector = Icons.Default.NotInterested, - contentDescription = null, - ) - Text(text = "Logout") - } else { + Row( + modifier = Modifier + .fillParentMaxWidth() + .defaultMinSize(minHeight = ButtonDefaults.MinHeight) + .clip(MaterialTheme.shapes.small) + .onClick { + if (isLoggedIn) { + component.logout() + } else { + uriHandler.openUri(component.loginUri) + } + }, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + if (isLoggedIn) { + Icon( + imageVector = Icons.Default.NotInterested, + contentDescription = null, + ) + Text(text = "Logout") + } else { + Image( + modifier = Modifier.size(24.dp).clip(CircleShape), + painter = painterResource(SharedRes.images.anilist), + contentDescription = null, + ) + Text(text = "Login") + } + } + } + item { + val uriHandler = LocalUriHandler.current + + Row( + modifier = Modifier + .fillParentMaxWidth() + .defaultMinSize(minHeight = ButtonDefaults.MinHeight) + .clip(MaterialTheme.shapes.small) + .onClick { + uriHandler.openUri(Constants.GITHUB_REPO) + }, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { Image( - modifier = Modifier.size(24.dp).clip(CircleShape), - painter = painterResource(SharedRes.images.anilist), + modifier = Modifier.size(24.dp), + painter = painterResource(SharedRes.images.github), contentDescription = null, + colorFilter = ColorFilter.tint(LocalContentColor.current) ) - Text(text = "Login") + Text(text = "GitHub Repository") } } - } - item { - val uriHandler = LocalUriHandler.current + item { + val uriHandler = LocalUriHandler.current - Row( - modifier = Modifier - .fillParentMaxWidth() - .defaultMinSize(minHeight = ButtonDefaults.MinHeight) - .clip(MaterialTheme.shapes.small) - .onClick { - uriHandler.openUri(Constants.GITHUB_REPO) - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Image( - modifier = Modifier.size(24.dp), - painter = painterResource(SharedRes.images.github), - contentDescription = null, - colorFilter = ColorFilter.tint(LocalContentColor.current) - ) - Text(text = "GitHub Repository") + Row( + modifier = Modifier + .fillParentMaxWidth() + .defaultMinSize(minHeight = ButtonDefaults.MinHeight) + .clip(MaterialTheme.shapes.medium) + .onClick { + uriHandler.openUri(Constants.GITHUB_OWNER) + }, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + imageVector = Icons.Default.Code, + contentDescription = null, + ) + Text(text = "Developed by DatLag") + } } } - item { - val uriHandler = LocalUriHandler.current - Row( - modifier = Modifier - .fillParentMaxWidth() - .defaultMinSize(minHeight = ButtonDefaults.MinHeight) - .clip(MaterialTheme.shapes.medium) - .onClick { - uriHandler.openUri(Constants.GITHUB_OWNER) - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Icon( - imageVector = Icons.Default.Code, - contentDescription = null, - ) - Text(text = "Developed by DatLag") + DisposableEffect(listState) { + onDispose { + StateSaver.List.settingsOverview = listState.firstVisibleItemIndex + StateSaver.List.settingsOverviewOffset = listState.firstVisibleItemScrollOffset } } } - - DisposableEffect(listState) { - onDispose { - StateSaver.List.settingsOverview = listState.firstVisibleItemIndex - StateSaver.List.settingsOverviewOffset = listState.firstVisibleItemScrollOffset - } - } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperComponent.kt new file mode 100644 index 0000000..02759b7 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperComponent.kt @@ -0,0 +1,9 @@ +package dev.datlag.aniflow.ui.navigation.screen.wallpaper + +import dev.datlag.aniflow.ui.navigation.Component + +interface WallpaperComponent : Component { + + fun viewHome() + fun viewFavorites() +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperScreen.kt new file mode 100644 index 0000000..860bf45 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperScreen.kt @@ -0,0 +1,23 @@ +package dev.datlag.aniflow.ui.navigation.screen.wallpaper + +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import dev.datlag.aniflow.ui.navigation.screen.component.HidingNavigationBar +import dev.datlag.aniflow.ui.navigation.screen.component.NavigationBarState + +@Composable +fun WallpaperScreen(component: WallpaperComponent) { + Scaffold( + bottomBar = { + HidingNavigationBar( + visible = true, + selected = NavigationBarState.Wallpaper, + onWallpaper = { }, + onHome = component::viewHome, + onFavorites = component::viewFavorites + ) + } + ) { + + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperScreenComponent.kt new file mode 100644 index 0000000..98ea7bc --- /dev/null +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/wallpaper/WallpaperScreenComponent.kt @@ -0,0 +1,39 @@ +package dev.datlag.aniflow.ui.navigation.screen.wallpaper + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember +import com.arkivanov.decompose.ComponentContext +import dev.chrisbanes.haze.HazeState +import dev.datlag.aniflow.LocalHaze +import dev.datlag.aniflow.common.onRender +import org.kodein.di.DI + +class WallpaperScreenComponent( + componentContext: ComponentContext, + override val di: DI, + private val onHome: () -> Unit, + private val onFavorites: () -> Unit, +) : WallpaperComponent, ComponentContext by componentContext { + + @Composable + override fun render() { + val haze = remember { HazeState() } + + CompositionLocalProvider( + LocalHaze provides haze + ) { + onRender { + WallpaperScreen(this) + } + } + } + + override fun viewHome() { + onHome() + } + + override fun viewFavorites() { + onFavorites() + } +} \ No newline at end of file