Merge pull request #92 from lihenggui/merge/mar_7

Merge latest changes from upstream
pull/2064/head
Mercury Li 2 years ago committed by GitHub
commit 7a1c00f87e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -16,6 +16,7 @@
package com.google.samples.apps.nowinandroid.ui
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
@ -199,15 +200,7 @@ internal fun NiaApp(
)
}
NiaNavHost(
appState = appState,
onShowSnackbar = { message, action ->
snackbarHostState.showSnackbar(
message = message,
actionLabel = action,
duration = Short,
) == ActionPerformed
},
Box(
modifier = if (shouldShowTopAppBar) {
Modifier.consumeWindowInsets(
WindowInsets.safeDrawing.only(WindowInsetsSides.Top),
@ -215,7 +208,18 @@ internal fun NiaApp(
} else {
Modifier
},
)
) {
NiaNavHost(
appState = appState,
onShowSnackbar = { message, action ->
snackbarHostState.showSnackbar(
message = message,
actionLabel = action,
duration = Short,
) == ActionPerformed
},
)
}
}
// TODO: We may want to add padding or spacer when the snackbar is shown so that

@ -27,7 +27,8 @@ import javax.inject.Inject
class Interests2PaneViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {
val selectedTopicId: StateFlow<String?> = savedStateHandle.getStateFlow(TOPIC_ID_ARG, null)
val selectedTopicId: StateFlow<String?> =
savedStateHandle.getStateFlow(TOPIC_ID_ARG, savedStateHandle[TOPIC_ID_ARG])
fun onTopicClick(topicId: String?) {
savedStateHandle[TOPIC_ID_ARG] = topicId

@ -18,14 +18,21 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane
import androidx.activity.compose.BackHandler
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.layout.AnimatedPane
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
@ -39,8 +46,10 @@ import com.google.samples.apps.nowinandroid.feature.interests.navigation.INTERES
import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_ARG
import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TOPIC_ROUTE
import com.google.samples.apps.nowinandroid.feature.topic.navigation.createTopicRoute
import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen
import java.util.UUID
private const val DETAIL_PANE_NAVHOST_ROUTE = "detail_pane_route"
@ -76,17 +85,42 @@ internal fun InterestsListDetailScreen(
selectedTopicId: String?,
onTopicClick: (String) -> Unit,
) {
val listDetailNavigator = rememberListDetailPaneScaffoldNavigator()
val listDetailNavigator = rememberListDetailPaneScaffoldNavigator(
initialDestinationHistory = listOfNotNull(
ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.List),
ThreePaneScaffoldDestinationItem<Nothing>(ListDetailPaneScaffoldRole.Detail).takeIf {
selectedTopicId != null
},
),
)
BackHandler(listDetailNavigator.canNavigateBack()) {
listDetailNavigator.navigateBack()
}
val nestedNavController = rememberNavController()
var nestedNavHostStartDestination by remember {
mutableStateOf(selectedTopicId?.let(::createTopicRoute) ?: TOPIC_ROUTE)
}
var nestedNavKey by rememberSaveable(
stateSaver = Saver({ it.toString() }, UUID::fromString),
) {
mutableStateOf(UUID.randomUUID())
}
val nestedNavController = key(nestedNavKey) {
rememberNavController()
}
fun onTopicClickShowDetailPane(topicId: String) {
onTopicClick(topicId)
nestedNavController.navigateToTopic(topicId) {
popUpTo(DETAIL_PANE_NAVHOST_ROUTE)
if (listDetailNavigator.isDetailPaneVisible()) {
// If the detail pane was visible, then use the nestedNavController navigate call
// directly
nestedNavController.navigateToTopic(topicId) {
popUpTo(DETAIL_PANE_NAVHOST_ROUTE)
}
} else {
// Otherwise, recreate the NavHost entirely, and start at the new destination
nestedNavHostStartDestination = createTopicRoute(topicId)
nestedNavKey = UUID.randomUUID()
}
listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
}
@ -95,34 +129,34 @@ internal fun InterestsListDetailScreen(
value = listDetailNavigator.scaffoldValue,
directive = listDetailNavigator.scaffoldDirective,
listPane = {
InterestsRoute(
onTopicClick = ::onTopicClickShowDetailPane,
highlightSelectedTopic = listDetailNavigator.isDetailPaneVisible(),
)
},
detailPane = {
NavHost(
navController = nestedNavController,
startDestination = TOPIC_ROUTE,
route = DETAIL_PANE_NAVHOST_ROUTE,
) {
topicScreen(
showBackButton = !listDetailNavigator.isListPaneVisible(),
onBackClick = listDetailNavigator::navigateBack,
AnimatedPane {
InterestsRoute(
onTopicClick = ::onTopicClickShowDetailPane,
highlightSelectedTopic = listDetailNavigator.isDetailPaneVisible(),
)
composable(route = TOPIC_ROUTE) {
TopicDetailPlaceholder()
}
},
detailPane = {
AnimatedPane {
key(nestedNavKey) {
NavHost(
navController = nestedNavController,
startDestination = nestedNavHostStartDestination,
route = DETAIL_PANE_NAVHOST_ROUTE,
) {
topicScreen(
showBackButton = !listDetailNavigator.isListPaneVisible(),
onBackClick = listDetailNavigator::navigateBack,
onTopicClick = ::onTopicClickShowDetailPane,
)
composable(route = TOPIC_ROUTE) {
TopicDetailPlaceholder()
}
}
}
}
},
)
LaunchedEffect(Unit) {
if (selectedTopicId != null) {
// Initial topic ID was provided when navigating to Interests, so show its details.
onTopicClickShowDetailPane(selectedTopicId)
}
}
}
@OptIn(ExperimentalMaterial3AdaptiveApi::class)

@ -26,15 +26,18 @@ import android.net.NetworkRequest.Builder
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import androidx.core.content.getSystemService
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn
import me.tatarka.inject.annotations.Inject
@Inject
internal class ConnectivityManagerNetworkMonitor(
private val context: Context,
private val ioDispatcher: CoroutineDispatcher,
) : NetworkMonitor {
override val isOnline: Flow<Boolean> = callbackFlow {
val connectivityManager = context.getSystemService<ConnectivityManager>()
@ -62,12 +65,10 @@ internal class ConnectivityManagerNetworkMonitor(
channel.trySend(networks.isNotEmpty())
}
}
val request = Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
connectivityManager.registerNetworkCallback(request, callback)
/**
* Sends the latest connectivity status to the underlying channel.
*/
@ -77,6 +78,7 @@ internal class ConnectivityManagerNetworkMonitor(
connectivityManager.unregisterNetworkCallback(callback)
}
}
.flowOn(ioDispatcher)
.conflate()
@Suppress("DEPRECATION")

@ -46,4 +46,4 @@ internal actual abstract class DriverModule(private val context: Context) {
},
)
}
}
}

@ -26,4 +26,4 @@ internal expect abstract class DriverModule {
suspend fun provideDbDriver(
schema: SqlSchema<AsyncValue<Unit>>,
): SqlDriver
}
}

@ -20,7 +20,6 @@ import app.cash.sqldelight.db.QueryResult.AsyncValue
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.db.SqlSchema
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver.Companion
import me.tatarka.inject.annotations.Component
import me.tatarka.inject.annotations.Provides
import java.util.Properties
@ -37,4 +36,4 @@ internal actual abstract class DriverModule {
)
.also { schema.create(it).await() }
}
}
}

