Skip to content

Commit

Permalink
Commonize "material-navigation" module.
Browse files Browse the repository at this point in the history
  • Loading branch information
terrakok committed Aug 21, 2024
1 parent db66e18 commit a88343a
Show file tree
Hide file tree
Showing 14 changed files with 443 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
public final class androidx/compose/material/navigation/BottomSheetKt {
public static final fun ModalBottomSheetLayout-4erKP6g (Landroidx/compose/material/navigation/BottomSheetNavigator;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/Shape;FJJJLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
}

public final class androidx/compose/material/navigation/BottomSheetNavigator : androidx/navigation/Navigator {
public static final field $stable I
public fun <init> (Landroidx/compose/material/ModalBottomSheetState;)V
public fun createDestination ()Landroidx/compose/material/navigation/BottomSheetNavigator$Destination;
public synthetic fun createDestination ()Landroidx/navigation/NavDestination;
public final fun getNavigatorSheetState ()Landroidx/compose/material/navigation/BottomSheetNavigatorSheetState;
public fun navigate (Ljava/util/List;Landroidx/navigation/NavOptions;Landroidx/navigation/Navigator$Extras;)V
public fun onAttach (Landroidx/navigation/NavigatorState;)V
public fun popBackStack (Landroidx/navigation/NavBackStackEntry;Z)V
}

public final class androidx/compose/material/navigation/BottomSheetNavigator$Destination : androidx/navigation/NavDestination, androidx/navigation/FloatingWindow {
public static final field $stable I
public fun <init> (Landroidx/compose/material/navigation/BottomSheetNavigator;Lkotlin/jvm/functions/Function4;)V
}

public final class androidx/compose/material/navigation/BottomSheetNavigatorKt {
public static final fun rememberBottomSheetNavigator (Landroidx/compose/animation/core/AnimationSpec;Landroidx/compose/runtime/Composer;II)Landroidx/compose/material/navigation/BottomSheetNavigator;
}

public final class androidx/compose/material/navigation/BottomSheetNavigatorSheetState {
public static final field $stable I
public fun <init> (Landroidx/compose/material/ModalBottomSheetState;)V
public final fun getCurrentValue ()Landroidx/compose/material/ModalBottomSheetValue;
public final fun getTargetValue ()Landroidx/compose/material/ModalBottomSheetValue;
public final fun isVisible ()Z
}

public final class androidx/compose/material/navigation/ComposableSingletons$BottomSheetNavigator_jbKt {
public static final field INSTANCE Landroidx/compose/material/navigation/ComposableSingletons$BottomSheetNavigator_jbKt;
public static field lambda-1 Lkotlin/jvm/functions/Function4;
public fun <init> ()V
public final fun getLambda-1$material_navigation ()Lkotlin/jvm/functions/Function4;
}

public final class androidx/compose/material/navigation/NavGraphBuilderKt {
public static final fun bottomSheet (Landroidx/navigation/NavGraphBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function4;)V
public static synthetic fun bottomSheet$default (Landroidx/navigation/NavGraphBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function4;ILjava/lang/Object;)V
}

77 changes: 61 additions & 16 deletions compose/material/material-navigation/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,82 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import androidx.build.AndroidXComposePlugin
import androidx.build.JetbrainsAndroidXPlugin
import androidx.build.LibraryType
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType

plugins {
id("AndroidXPlugin")
id("com.android.library")
id("AndroidXComposePlugin")
id("org.jetbrains.kotlin.android")
id("JetbrainsAndroidXPlugin")
}

AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project)
JetbrainsAndroidXPlugin.applyAndConfigure(project)

androidXComposeMultiplatform {
android()
desktop()
darwin()
js()
wasm()
}

