Skip to content

Commit

Permalink
Merge pull request Kaaveh#235 from rezazarchi/adaptive-new-lib
Browse files Browse the repository at this point in the history
Refactoring for adaptive layouts new implementation
  • Loading branch information
Kaaveh authored Oct 15, 2024
2 parents facad49 + 016277b commit 2d49e4a
Show file tree
Hide file tree
Showing 16 changed files with 148 additions and 609 deletions.
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ dependencies {
implementation(lifecycle.runtime.ktx)
implementation(work.runtime.ktx)
implementation(hilt.navigation.compose)
implementation(compose.material3.adaptive.navigation.suite)
implementation(compose.material3.adaptive.navigation)
implementation(espresso.core)
implementation(compose.ui.test.manifest)
implementation(compose.ui.test.junit4)
Expand Down
53 changes: 0 additions & 53 deletions app/src/main/java/ir/composenews/navigation/ComposeNewsNavHost.kt

This file was deleted.

182 changes: 49 additions & 133 deletions app/src/main/java/ir/composenews/ui/ComposeNewsApp.kt
Original file line number Diff line number Diff line change
@@ -1,116 +1,31 @@
package ir.composenews.ui

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.material3.Text
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.window.layout.DisplayFeature
import androidx.window.layout.FoldingFeature
import ir.composenews.navigation.BottomNavItem
import ir.composenews.navigation.ComposeNewsNavHost
import ir.composenews.navigation.Destinations
import ir.composenews.navigation.MainContract
import ir.composenews.ui.component.BottomNavigationBar
import ir.composenews.ui.component.ComposeNewsNavigationRail
import ir.composenews.uimarket.model.MarketModel
import ir.composenews.utils.ContentType
import ir.composenews.utils.DevicePosture
import ir.composenews.utils.NavigationType
import ir.composenews.utils.isBookPosture
import ir.composenews.utils.isSeparating
import kotlinx.collections.immutable.PersistentList
import ir.composenews.navigation.graph.ListWithDetailScreen
import kotlinx.collections.immutable.persistentListOf

@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun ComposeNewsApp(
windowSize: WindowSizeClass,
displayFeatures: PersistentList<DisplayFeature>,
onMarketSelected: ((MarketModel, ContentType) -> Unit)? = null,
closeDetailScreen: () -> Unit,
uiState: MainContract.State
) {

/**
* This will help us select type of navigation and content type depending on window size and
* fold state of the device.
*/
val navigationType: NavigationType
val contentType: ContentType

/**
* We are using display's folding features to map the device postures a fold is in.
* In the state of folding device If it's half fold in BookPosture we want to avoid content
* at the crease/hinge
*/
val foldingFeature = displayFeatures.filterIsInstance<FoldingFeature>().firstOrNull()
val foldingDevicePosture = when {
isBookPosture(foldingFeature) ->
DevicePosture.BookPosture(foldingFeature.bounds)

isSeparating(foldingFeature) ->
DevicePosture.Separating(foldingFeature.bounds, foldingFeature.orientation)

else -> DevicePosture.NormalPosture
}

when (windowSize.widthSizeClass) {
WindowWidthSizeClass.Compact -> {
navigationType = NavigationType.BOTTOM_NAVIGATION
contentType = ContentType.SINGLE_PANE
}

WindowWidthSizeClass.Medium -> {
navigationType = NavigationType.NAVIGATION_RAIL
contentType = if (foldingDevicePosture != DevicePosture.NormalPosture) {
ContentType.DUAL_PANE
} else {
ContentType.SINGLE_PANE
}
}

WindowWidthSizeClass.Expanded -> {
navigationType = NavigationType.NAVIGATION_RAIL
contentType = ContentType.DUAL_PANE
}

else -> {
navigationType = NavigationType.BOTTOM_NAVIGATION
contentType = ContentType.SINGLE_PANE
}
}

ComposeNewsAppWrapper(
navigationType = navigationType,
contentType = contentType,
displayFeatures = displayFeatures,
onMarketSelected = onMarketSelected,
closeDetailScreen = closeDetailScreen,
uiState = uiState
)

}

@Composable
fun ComposeNewsAppWrapper(
navigationType: NavigationType,
contentType: ContentType,
displayFeatures: PersistentList<DisplayFeature>,
onMarketSelected: ((MarketModel, ContentType) -> Unit)? = null,
closeDetailScreen: () -> Unit,
uiState: MainContract.State
) {
fun ComposeNewsApp() {
val items = remember {
persistentListOf(
BottomNavItem(
Expand All @@ -126,47 +41,48 @@ fun ComposeNewsAppWrapper(
)
}

val navController = rememberNavController()
val backStackEntry = navController.currentBackStackEntryAsState()
val currentScreenRoute = backStackEntry.value?.destination?.route
val bottomNavVisible =
navigationType == NavigationType.BOTTOM_NAVIGATION && !uiState.isDetailOnlyOpen

var currentRoute by remember { mutableStateOf(Destinations.MarketListScreen.route) }

Scaffold { paddingValues ->
Row(
modifier = Modifier.padding(paddingValues)
NavigationSuiteScaffold(
navigationSuiteItems = {
items.forEach { item ->
item(selected = item.route == currentRoute, onClick = {
currentRoute = item.route
}, icon = {
Icon(
imageVector = item.icon,
contentDescription = item.name,
)
}, label = {
Text(
text = item.name,
)
})
}
},
layoutType = NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(
currentWindowAdaptiveInfo()
)
) {
AnimatedVisibility(visible = navigationType == NavigationType.NAVIGATION_RAIL) {
ComposeNewsNavigationRail(
items = items,
currentScreenRoute = currentScreenRoute,
onItemClick = { navController.navigate(it.route) })
}
Column(
modifier = Modifier
.fillMaxSize()
) {
ComposeNewsNavHost(
modifier = Modifier
.weight(1f)
.padding(bottom = paddingValues.calculateBottomPadding()),
navController = navController,
contentType = contentType,
displayFeatures = displayFeatures,
onMarketSelected = onMarketSelected,
closeDetailScreen = closeDetailScreen,
uiState = uiState
)
AnimatedVisibility(visible = bottomNavVisible) {
BottomNavigationBar(
items = items,
currentScreenRoute = currentScreenRoute,
onItemClick = { navController.navigate(it.route) }
val navigator = rememberListDetailPaneScaffoldNavigator<Any>()
when (currentRoute) {
Destinations.MarketListScreen.route -> {
ListWithDetailScreen(
Modifier.padding(paddingValues),
navigator,
showFavorite = false,
)
}
}

Destinations.FavoriteMarketScreen.route -> {
ListWithDetailScreen(
Modifier.padding(paddingValues),
navigator,
showFavorite = true,
)
}
}
}
}
}
Loading

0 comments on commit 2d49e4a

Please sign in to comment.