@ -41,13 +41,16 @@ internal class TopicArgs(val topicId: String) {
}
fun NavController.navigateToTopic(topicId: String, navOptions: NavOptionsBuilder.() -> Unit = {}) {
val encodedId = URLEncoder.encode(topicId, URL_CHARACTER_ENCODING)
val newRoute = "$TOPIC_ROUTE/$encodedId"
navigate(newRoute) {
navigate(createTopicRoute(topicId)) {
navOptions()
}
}
fun createTopicRoute(topicId: String): String {
val encodedId = URLEncoder.encode(topicId, URL_CHARACTER_ENCODING)
return "$TOPIC_ROUTE/$encodedId"
}
fun NavGraphBuilder.topicScreen(
showBackButton: Boolean,
onBackClick: () -> Unit,

@ -12,15 +12,15 @@ androidxComposeCompiler = "1.5.13"
androidxComposeUiTest = "1.7.0-alpha08"
androidxComposeMaterial3Adaptive = "1.0.0-alpha12"
androidxComposeRuntimeTracing = "1.0.0-beta01"
androidxCore = "1.13.0"
androidxCore = "1.13.1"
androidxCoreSplashscreen = "1.0.1"
androidxDataStore = "1.1.0"
androidxDataStore = "1.1.1"
androidxEspresso = "3.5.1"
androidxHiltNavigationCompose = "1.2.0"
androidxLifecycle = "2.7.0"
androidxMacroBenchmark = "1.2.4"
androidxMetrics = "1.0.0-beta01"
androidxNavigation = "2.7.7"
androidxNavigation = "2.8.0-alpha08"
androidxProfileinstaller = "1.3.1"
androidxTestCore = "1.5.0"
androidxTestExt = "1.1.5"
@ -28,7 +28,7 @@ androidxTestRules = "1.5.0"
androidxTestRunner = "1.5.2"
androidxTracing = "1.3.0-alpha02"
androidxUiAutomator = "2.3.0"
androidxWindowManager = "1.3.0-beta01"
androidxWindowManager = "1.3.0-beta02"
androidxWork = "2.9.0"
coil = "3.0.0-alpha06"
dependencyGuard = "0.5.0"
@ -54,7 +54,7 @@ protobufPlugin = "0.9.4"
retrofit = "2.11.0"
retrofitKotlinxSerializationJson = "1.0.0"
robolectric = "4.12.1"
roborazzi = "1.13.0"
roborazzi = "1.14.0"
room = "2.6.1"
secrets = "2.0.1"
truth = "1.4.2"
@ -68,10 +68,10 @@ androidx-appcompat = "1.6.1"
androidx-constraintlayout = "2.1.4"
androidx-core-ktx = "1.12.0"
androidx-espresso-core = "3.5.1"
androidx-material = "1.11.0"
androidx-material = "1.12.0"
androidx-test-junit = "1.1.5"
compose-ui-tooling = "1.6.7"
compose-plugin = "1.6.10-beta03"
compose-plugin = "1.6.10-rc01"
junit = "4.13.2"
sqldelight = "2.0.2"
kotlinInject = '0.6.3'

Loading…
Cancel
Save