From 6bb30bf84294dcf3714d0e4fe537408405d2ba4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bo=C5=99ek=20Leikep?= Date: Tue, 31 Oct 2023 10:20:27 +0100 Subject: [PATCH] Added extraContent slot to TopAppBarLarge. --- .../catalog/screens/TopAppBarScreen.kt | 31 ++++++++++------ .../catalog/screens/TopAppBarScreensLarge.kt | 35 +++++++++++++++++++ ui/detekt-baseline-debug.xml | 8 +---- .../orbit/compose/ui/controls/TopAppBar.kt | 23 ++++++++++++ .../compose/ui/controls/TopAppBarLarge.kt | 30 ++++++++++++++++ ...it.compose.ui_ScreenshotTest_topAppBar.png | 4 +-- ...mpose.ui_ScreenshotTest_topAppBarLarge.png | 4 +-- ...e.ui_ScreenshotTest_topAppBarLarge_big.png | 4 +-- ....ui_ScreenshotTest_topAppBarLarge_dark.png | 4 +-- ...ompose.ui_ScreenshotTest_topAppBar_big.png | 4 +-- ...mpose.ui_ScreenshotTest_topAppBar_dark.png | 4 +-- 11 files changed, 122 insertions(+), 29 deletions(-) diff --git a/catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreen.kt b/catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreen.kt index efcc22dc6..c09764ce2 100644 --- a/catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreen.kt +++ b/catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreen.kt @@ -33,34 +33,37 @@ import kotlinx.serialization.Serializable sealed interface TopAppBarDestination : Destination { @Serializable - object Home : TopAppBarDestination + data object Home : TopAppBarDestination @Serializable - object Normal : TopAppBarDestination + data object Normal : TopAppBarDestination @Serializable - object NormalScrollable : TopAppBarDestination + data object NormalScrollable : TopAppBarDestination @Serializable - object NormalWithTabs : TopAppBarDestination + data object NormalWithTabs : TopAppBarDestination @Serializable - object NormalWithFilters : TopAppBarDestination + data object NormalWithFilters : TopAppBarDestination @Serializable - object Large : TopAppBarDestination + data object Large : TopAppBarDestination @Serializable - object LargeScrollable : TopAppBarDestination + data object LargeScrollable : TopAppBarDestination @Serializable - object LargeScrollableElevated : TopAppBarDestination + data object LargeScrollableElevated : TopAppBarDestination @Serializable - object LargeCustomContent : TopAppBarDestination + data object LargeWithTabs : TopAppBarDestination @Serializable - object LargePullRefresh : TopAppBarDestination + data object LargeCustomContent : TopAppBarDestination + + @Serializable + data object LargePullRefresh : TopAppBarDestination } @ExperimentalSerializationApi @@ -94,6 +97,9 @@ internal inline fun NavGraphBuilder.topAppBarNavigatio composable { TopAppBarLargeScrollableElevatedScreen(navController::navigateUp) } + composable { + TopAppBarLargeWithTabsScreen(navController::navigateUp) + } composable { TopAppBarLargeCustomContentScreen(navController::navigateUp) } @@ -166,6 +172,11 @@ internal fun TopAppBarScreenInner( ) { Text("Scrollable Elevated") } + ButtonSecondary( + onClick = { onSelect(TopAppBarDestination.LargeWithTabs) }, + ) { + Text("With Tabs") + } ButtonSecondary( onClick = { onSelect(TopAppBarDestination.LargeCustomContent) }, ) { diff --git a/catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreensLarge.kt b/catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreensLarge.kt index 51c9ef642..3f1740e35 100644 --- a/catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreensLarge.kt +++ b/catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreensLarge.kt @@ -33,6 +33,8 @@ import kiwi.orbit.compose.ui.OrbitTheme import kiwi.orbit.compose.ui.controls.Icon import kiwi.orbit.compose.ui.controls.IconButton import kiwi.orbit.compose.ui.controls.Scaffold +import kiwi.orbit.compose.ui.controls.Tab +import kiwi.orbit.compose.ui.controls.TabRow import kiwi.orbit.compose.ui.controls.Text import kiwi.orbit.compose.ui.controls.TopAppBarLarge import kiwi.orbit.compose.ui.controls.TopAppBarScrollBehavior @@ -100,6 +102,39 @@ internal fun TopAppBarLargeScrollableElevatedScreen( ) } +@Composable +internal fun TopAppBarLargeWithTabsScreen( + onNavigateUp: () -> Unit, +) { + val scrollBehavior = TopAppBarScrollBehavior.exitUntilCollapsed() + Scaffold( + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + TopAppBarLarge( + title = { Text("With Tabs") }, + onNavigateUp = onNavigateUp, + extraContent = { + var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) } + TabRow(selectedTabIndex = selectedTabIndex) { + Tab( + selected = selectedTabIndex == 0, + onClick = { selectedTabIndex = 0 }, + text = { Text("Normal") }, + ) + Tab( + selected = selectedTabIndex == 1, + onClick = { selectedTabIndex = 1 }, + text = { Text("Inline") }, + ) + } + }, + scrollBehavior = scrollBehavior, + ) + }, + content = { CustomContentPlaceholder(it) }, + ) +} + @Composable internal fun TopAppBarLargeCustomContentScreen( onNavigateUp: () -> Unit, diff --git a/ui/detekt-baseline-debug.xml b/ui/detekt-baseline-debug.xml index 7f931586c..2cb9bc13b 100644 --- a/ui/detekt-baseline-debug.xml +++ b/ui/detekt-baseline-debug.xml @@ -3,26 +3,20 @@ CyclomaticComplexMethod:Checkbox.kt$@OptIn(ExperimentalAnimationGraphicsApi::class) @Composable public fun Checkbox( checked: Boolean, onCheckedChange: (() -> Unit)?, modifier: Modifier = Modifier, enabled: Boolean = true, isError: Boolean = false, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, ) - CyclomaticComplexMethod:Scaffold.kt$@OptIn(ExperimentalLayoutApi::class) @Composable private fun ScaffoldLayout( topBar: @Composable () -> Unit, toast: @Composable () -> Unit, action: @Composable () -> Unit, content: @Composable (contentPadding: PaddingValues) -> Unit, contentWindowInsets: WindowInsets, ) - CyclomaticComplexMethod:Seat.kt$@Composable private fun ColumnScope.Seat( selected: Boolean, enabled: Boolean, isExtraLegroom: Boolean, content: @Composable () -> Unit, ) CyclomaticComplexMethod:Slider.kt$@Composable private fun Track(enabled: Boolean, sliderPositions: SliderPositions) - CyclomaticComplexMethod:TextField.kt$@Suppress("LongParameterList") @Composable internal fun TextField( value: String, onValueChange: (String) -> Unit, enabled: Boolean, readOnly: Boolean, label: @Composable (() -> Unit)?, error: @Composable (() -> Unit)?, info: @Composable (() -> Unit)?, additionalContent: @Composable (() -> Unit)?, placeholder: @Composable (() -> Unit)?, leadingIcon: @Composable (() -> Unit)?, onLeadingIconClick: (() -> Unit)?, trailingIcon: @Composable (() -> Unit)?, onTrailingIconClick: (() -> Unit)?, keyboardOptions: KeyboardOptions, keyboardActions: KeyboardActions, singleLine: Boolean, maxLines: Int, minLines: Int, visualTransformation: VisualTransformation, interactionSource: MutableInteractionSource, modifier: Modifier = Modifier, ) ForbiddenComment:SelectField.kt$// TODO: ForbiddenComment:Typography.kt$Typography$// TODO: remove data class to allow maintain better binary compatibility FunctionNaming:SwipeableV2.kt$SwipeableV2Defaults$internal fun <T> ReconcileAnimationOnAnchorChangeHandler( state: SwipeableV2State<T>, animate: (target: T, velocity: Float) -> Unit, snap: (target: T) -> Unit ) FunctionNaming:SwipeableV2.kt$SwipeableV2State.Companion$fun <T : Any> Saver( animationSpec: AnimationSpec<Float>, confirmValueChange: (T) -> Boolean, positionalThreshold: Density.(distance: Float) -> Float, velocityThreshold: Dp ) - LongMethod:Alert.kt$@Composable private fun Alert( icon: Painter?, title: @Composable ColumnScope.() -> Unit, actions: @Composable () -> Unit, content: @Composable ColumnScope.() -> Unit, suppressed: Boolean, modifier: Modifier = Modifier, ) LongMethod:Checkbox.kt$@OptIn(ExperimentalAnimationGraphicsApi::class) @Composable public fun Checkbox( checked: Boolean, onCheckedChange: (() -> Unit)?, modifier: Modifier = Modifier, enabled: Boolean = true, isError: Boolean = false, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, ) LongMethod:FieldContent.kt$FieldContentMeasurePolicy$override fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints, ): MeasureResult LongMethod:ListChoice.kt$@Composable private fun ListChoicePrimitive( onClick: (() -> Unit)?, icon: @Composable () -> Unit, description: @Composable () -> Unit, trailingIcon: @Composable () -> Unit, withSeparator: Boolean, interactionSource: MutableInteractionSource, title: @Composable () -> Unit, modifier: Modifier = Modifier, ) LongMethod:SegmentedSwitch.kt$@Composable public fun SegmentedSwitch( onOptionClick: (selectedIndex: Int) -> Unit, options: List<@Composable () -> Unit>, selectedIndex: Int?, modifier: Modifier = Modifier, label: @Composable () -> Unit = {}, error: @Composable (() -> Unit)? = null, info: @Composable (() -> Unit)? = null, ) LongMethod:SelectField.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable public fun <T> SelectField( value: String, options: List<T>, onOptionSelect: (T) -> Unit, modifier: Modifier = Modifier, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, label: @Composable (() -> Unit)? = null, error: @Composable (() -> Unit)? = null, info: @Composable (() -> Unit)? = null, placeholder: @Composable (() -> Unit)? = null, leadingIcon: @Composable (() -> Unit)? = null, singleLine: Boolean = true, maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, minLines: Int = 1, optionContent: @Composable RowScope.(option: T) -> Unit, ) LongMethod:Slider.kt$@Composable private fun Track(enabled: Boolean, sliderPositions: SliderPositions) - LongMethod:Switch.kt$@Composable private fun BoxScope.SwitchImpl( checked: Boolean, enabled: Boolean, state: SwipeableV2State<Boolean>, interactionSource: InteractionSource, ) - LongMethod:TextField.kt$@Suppress("LongParameterList") @Composable internal fun TextField( value: String, onValueChange: (String) -> Unit, enabled: Boolean, readOnly: Boolean, label: @Composable (() -> Unit)?, error: @Composable (() -> Unit)?, info: @Composable (() -> Unit)?, additionalContent: @Composable (() -> Unit)?, placeholder: @Composable (() -> Unit)?, leadingIcon: @Composable (() -> Unit)?, onLeadingIconClick: (() -> Unit)?, trailingIcon: @Composable (() -> Unit)?, onTrailingIconClick: (() -> Unit)?, keyboardOptions: KeyboardOptions, keyboardActions: KeyboardActions, singleLine: Boolean, maxLines: Int, minLines: Int, visualTransformation: VisualTransformation, interactionSource: MutableInteractionSource, modifier: Modifier = Modifier, ) LongMethod:Toast.kt$private fun Modifier.toastGesturesDetector( onPause: () -> Unit, onResume: () -> Unit, onDismissed: () -> Unit, ): Modifier LongMethod:TopAppBar.kt$@Composable internal fun TopAppBarLayout( title: @Composable () -> Unit, titleAlpha: Float, hideTitleSemantics: Boolean, navigationIcon: @Composable () -> Unit, actions: @Composable () -> Unit, modifier: Modifier = Modifier, ) - LongMethod:TopAppBarLarge.kt$@Composable private fun TwoRowsTopAppBar( title: @Composable () -> Unit, largeTitle: @Composable () -> Unit, navigationIcon: @Composable () -> Unit, actions: @Composable () -> Unit, largeElevated: Boolean, elevation: Dp, scrollBehavior: TopAppBarScrollBehavior?, modifier: Modifier = Modifier, ) + LongMethod:TopAppBarLarge.kt$@Composable private fun TwoRowsTopAppBar( title: @Composable () -> Unit, largeTitle: @Composable () -> Unit, navigationIcon: @Composable () -> Unit, actions: @Composable () -> Unit, extraContent: @Composable () -> Unit, largeElevated: Boolean, elevation: Dp, scrollBehavior: TopAppBarScrollBehavior?, modifier: Modifier = Modifier, ) MatchingDeclarationName:Toast.kt$ToastData MatchingDeclarationName:ToastHost.kt$ToastHostState NestedBlockDepth:SwipeableV2.kt$SwipeableV2State$private fun computeTarget( offset: Float, currentValue: T, velocity: Float ): T diff --git a/ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBar.kt b/ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBar.kt index 1a65bc689..f86bcc8a9 100644 --- a/ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBar.kt +++ b/ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBar.kt @@ -17,6 +17,10 @@ import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -289,5 +293,24 @@ internal fun TopAppBarPreview() { } }, ) + TopAppBar( + title = { Text("Title") }, + onNavigateUp = {}, + extraContent = { + var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) } + TabRow(selectedTabIndex = selectedTabIndex) { + Tab( + selected = selectedTabIndex == 0, + onClick = { selectedTabIndex = 0 }, + text = { Text("Tab A") }, + ) + Tab( + selected = selectedTabIndex == 1, + onClick = { selectedTabIndex = 1 }, + text = { Text("Tab B") }, + ) + } + }, + ) } } diff --git a/ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBarLarge.kt b/ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBarLarge.kt index 08e892911..def6724fe 100644 --- a/ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBarLarge.kt +++ b/ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBarLarge.kt @@ -15,6 +15,10 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -43,6 +47,7 @@ public fun TopAppBarLarge( largeTitle: @Composable () -> Unit = title, navigationIcon: Painter = TopAppBarIcons.Back, actions: @Composable RowScope.() -> Unit = {}, + extraContent: @Composable () -> Unit = {}, largeElevated: Boolean = true, elevation: Dp = TopAppBarElevation, scrollBehavior: TopAppBarScrollBehavior? = null, @@ -62,6 +67,7 @@ public fun TopAppBarLarge( }, largeTitle = largeTitle, actions = actions, + extraContent = extraContent, largeElevated = largeElevated, elevation = elevation, scrollBehavior = scrollBehavior, @@ -75,6 +81,7 @@ public fun TopAppBarLarge( navigationIcon: @Composable () -> Unit = {}, largeTitle: @Composable () -> Unit = title, actions: @Composable RowScope.() -> Unit = {}, + extraContent: @Composable () -> Unit = {}, largeElevated: Boolean = true, elevation: Dp = TopAppBarElevation, scrollBehavior: TopAppBarScrollBehavior? = null, @@ -106,6 +113,7 @@ public fun TopAppBarLarge( content = actions, ) }, + extraContent = extraContent, largeElevated = largeElevated, elevation = elevation, scrollBehavior = scrollBehavior, @@ -119,6 +127,7 @@ private fun TwoRowsTopAppBar( largeTitle: @Composable () -> Unit, navigationIcon: @Composable () -> Unit, actions: @Composable () -> Unit, + extraContent: @Composable () -> Unit, largeElevated: Boolean, elevation: Dp, scrollBehavior: TopAppBarScrollBehavior?, @@ -177,6 +186,7 @@ private fun TwoRowsTopAppBar( hideTitleSemantics = hideBottomRowSemantics, modifier = Modifier, ) + extraContent() } } } else { @@ -210,6 +220,7 @@ private fun TwoRowsTopAppBar( WindowInsets.systemBars.only(WindowInsetsSides.Horizontal), ), ) + extraContent() } } } @@ -257,5 +268,24 @@ internal fun TopAppBarLargePreview() { } }, ) + TopAppBarLarge( + title = { Text("Title") }, + onNavigateUp = {}, + extraContent = { + var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) } + TabRow(selectedTabIndex = selectedTabIndex) { + Tab( + selected = selectedTabIndex == 0, + onClick = { selectedTabIndex = 0 }, + text = { Text("Tab A") }, + ) + Tab( + selected = selectedTabIndex == 1, + onClick = { selectedTabIndex = 1 }, + text = { Text("Tab B") }, + ) + } + }, + ) } } diff --git a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar.png b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar.png index 6e8832304..c67388952 100644 --- a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar.png +++ b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1824321e41207a00317051e111d8f4bc1863edb2c75a95c5c42aa0458e0631c -size 9808 +oid sha256:c44f408378720ef3d583dbcdf1c2abd472683e10c6cf58809d3f1a11ab1a1994 +size 20297 diff --git a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge.png b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge.png index 5fcebac04..f72d55d03 100644 --- a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge.png +++ b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53a0d1b3ad71675c940c6d53eb60b459176bdd02dc1c6133d8d5f38ac2cac39f -size 13439 +oid sha256:555c3ae5d3eb2c6a18e754d36e012091ed3a03120f471deafe18c39bba64983f +size 26185 diff --git a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge_big.png b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge_big.png index 87635e0c8..6f578ca86 100644 --- a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge_big.png +++ b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge_big.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9fb3f4e71b1ecdc9f9f14a1bb4ac8c5c236bde5dc674505663612c3e1c7e648f -size 19383 +oid sha256:cf60e87f03402af8a4a8ddfa6aadfe668c0c70caef86127dba512d9ff0cb8327 +size 27659 diff --git a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge_dark.png b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge_dark.png index 23085913e..31982e053 100644 --- a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge_dark.png +++ b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBarLarge_dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00b6940263b391e8e6b8e18296e958b77a231615de889d51d4dbb6fd4ca54165 -size 12811 +oid sha256:379485b4f1d6e1d9850550f2ac0ead27198a18c0cfbf644e62e228d13b2080ff +size 25397 diff --git a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar_big.png b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar_big.png index 953d15f26..300af954f 100644 --- a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar_big.png +++ b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar_big.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5743cbec948fe8f5cdd2fdec498689e45a713ab3dd825b182dc355af4a7c37fc -size 13657 +oid sha256:2943873c4a16491249121316043633cfc94fa1fa4660a0fdb84776772e2ea2e3 +size 29256 diff --git a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar_dark.png b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar_dark.png index 0f9a52fd8..e45351a9f 100644 --- a/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar_dark.png +++ b/ui/src/test/snapshots/images/kiwi.orbit.compose.ui_ScreenshotTest_topAppBar_dark.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f76eedb235acf4586fb0e22311a127054e9a8398a2fbabd2b556acfc26ef083 -size 9134 +oid sha256:edb3f8204ee529a809b00d4691db9497540b392baae891faf8a68588ccad9216 +size 19568