dependencies {
api("androidx.navigation:navigation-compose:2.7.7")
implementation(project(":compose:material:material"))
implementation(libs.kotlinStdlib)

androidTestImplementation project(":compose:test-utils")
androidTestImplementation("androidx.navigation:navigation-testing:2.7.7")
androidTestImplementation(project(":compose:ui:ui-test-junit4"))
androidTestImplementation(project(":compose:ui:ui-test-manifest"))
androidTestImplementation(libs.testRunner)
androidTestImplementation(libs.junit)
androidTestImplementation(libs.truth)
androidTestImplementation(libs.testRules)
kotlin {
sourceSets {
commonMain {
dependencies {
implementation(project(":navigation:navigation-compose"))
implementation(project(":compose:material:material"))
implementation(libs.kotlinStdlib)
}
}

androidInstrumentedTest {
dependencies {
implementation(project(":compose:test-utils"))
implementation(project(":navigation:navigation-testing"))
implementation(project(":compose:ui:ui-test-junit4"))
implementation(project(":compose:ui:ui-test-manifest"))
implementation(libs.testRunner)
implementation(libs.junit)
implementation(libs.truth)
implementation(libs.testRules)
}
}

jbMain.dependsOn(commonMain)
desktopMain.dependsOn(jbMain)
nativeMain.dependsOn(jbMain)
webMain.dependsOn(jbMain)

targets.all { target ->
if (target.platformType == KotlinPlatformType.native) {
target.compilations["main"].defaultSourceSet {
dependsOn(nativeMain)
}
} else if (target.platformType in [
KotlinPlatformType.js,
KotlinPlatformType.wasm
]) {
target.compilations["main"].defaultSourceSet {
dependsOn(webMain)
}
}
}
}
}

androidx {
name = "Compose Material Navigation"
type = LibraryType.PUBLISHED_LIBRARY_ONLY_USED_BY_KOTLIN_CONSUMERS
type = LibraryType.PUBLISHED_LIBRARY
mavenVersion = LibraryVersions.COMPOSE
inceptionYear = "2024"
description = "Compose Material integration with Navigation"
samples(projectOrArtifact(":compose:material:material-navigation-samples"))
// samples(projectOrArtifact(":compose:material:material-navigation-samples"))
}

android {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,15 @@
package androidx.compose.material.navigation

import androidx.activity.compose.BackHandler
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.SpringSpec
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material.navigation.BottomSheetNavigator.Destination
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.runtime.setValue
import androidx.compose.ui.util.fastForEach
Expand All @@ -44,45 +40,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.transform

/**
* The state of a [ModalBottomSheetLayout] that the [BottomSheetNavigator] drives
*
* @param sheetState The sheet state that is driven by the [BottomSheetNavigator]
*/
public class BottomSheetNavigatorSheetState(private val sheetState: ModalBottomSheetState) {
/**
* @see ModalBottomSheetState.isVisible
*/
public val isVisible: Boolean
get() = sheetState.isVisible

/**
* @see ModalBottomSheetState.currentValue
*/
public val currentValue: ModalBottomSheetValue
get() = sheetState.currentValue

/**
* @see ModalBottomSheetState.targetValue
*/
public val targetValue: ModalBottomSheetValue
get() = sheetState.targetValue
}

/**
* Create and remember a [BottomSheetNavigator]
*/
@Composable
public fun rememberBottomSheetNavigator(
animationSpec: AnimationSpec<Float> = SpringSpec()
): BottomSheetNavigator {
val sheetState = rememberModalBottomSheetState(
ModalBottomSheetValue.Hidden,
animationSpec = animationSpec
)
return remember(sheetState) { BottomSheetNavigator(sheetState) }
}

/**
* Navigator that drives a [ModalBottomSheetState] for use of [ModalBottomSheetLayout]s
* with the navigation library. Every destination using this Navigator must set a valid
Expand All @@ -103,8 +60,8 @@ public fun rememberBottomSheetNavigator(
* drive the sheet state
*/
@Navigator.Name("bottomSheet")
public class BottomSheetNavigator(
internal val sheetState: ModalBottomSheetState
public actual class BottomSheetNavigator actual constructor(
internal actual val sheetState: ModalBottomSheetState
) : Navigator<BottomSheetNavigator.Destination>() {

private var attached by mutableStateOf(false)
Expand All @@ -126,7 +83,7 @@ public class BottomSheetNavigator(
* composed before the Navigator is attached, so we specifically return an empty flow if we
* aren't attached yet.
*/
internal val transitionsInProgress: StateFlow<Set<NavBackStackEntry>>
internal actual val transitionsInProgress: StateFlow<Set<NavBackStackEntry>>
get() = if (attached) {
state.transitionsInProgress
} else {
Expand All @@ -136,14 +93,14 @@ public class BottomSheetNavigator(
/**
* Access properties of the [ModalBottomSheetLayout]'s [ModalBottomSheetState]
*/
public val navigatorSheetState: BottomSheetNavigatorSheetState =
public actual val navigatorSheetState: BottomSheetNavigatorSheetState =
BottomSheetNavigatorSheetState(sheetState)

/**
* A [Composable] function that hosts the current sheet content. This should be set as
* sheetContent of your [ModalBottomSheetLayout].
*/
internal val sheetContent: @Composable ColumnScope.() -> Unit = {
internal actual val sheetContent: @Composable ColumnScope.() -> Unit = {
val saveableStateHolder = rememberSaveableStateHolder()
val transitionsInProgressEntries by transitionsInProgress.collectAsState()

Expand Down Expand Up @@ -235,8 +192,8 @@ public class BottomSheetNavigator(
* [NavDestination] specific to [BottomSheetNavigator]
*/
@NavDestination.ClassType(Composable::class)
public class Destination(
public actual class Destination actual constructor(
navigator: BottomSheetNavigator,
internal val content: @Composable ColumnScope.(NavBackStackEntry) -> Unit
internal actual val content: @Composable ColumnScope.(NavBackStackEntry) -> Unit
) : NavDestination(navigator), FloatingWindow
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.material.navigation

import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.SpringSpec
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.navigation.BottomSheetNavigator.Destination
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.navigation.FloatingWindow
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavDestination
import androidx.navigation.Navigator
import androidx.navigation.NavigatorState
import kotlinx.coroutines.flow.StateFlow

/**
* The state of a [ModalBottomSheetLayout] that the [BottomSheetNavigator] drives
*
* @param sheetState The sheet state that is driven by the [BottomSheetNavigator]
*/
public class BottomSheetNavigatorSheetState(private val sheetState: ModalBottomSheetState) {
/**
* @see ModalBottomSheetState.isVisible
*/
public val isVisible: Boolean
get() = sheetState.isVisible

/**
* @see ModalBottomSheetState.currentValue
*/
public val currentValue: ModalBottomSheetValue
get() = sheetState.currentValue

/**
* @see ModalBottomSheetState.targetValue
*/
public val targetValue: ModalBottomSheetValue
get() = sheetState.targetValue
}

/**
* Create and remember a [BottomSheetNavigator]
*/
@Composable
public fun rememberBottomSheetNavigator(
animationSpec: AnimationSpec<Float> = SpringSpec()
): BottomSheetNavigator {
val sheetState = rememberModalBottomSheetState(
ModalBottomSheetValue.Hidden,
animationSpec = animationSpec
)
return remember(sheetState) { BottomSheetNavigator(sheetState) }
}

/**
* Navigator that drives a [ModalBottomSheetState] for use of [ModalBottomSheetLayout]s
* with the navigation library. Every destination using this Navigator must set a valid
* [Composable] by setting it directly on an instantiated [Destination] or calling
* [androidx.compose.material.navigation.bottomSheet].
*
* <b>The [sheetContent] [Composable] will always host the latest entry of the back stack. When
* navigating from a [BottomSheetNavigator.Destination] to another
* [BottomSheetNavigator.Destination], the content of the sheet will be replaced instead of a
* new bottom sheet being shown.</b>
*
* When the sheet is dismissed by the user, the [state]'s [NavigatorState.backStack] will be popped.
*
* The primary constructor is not intended for public use. Please refer to
* [rememberBottomSheetNavigator] instead.
*
* @param sheetState The [ModalBottomSheetState] that the [BottomSheetNavigator] will use to
* drive the sheet state
*/
public expect class BottomSheetNavigator(
sheetState: ModalBottomSheetState
) : Navigator<Destination> {

internal val sheetState: ModalBottomSheetState

/**
* Get the transitionsInProgress from the [state]. In some cases, the [sheetContent] might be
* composed before the Navigator is attached, so we specifically return an empty flow if we
* aren't attached yet.
*/
internal val transitionsInProgress: StateFlow<Set<NavBackStackEntry>>

/**
* Access properties of the [ModalBottomSheetLayout]'s [ModalBottomSheetState]
*/
public val navigatorSheetState: BottomSheetNavigatorSheetState

/**
* A [Composable] function that hosts the current sheet content. This should be set as
* sheetContent of your [ModalBottomSheetLayout].
*/
internal val sheetContent: @Composable ColumnScope.() -> Unit

/**
* [NavDestination] specific to [BottomSheetNavigator]
*/
public class Destination(
navigator: BottomSheetNavigator,
content: @Composable ColumnScope.(NavBackStackEntry) -> Unit
) : NavDestination, FloatingWindow {
internal val content: @Composable ColumnScope.(NavBackStackEntry) -> Unit
}
}
Loading

0 comments on commit a88343a

Please sign in to comment.