Compose 1.5.0 (#3584)

https://android-developers.googleblog.com/2023/08/whats-new-in-jetpack-compose-august-23-release.html
https://google.github.io/accompanist/navigation-animation
https://google.github.io/accompanist/pager
https://google.github.io/accompanist/placeholder


* Update dependency androidx.compose:compose-bom to v2023.08.00

* Update dependency androidx.navigation:navigation-compose to v2.7.0

* Migrate rememberPagerState & HorizontalPager

* material-motion-compose-core:1.0.4

* Migrate AnimatedNavHost

* Remove accompanist-insets-ui

* Add Placeholder sources from the original repo

* Migrate accompanist-insets-ui

* Minor Compose cleanups

* io.github.fornewid:material-motion-compose-core:1.0.6

* Remove accompanist-pager

* Remove ExperimentalAnimationApi imports

* Migrate ModalBottomSheetState

* Revert changes about insets-ui

* Cleanup

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
Goooler
2023-08-15 09:25:53 +08:00
committed by GitHub
parent 2ae7a9beac
commit 627f2d0c3f
29 changed files with 679 additions and 98 deletions
+4 -6
View File
@@ -326,8 +326,9 @@ dependencies {
implementation 'com.github.ChickenHook:RestrictionBypass:2.2'
implementation 'dev.rikka.tools.refine:runtime:4.3.0'
implementation platform("androidx.compose:compose-bom:2023.06.01")
implementation platform("androidx.compose:compose-bom:2023.08.00")
implementation "androidx.compose.ui:ui"
implementation "androidx.compose.ui:ui-util"
debugImplementation "androidx.compose.ui:ui-tooling"
implementation "androidx.compose.ui:ui-text-google-fonts"
implementation "androidx.compose.foundation:foundation"
@@ -338,18 +339,15 @@ dependencies {
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation "androidx.activity:activity-compose:1.7.2"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1"
implementation "androidx.navigation:navigation-compose:2.6.0"
implementation "androidx.navigation:navigation-compose:2.7.0"
implementation "androidx.palette:palette-ktx:1.0.0"
implementation "androidx.slice:slice-core:1.1.0-alpha02"
implementation "com.google.accompanist:accompanist-drawablepainter:$accompanist_version"
implementation "com.google.accompanist:accompanist-insets-ui:$accompanist_version"
implementation "com.google.accompanist:accompanist-navigation-animation:$accompanist_version"
implementation "com.google.accompanist:accompanist-permissions:$accompanist_version"
implementation "com.google.accompanist:accompanist-pager:$accompanist_version"
implementation "com.google.accompanist:accompanist-placeholder-material:$accompanist_version"
implementation "com.google.accompanist:accompanist-systemuicontroller:$accompanist_version"
implementation "com.google.android.material:material:1.9.0"
implementation "io.github.fornewid:material-motion-compose-core:0.12.3"
implementation "io.github.fornewid:material-motion-compose-core:1.0.6"
implementation 'dev.kdrag0n:colorkt:1.0.5'
implementation 'io.coil-kt:coil-compose:2.4.0'
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
@@ -9,7 +9,6 @@ import android.widget.Toast
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
@@ -30,6 +29,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.backup.LawnchairBackup
import app.lawnchair.ui.preferences.LocalNavController
@@ -40,11 +40,9 @@ import app.lawnchair.util.BackHandler
import app.lawnchair.util.hasFlag
import app.lawnchair.util.restartLauncher
import com.android.launcher3.R
import com.google.accompanist.navigation.animation.composable
import kotlinx.coroutines.launch
import java.util.Base64
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.restoreBackupGraph(route: String) {
preferenceGraph(route, {}) { subRoute ->
composable(
@@ -0,0 +1,261 @@
/*
* Copyright 2021 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 app.lawnchair.ui.placeholder
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.InfiniteRepeatableSpec
import androidx.compose.animation.core.MutableTransitionState
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.geometry.toRect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawOutline
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.node.Ref
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.LayoutDirection
/**
* Contains default values used by [Modifier.placeholder] and [PlaceholderHighlight].
*/
object PlaceholderDefaults {
/**
* The default [InfiniteRepeatableSpec] to use for [fade].
*/
val fadeAnimationSpec: InfiniteRepeatableSpec<Float> by lazy {
infiniteRepeatable(
animation = tween(delayMillis = 200, durationMillis = 600),
repeatMode = RepeatMode.Reverse,
)
}
/**
* The default [InfiniteRepeatableSpec] to use for [shimmer].
*/
val shimmerAnimationSpec: InfiniteRepeatableSpec<Float> by lazy {
infiniteRepeatable(
animation = tween(durationMillis = 1700, delayMillis = 200),
repeatMode = RepeatMode.Restart,
)
}
}
/**
* Draws some skeleton UI which is typically used whilst content is 'loading'.
*
* A version of this modifier which uses appropriate values for Material themed apps is available
* in the 'Placeholder Material' library.
*
* You can provide a [PlaceholderHighlight] which runs an highlight animation on the placeholder.
* The [shimmer] and [fade] implementations are provided for easy usage.
*
* A cross-fade transition will be applied to the content and placeholder UI when the [visible]
* value changes. The transition can be customized via the [contentFadeTransitionSpec] and
* [placeholderFadeTransitionSpec] parameters.
*
* You can find more information on the pattern at the Material Theming
* [Placeholder UI](https://material.io/design/communication/launch-screen.html#placeholder-ui)
* guidelines.
*
* @param visible whether the placeholder should be visible or not.
* @param color the color used to draw the placeholder UI.
* @param shape desired shape of the placeholder. Defaults to [RectangleShape].
* @param highlight optional highlight animation.
* @param placeholderFadeTransitionSpec The transition spec to use when fading the placeholder
* on/off screen. The boolean parameter defined for the transition is [visible].
* @param contentFadeTransitionSpec The transition spec to use when fading the content
* on/off screen. The boolean parameter defined for the transition is [visible].
*/
fun Modifier.placeholder(
visible: Boolean,
color: Color,
shape: Shape = RectangleShape,
highlight: PlaceholderHighlight? = null,
placeholderFadeTransitionSpec: @Composable Transition.Segment<Boolean>.() -> FiniteAnimationSpec<Float> = { spring() },
contentFadeTransitionSpec: @Composable Transition.Segment<Boolean>.() -> FiniteAnimationSpec<Float> = { spring() },
): Modifier = composed(
inspectorInfo = debugInspectorInfo {
name = "placeholder"
value = visible
properties["visible"] = visible
properties["color"] = color
properties["highlight"] = highlight
properties["shape"] = shape
},
) {
// Values used for caching purposes
val lastSize = remember { Ref<Size>() }
val lastLayoutDirection = remember { Ref<LayoutDirection>() }
val lastOutline = remember { Ref<Outline>() }
// The current highlight animation progress
var highlightProgress: Float by remember { mutableFloatStateOf(0f) }
// This is our crossfade transition
val transitionState = remember { MutableTransitionState(visible) }.apply {
targetState = visible
}
val transition = updateTransition(transitionState, "placeholder_crossfade")
val placeholderAlpha by transition.animateFloat(
transitionSpec = placeholderFadeTransitionSpec,
label = "placeholder_fade",
targetValueByState = { placeholderVisible -> if (placeholderVisible) 1f else 0f },
)
val contentAlpha by transition.animateFloat(
transitionSpec = contentFadeTransitionSpec,
label = "content_fade",
targetValueByState = { placeholderVisible -> if (placeholderVisible) 0f else 1f },
)
// Run the optional animation spec and update the progress if the placeholder is visible
val animationSpec = highlight?.animationSpec
if (animationSpec != null && (visible || placeholderAlpha >= 0.01f)) {
val infiniteTransition = rememberInfiniteTransition(label = "")
highlightProgress = infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = animationSpec,
label = "",
).value
}
val paint = remember { Paint() }
remember(color, shape, highlight) {
drawWithContent {
// Draw the composable content first
if (contentAlpha in 0.01f..0.99f) {
// If the content alpha is between 1% and 99%, draw it in a layer with
// the alpha applied
paint.alpha = contentAlpha
withLayer(paint) {
with(this@drawWithContent) {
drawContent()
}
}
} else if (contentAlpha >= 0.99f) {
// If the content alpha is > 99%, draw it with no alpha
drawContent()
}
if (placeholderAlpha in 0.01f..0.99f) {
// If the placeholder alpha is between 1% and 99%, draw it in a layer with
// the alpha applied
paint.alpha = placeholderAlpha
withLayer(paint) {
lastOutline.value = drawPlaceholder(
shape = shape,
color = color,
highlight = highlight,
progress = highlightProgress,
lastOutline = lastOutline.value,
lastLayoutDirection = lastLayoutDirection.value,
lastSize = lastSize.value,
)
}
} else if (placeholderAlpha >= 0.99f) {
// If the placeholder alpha is > 99%, draw it with no alpha
lastOutline.value = drawPlaceholder(
shape = shape,
color = color,
highlight = highlight,
progress = highlightProgress,
lastOutline = lastOutline.value,
lastLayoutDirection = lastLayoutDirection.value,
lastSize = lastSize.value,
)
}
// Keep track of the last size & layout direction
lastSize.value = size
lastLayoutDirection.value = layoutDirection
}
}
}
private fun DrawScope.drawPlaceholder(
shape: Shape,
color: Color,
highlight: PlaceholderHighlight?,
progress: Float,
lastOutline: Outline?,
lastLayoutDirection: LayoutDirection?,
lastSize: Size?,
): Outline? {
// shortcut to avoid Outline calculation and allocation
if (shape === RectangleShape) {
// Draw the initial background color
drawRect(color = color)
if (highlight != null) {
drawRect(
brush = highlight.brush(progress, size),
alpha = highlight.alpha(progress),
)
}
// We didn't create an outline so return null
return null
}
// Otherwise we need to create an outline from the shape
val outline = lastOutline.takeIf {
size == lastSize && layoutDirection == lastLayoutDirection
} ?: shape.createOutline(size, layoutDirection, this)
// Draw the placeholder color
drawOutline(outline = outline, color = color)
if (highlight != null) {
drawOutline(
outline = outline,
brush = highlight.brush(progress, size),
alpha = highlight.alpha(progress),
)
}
// Return the outline we used
return outline
}
private inline fun DrawScope.withLayer(
paint: Paint,
drawBlock: DrawScope.() -> Unit,
) = drawIntoCanvas { canvas ->
canvas.saveLayer(size.toRect(), paint)
drawBlock()
canvas.restore()
}
@@ -0,0 +1,145 @@
/*
* Copyright 2021 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 app.lawnchair.ui.placeholder
import androidx.annotation.FloatRange
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.InfiniteRepeatableSpec
import androidx.compose.runtime.Stable
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.util.lerp
import kotlin.math.max
/**
* A class which provides a brush to paint placeholder based on progress.
*/
@Stable
interface PlaceholderHighlight {
/**
* The optional [AnimationSpec] to use when running the animation for this highlight.
*/
val animationSpec: InfiniteRepeatableSpec<Float>?
/**
* Return a [Brush] to draw for the given [progress] and [size].
*
* @param progress the current animated progress in the range of 0f..1f.
* @param size The size of the current layout to draw in.
*/
fun brush(
@FloatRange(from = 0.0, to = 1.0) progress: Float,
size: Size,
): Brush
/**
* Return the desired alpha value used for drawing the [Brush] returned from [brush].
*
* @param progress the current animated progress in the range of 0f..1f.
*/
@FloatRange(from = 0.0, to = 1.0)
fun alpha(progress: Float): Float
companion object
}
/**
* Creates a [Fade] brush with the given initial and target colors.
*
* @param highlightColor the color of the highlight which is faded in/out.
* @param animationSpec the [AnimationSpec] to configure the animation.
*/
fun PlaceholderHighlight.Companion.fade(
highlightColor: Color,
animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.fadeAnimationSpec,
): PlaceholderHighlight = Fade(
highlightColor = highlightColor,
animationSpec = animationSpec,
)
/**
* Creates a [PlaceholderHighlight] which 'shimmers', using the given [highlightColor].
*
* The highlight starts at the top-start, and then grows to the bottom-end during the animation.
* During that time it is also faded in, from 0f..progressForMaxAlpha, and then faded out from
* progressForMaxAlpha..1f.
*
* @param highlightColor the color of the highlight 'shimmer'.
* @param animationSpec the [AnimationSpec] to configure the animation.
* @param progressForMaxAlpha The progress where the shimmer should be at it's peak opacity.
* Defaults to 0.6f.
*/
fun PlaceholderHighlight.Companion.shimmer(
highlightColor: Color,
animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.shimmerAnimationSpec,
@FloatRange(from = 0.0, to = 1.0) progressForMaxAlpha: Float = 0.6f,
): PlaceholderHighlight = Shimmer(
highlightColor = highlightColor,
animationSpec = animationSpec,
progressForMaxAlpha = progressForMaxAlpha,
)
private data class Fade(
private val highlightColor: Color,
override val animationSpec: InfiniteRepeatableSpec<Float>,
) : PlaceholderHighlight {
private val brush = SolidColor(highlightColor)
override fun brush(progress: Float, size: Size): Brush = brush
override fun alpha(progress: Float): Float = progress
}
private data class Shimmer(
private val highlightColor: Color,
override val animationSpec: InfiniteRepeatableSpec<Float>,
private val progressForMaxAlpha: Float = 0.6f,
) : PlaceholderHighlight {
override fun brush(
progress: Float,
size: Size,
): Brush = Brush.radialGradient(
colors = listOf(
highlightColor.copy(alpha = 0f),
highlightColor,
highlightColor.copy(alpha = 0f),
),
center = Offset(x = 0f, y = 0f),
radius = (max(size.width, size.height) * progress * 2).coerceAtLeast(0.01f),
)
override fun alpha(progress: Float): Float = when {
// From 0f...ProgressForOpaqueAlpha we animate from 0..1
progress <= progressForMaxAlpha -> {
lerp(
start = 0f,
stop = 1f,
fraction = progress / progressForMaxAlpha,
)
}
// From ProgressForOpaqueAlpha..1f we animate from 1..0
else -> {
lerp(
start = 1f,
stop = 0f,
fraction = (progress - progressForMaxAlpha) / (1f - progressForMaxAlpha),
)
}
}
}
@@ -0,0 +1,125 @@
/*
* Copyright 2021 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 app.lawnchair.ui.placeholder.material
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.spring
import androidx.compose.material.MaterialTheme
import androidx.compose.material.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.graphics.isSpecified
import app.lawnchair.ui.placeholder.PlaceholderDefaults
import app.lawnchair.ui.placeholder.PlaceholderHighlight
import app.lawnchair.ui.placeholder.placeholder
/**
* Returns the value used as the the `color` parameter value on [Modifier.placeholder].
*
* @param backgroundColor The current background color of the layout. Defaults to
* `MaterialTheme.colors.surface`.
* @param contentColor The content color to be used on top of [backgroundColor].
* @param contentAlpha The alpha component to set on [contentColor] when compositing the color
* on top of [backgroundColor]. Defaults to `0.1f`.
*/
@Composable
fun PlaceholderDefaults.color(
backgroundColor: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(backgroundColor),
contentAlpha: Float = 0.1f,
): Color = contentColor.copy(contentAlpha).compositeOver(backgroundColor)
/**
* Returns the value used as the the `highlightColor` parameter value of
* [PlaceholderHighlight.Companion.fade].
*
* @param backgroundColor The current background color of the layout. Defaults to
* `MaterialTheme.colors.surface`.
* @param alpha The alpha component to set on [backgroundColor]. Defaults to `0.3f`.
*/
@Composable
fun PlaceholderDefaults.fadeHighlightColor(
backgroundColor: Color = MaterialTheme.colors.surface,
alpha: Float = 0.3f,
): Color = backgroundColor.copy(alpha = alpha)
/**
* Returns the value used as the the `highlightColor` parameter value of
* [PlaceholderHighlight.Companion.shimmer].
*
* @param backgroundColor The current background color of the layout. Defaults to
* `MaterialTheme.colors.surface`.
* @param alpha The alpha component to set on [backgroundColor]. Defaults to `0.75f`.
*/
@Composable
fun PlaceholderDefaults.shimmerHighlightColor(
backgroundColor: Color = MaterialTheme.colors.surface,
alpha: Float = 0.75f,
): Color {
return backgroundColor.copy(alpha = alpha)
}
/**
* Draws some skeleton UI which is typically used whilst content is 'loading'.
*
* To customize the color and shape of the placeholder, you can use the foundation version of
* [Modifier.placeholder], along with the values provided by [PlaceholderDefaults].
*
* A cross-fade transition will be applied to the content and placeholder UI when the [visible]
* value changes. The transition can be customized via the [contentFadeTransitionSpec] and
* [placeholderFadeTransitionSpec] parameters.
*
* You can provide a [PlaceholderHighlight] which runs an highlight animation on the placeholder.
* The [shimmer] and [fade] implementations are provided for easy usage.
*
* You can find more information on the pattern at the Material Theming
* [Placeholder UI](https://material.io/design/communication/launch-screen.html#placeholder-ui)
* guidelines.
*
* @param visible whether the placeholder should be visible or not.
* @param color the color used to draw the placeholder UI. If [Color.Unspecified] is provided,
* the placeholder will use [PlaceholderDefaults.color].
* @param shape desired shape of the placeholder. If null is provided the placeholder
* will use the small shape set in [MaterialTheme.shapes].
* @param highlight optional highlight animation.
* @param placeholderFadeTransitionSpec The transition spec to use when fading the placeholder
* on/off screen. The boolean parameter defined for the transition is [visible].
* @param contentFadeTransitionSpec The transition spec to use when fading the content
* on/off screen. The boolean parameter defined for the transition is [visible].
*/
fun Modifier.placeholder(
visible: Boolean,
color: Color = Color.Unspecified,
shape: Shape? = null,
highlight: PlaceholderHighlight? = null,
placeholderFadeTransitionSpec: @Composable Transition.Segment<Boolean>.() -> FiniteAnimationSpec<Float> = { spring() },
contentFadeTransitionSpec: @Composable Transition.Segment<Boolean>.() -> FiniteAnimationSpec<Float> = { spring() },
): Modifier = composed {
Modifier.placeholder(
visible = visible,
color = if (color.isSpecified) color else PlaceholderDefaults.color(),
shape = shape ?: MaterialTheme.shapes.small,
highlight = highlight,
placeholderFadeTransitionSpec = placeholderFadeTransitionSpec,
contentFadeTransitionSpec = contentFadeTransitionSpec,
)
}
@@ -0,0 +1,61 @@
/*
* Copyright 2021 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 app.lawnchair.ui.placeholder.material
import androidx.annotation.FloatRange
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.InfiniteRepeatableSpec
import androidx.compose.runtime.Composable
import app.lawnchair.ui.placeholder.PlaceholderDefaults
import app.lawnchair.ui.placeholder.PlaceholderHighlight
import app.lawnchair.ui.placeholder.fade
import app.lawnchair.ui.placeholder.shimmer
/**
* Creates a [PlaceholderHighlight] which fades in an appropriate color, using the
* given [animationSpec].
*
* @param animationSpec the [AnimationSpec] to configure the animation.
*/
@Composable
fun PlaceholderHighlight.Companion.fade(
animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.fadeAnimationSpec,
): PlaceholderHighlight = PlaceholderHighlight.fade(
highlightColor = PlaceholderDefaults.fadeHighlightColor(),
animationSpec = animationSpec,
)
/**
* Creates a [PlaceholderHighlight] which 'shimmers', using a default color.
*
* The highlight starts at the top-start, and then grows to the bottom-end during the animation.
* During that time it is also faded in, from 0f..progressForMaxAlpha, and then faded out from
* progressForMaxAlpha..1f.
*
* @param animationSpec the [AnimationSpec] to configure the animation.
* @param progressForMaxAlpha The progress where the shimmer should be at it's peak opacity.
* Defaults to 0.6f.
*/
@Composable
fun PlaceholderHighlight.Companion.shimmer(
animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.shimmerAnimationSpec,
@FloatRange(from = 0.0, to = 1.0) progressForMaxAlpha: Float = 0.6f,
): PlaceholderHighlight = PlaceholderHighlight.shimmer(
highlightColor = PlaceholderDefaults.shimmerHighlightColor(),
animationSpec = animationSpec,
progressForMaxAlpha = progressForMaxAlpha,
)
@@ -73,8 +73,10 @@ private fun CustomIconShapePreference() {
val appliedIconShape = customIconShapeAdapter.state.value
val selectedIconShape = remember { mutableStateOf(appliedIconShape ?: IconShape.Circle) }
val selectedIconShapeApplied = derivedStateOf {
appliedIconShape.toString() == selectedIconShape.value.toString()
val selectedIconShapeApplied = remember {
derivedStateOf {
appliedIconShape.toString() == selectedIconShape.value.toString()
}
}
PreferenceLayout(
@@ -5,7 +5,6 @@ import android.content.Intent
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.itemsIndexed
@@ -26,6 +25,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.font.FontCache
import app.lawnchair.font.googlefonts.GoogleFontsListing
@@ -37,10 +37,7 @@ import app.lawnchair.ui.AndroidText
import app.lawnchair.ui.OverflowMenu
import app.lawnchair.ui.preferences.components.*
import com.android.launcher3.R
import com.google.accompanist.navigation.animation.composable
import kotlinx.coroutines.launch
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.fontSelectionGraph(route: String) {
preferenceGraph(route, {}) { subRoute ->
composable(
@@ -81,16 +78,18 @@ fun FontSelection(fontPref: BasePreferenceManager.FontPref) {
}
value = list
}
val allItems by derivedStateOf { customFonts + items }
val allItems by remember { derivedStateOf { items + customFonts } }
val adapter = fontPref.getAdapter()
var searchQuery by remember { mutableStateOf("") }
val hasFilter by derivedStateOf { searchQuery.isNotEmpty() }
val filteredItems by derivedStateOf {
if (hasFilter) {
val lowerCaseQuery = searchQuery.lowercase()
allItems.filter { it.displayName.lowercase().contains(lowerCaseQuery) }
} else items
val hasFilter by remember { derivedStateOf { searchQuery.isNotEmpty() } }
val filteredItems by remember {
derivedStateOf {
if (hasFilter) {
val lowerCaseQuery = searchQuery.lowercase()
allItems.filter { it.displayName.lowercase().contains(lowerCaseQuery) }
} else items
}
}
val request = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
@@ -9,7 +9,7 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
@@ -49,8 +49,8 @@ fun HomeScreenGridPreferences() {
val originalColumns = remember { columnsAdapter.state.value }
val originalRows = remember { rowsAdapter.state.value }
val columns = rememberSaveable { mutableStateOf(originalColumns) }
val rows = rememberSaveable { mutableStateOf(originalRows) }
val columns = rememberSaveable { mutableIntStateOf(originalColumns) }
val rows = rememberSaveable { mutableIntStateOf(originalRows) }
if (isPortrait) {
GridOverridesPreview(
@@ -60,7 +60,7 @@ fun HomeScreenGridPreferences() {
.align(Alignment.CenterHorizontally)
.clip(MaterialTheme.shapes.large)
) {
copy(numColumns = columns.value, numRows = rows.value)
copy(numColumns = columns.intValue, numRows = rows.intValue)
}
}
@@ -85,8 +85,8 @@ fun HomeScreenGridPreferences() {
val context = LocalContext.current
val applyOverrides = {
prefs.batchEdit {
columnsAdapter.onChange(columns.value)
rowsAdapter.onChange(rows.value)
columnsAdapter.onChange(columns.intValue)
rowsAdapter.onChange(rows.intValue)
}
LauncherAppState.getIDP(context).onPreferencesChanged(context)
navController.popBackStack()
@@ -103,7 +103,7 @@ fun HomeScreenGridPreferences() {
modifier = Modifier
.align(Alignment.CenterEnd)
.fillMaxWidth(),
enabled = columns.value != originalColumns || rows.value != originalRows
enabled = columns.intValue != originalColumns || rows.intValue != originalRows
) {
Text(text = stringResource(id = R.string.apply_grid))
}
@@ -7,7 +7,6 @@ import android.os.Process
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -27,6 +26,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.icons.*
import app.lawnchair.ui.OverflowMenu
@@ -37,13 +37,11 @@ import app.lawnchair.util.requireSystemService
import com.android.launcher3.R
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.google.accompanist.insets.ui.LocalScaffoldPadding
import com.google.accompanist.navigation.animation.composable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
import androidx.compose.material.MaterialTheme as Material2Theme
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.iconPickerGraph(route: String) {
preferenceGraph(route, {
IconPickerPreference(packageName = "")
@@ -162,11 +160,13 @@ fun IconPickerGrid(
.catch { loadFailed = true }
}
val categories by categoriesFlow.collectAsState(emptyList())
val filteredCategories by derivedStateOf {
categories.asSequence()
.map { it.filter(searchQuery) }
.filter { it.items.isNotEmpty() }
.toList()
val filteredCategories by remember {
derivedStateOf {
categories.asSequence()
.map { it.filter(searchQuery) }
.filter { it.items.isNotEmpty() }
.toList()
}
}
val density = LocalDensity.current
@@ -16,7 +16,6 @@
package app.lawnchair.ui.preferences
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@@ -25,6 +24,8 @@ import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import app.lawnchair.backup.ui.createBackupGraph
import app.lawnchair.backup.ui.restoreBackupGraph
import app.lawnchair.ui.preferences.about.aboutGraph
@@ -32,8 +33,6 @@ import app.lawnchair.ui.preferences.components.SystemUi
import app.lawnchair.ui.preferences.components.colorpreference.colorSelectionGraph
import app.lawnchair.ui.util.ProvideBottomSheetHandler
import app.lawnchair.util.ProvideLifecycleState
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import soup.compose.material.motion.animation.materialSharedAxisXIn
import soup.compose.material.motion.animation.materialSharedAxisXOut
import soup.compose.material.motion.animation.rememberSlideDistance
@@ -68,10 +67,9 @@ val LocalPreferenceInteractor = staticCompositionLocalOf<PreferenceInteractor> {
error("CompositionLocal LocalPreferenceInteractor not present")
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun Preferences(interactor: PreferenceInteractor = viewModel<PreferenceViewModel>()) {
val navController = rememberAnimatedNavController()
val navController = rememberNavController()
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
val slideDistance = rememberSlideDistance()
@@ -82,7 +80,7 @@ fun Preferences(interactor: PreferenceInteractor = viewModel<PreferenceViewModel
LocalNavController provides navController,
LocalPreferenceInteractor provides interactor,
) {
AnimatedNavHost(
NavHost(
navController = navController,
startDestination = "/",
enterTransition = { materialSharedAxisXIn(!isRtl, slideDistance) },
@@ -3,13 +3,13 @@ package app.lawnchair.ui.preferences
import android.app.Activity
import android.content.Intent
import android.content.pm.LauncherApps
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.core.graphics.drawable.toBitmap
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.data.iconoverride.IconOverrideRepository
import app.lawnchair.icons.IconPickerItem
@@ -21,10 +21,8 @@ import app.lawnchair.ui.util.OnResult
import app.lawnchair.util.requireSystemService
import com.android.launcher3.R
import com.android.launcher3.util.ComponentKey
import com.google.accompanist.navigation.animation.composable
import kotlinx.coroutines.launch
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.selectIconGraph(route: String) {
preferenceGraph(route, { }) { subRoute ->
composable(
@@ -34,9 +34,9 @@ import androidx.compose.ui.unit.dp
import app.lawnchair.theme.surfaceColorAtElevation
import app.lawnchair.ui.preferences.components.PreferenceTemplate
import coil.compose.SubcomposeAsyncImage
import com.google.accompanist.placeholder.PlaceholderHighlight
import com.google.accompanist.placeholder.material.fade
import com.google.accompanist.placeholder.material.placeholder
import app.lawnchair.ui.placeholder.PlaceholderHighlight
import app.lawnchair.ui.placeholder.material.fade
import app.lawnchair.ui.placeholder.material.placeholder
@Composable
fun ContributorRow(name: String, description: String, photoUrl: String, url: String) {
@@ -17,7 +17,6 @@
package app.lawnchair.ui.preferences.about.acknowledgements
import androidx.compose.animation.Crossfade
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.fillMaxWidth
@@ -35,6 +34,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import app.lawnchair.ui.preferences.LocalNavController
import app.lawnchair.ui.preferences.LocalPreferenceInteractor
@@ -42,9 +42,7 @@ import app.lawnchair.ui.preferences.components.*
import app.lawnchair.ui.preferences.preferenceGraph
import app.lawnchair.ui.preferences.subRoute
import com.android.launcher3.R
import com.google.accompanist.navigation.animation.composable
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.licensesGraph(route: String) {
preferenceGraph(route, { Acknowledgements() }) { subRoute ->
composable(
@@ -24,12 +24,11 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import app.lawnchair.ui.placeholder.PlaceholderHighlight
import app.lawnchair.ui.placeholder.material.fade
import app.lawnchair.ui.placeholder.material.placeholder
import app.lawnchair.util.App
import com.google.accompanist.placeholder.PlaceholderHighlight
import com.google.accompanist.placeholder.material.fade
import com.google.accompanist.placeholder.material.placeholder
@Composable
fun AppItem(
@@ -28,7 +28,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.lawnchair.ui.AlertBottomSheetContent
import app.lawnchair.ui.util.bottomSheetHandler
import com.android.launcher3.R
@Composable
fun ClickablePreference(
@@ -3,6 +3,7 @@ package app.lawnchair.ui.preferences.components
import android.content.Context
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
@@ -20,8 +21,8 @@ import app.lawnchair.ui.StretchEdgeEffect
@Composable
fun NestedScrollStretch(content: @Composable () -> Unit) {
val invalidateTick = remember { mutableStateOf(0) }
val invalidate = Runnable { invalidateTick.value++ }
val invalidateTick = remember { mutableIntStateOf(0) }
val invalidate = Runnable { invalidateTick.intValue++ }
val context = LocalContext.current
val connection = remember { NestedScrollStretchConnection(context, invalidate) }
@@ -38,7 +39,7 @@ fun NestedScrollStretch(content: @Composable () -> Unit) {
}
.drawWithContent {
// Redraw when this value changes
invalidateTick.value
invalidateTick.intValue
connection.topEdgeEffect.draw(tmpOut, StretchEdgeEffect.POSITION_TOP, this) {
connection.bottomEdgeEffect.draw(tmpOut, StretchEdgeEffect.POSITION_BOTTOM, this) {
@@ -16,7 +16,6 @@
package app.lawnchair.ui.preferences.components
import androidx.compose.animation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.ContentAlpha
import androidx.compose.material.MaterialTheme
@@ -25,9 +25,6 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@@ -19,9 +19,6 @@ package app.lawnchair.ui.preferences.components
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.material3.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -74,7 +74,7 @@ fun PreferenceSearchScaffold(
}
},
bottomBar = { BottomSpacer() },
contentPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues()
contentPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues(),
) {
val layoutDirection = LocalLayoutDirection.current
innerPadding.left = it.calculateLeftPadding(layoutDirection)
@@ -31,6 +31,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
@@ -76,7 +77,7 @@ fun SliderPreference(
showAsPercentage: Boolean = false,
) {
var adapterValue by adapter
var sliderValue by remember { mutableStateOf(adapterValue) }
var sliderValue by remember { mutableFloatStateOf(adapterValue) }
DisposableEffect(adapterValue) {
sliderValue = adapterValue
@@ -2,7 +2,6 @@ package app.lawnchair.ui.preferences.components.colorpreference
import android.content.Context
import android.graphics.Color
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.*
@@ -27,13 +26,12 @@ import app.lawnchair.ui.preferences.components.colorpreference.pickers.PresetsLi
import app.lawnchair.ui.preferences.components.colorpreference.pickers.SwatchGrid
import app.lawnchair.ui.preferences.preferenceGraph
import com.android.launcher3.R
import com.google.accompanist.navigation.animation.composable
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.navigation.compose.composable
import com.patrykmichalik.opto.domain.Preference
import kotlinx.coroutines.launch
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.colorSelectionGraph(route: String) {
preferenceGraph(route, {}) { subRoute ->
composable(
@@ -67,10 +65,10 @@ fun ColorSelection(
val adapter = preference.getAdapter()
val appliedColor = adapter.state.value
val context = LocalContext.current
val selectedColor = remember { mutableStateOf(appliedColor.forCustomPicker(context)) }
val selectedColor = remember { mutableIntStateOf(appliedColor.forCustomPicker(context)) }
val selectedColorApplied = remember {
derivedStateOf {
appliedColor is ColorOption.CustomColor && appliedColor.color == selectedColor.value
appliedColor is ColorOption.CustomColor && appliedColor.color == selectedColor.intValue
}
}
val defaultTabIndex = when {
@@ -80,11 +78,14 @@ fun ColorSelection(
}
val onPresetClick = { option: ColorOption ->
selectedColor.value = option.forCustomPicker(context)
selectedColor.intValue = option.forCustomPicker(context)
adapter.onChange(newValue = option)
}
val pagerState = rememberPagerState(initialPage = defaultTabIndex)
val pagerState = rememberPagerState(
initialPage = defaultTabIndex,
pageCount = { 2 },
)
PreferenceLayout(
label = label,
bottomBar = {
@@ -98,7 +99,7 @@ fun ColorSelection(
) {
Button(
enabled = !selectedColorApplied.value,
onClick = { adapter.onChange(newValue = ColorOption.CustomColor(selectedColor.value)) },
onClick = { adapter.onChange(newValue = ColorOption.CustomColor(selectedColor.intValue)) },
modifier = Modifier
.fillMaxWidth()
.padding(all = 16.dp),
@@ -132,7 +133,6 @@ fun ColorSelection(
)
}
HorizontalPager(
pageCount = 2,
state = pagerState,
verticalAlignment = Alignment.Top,
modifier = Modifier.animateContentSize(),
@@ -161,8 +161,8 @@ fun ColorSelection(
}
1 -> {
CustomColorPicker(
selectedColor = selectedColor.value,
onSelect = { selectedColor.value = it },
selectedColor = selectedColor.intValue,
onSelect = { selectedColor.intValue = it },
)
}
}
@@ -108,7 +108,10 @@ fun CustomColorPicker(
}
}
val pagerState = rememberPagerState(0)
val pagerState = rememberPagerState(
initialPage = 0,
pageCount = { 2 }
)
val scope = rememberCoroutineScope()
val scrollToPage =
{ page: Int -> scope.launch { pagerState.animateScrollToPage(page) } }
@@ -142,7 +145,6 @@ fun CustomColorPicker(
HorizontalPager(
modifier = Modifier.animateContentSize(),
pageCount = 2,
state = pagerState,
verticalAlignment = Alignment.Top,
) { page ->
@@ -274,9 +276,9 @@ private fun HsvColorPicker(
onSliderValuesChange: (Int) -> Unit,
) {
val hsv = remember { intColorToHsvColorArray(selectedColor) }
var hue by remember { mutableStateOf(hsv[0]) }
var saturation by remember { mutableStateOf(hsv[1]) }
var brightness by remember { mutableStateOf(hsv[2]) }
var hue by remember { mutableFloatStateOf(hsv[0]) }
var saturation by remember { mutableFloatStateOf(hsv[1]) }
var brightness by remember { mutableFloatStateOf(hsv[2]) }
val coroutineScope = rememberCoroutineScope()
fun updateColor(
@@ -343,9 +345,9 @@ private fun RgbColorPicker(
onSliderValuesChange: (Int) -> Unit,
) {
var red by remember { mutableStateOf(selectedColor.red) }
var green by remember { mutableStateOf(selectedColor.green) }
var blue by remember { mutableStateOf(selectedColor.blue) }
var red by remember { mutableIntStateOf(selectedColor.red) }
var green by remember { mutableIntStateOf(selectedColor.green) }
var blue by remember { mutableIntStateOf(selectedColor.blue) }
val coroutineScope = rememberCoroutineScope()
fun updateColor(
@@ -1,13 +1,11 @@
package app.lawnchair.ui.preferences
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.navigation.NavGraphBuilder
import com.google.accompanist.navigation.animation.composable
import androidx.navigation.compose.composable
@OptIn(ExperimentalAnimationApi::class)
inline fun NavGraphBuilder.preferenceGraph(
route: String,
crossinline root: @Composable () -> Unit,
@@ -2,7 +2,7 @@ package app.lawnchair.ui.util
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.Density
@@ -13,7 +13,7 @@ class LazyGridLayout(
private val gapWidth: Dp,
private val density: Density
) {
private val _numColumns = mutableStateOf(0)
private val _numColumns = mutableIntStateOf(0)
val numColumns: State<Int> = _numColumns
@Composable
@@ -23,7 +23,7 @@ class LazyGridLayout(
val gapWidth = gapWidth.roundToPx()
val availableWidth = (it.width - minWidth).coerceAtLeast(0)
val additionalCols = availableWidth / (minWidth + gapWidth)
_numColumns.value = 1 + additionalCols
_numColumns.intValue = 1 + additionalCols
}
}
}
@@ -52,9 +52,11 @@ fun ProvideBottomSheetHandler(
) {
val coroutineScope = rememberCoroutineScope()
var onDismiss by remember { mutableStateOf({}) }
val density = LocalDensity.current
val bottomSheetState = remember {
ModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
density = density,
confirmValueChange = {
if (it == ModalBottomSheetValue.Hidden) onDismiss()
true
@@ -2,7 +2,9 @@ package app.lawnchair.ui.util
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.remember
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
@@ -16,6 +16,7 @@ import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
@@ -41,8 +42,8 @@ class ComposeBottomSheet<T>(context: Context)
private val container = ComposeView(context)
private var imeShift = 0f
private var _hintCloseProgress = mutableStateOf(0f)
private val hintCloseProgress get() = _hintCloseProgress.value
private var _hintCloseProgress = mutableFloatStateOf(0f)
private val hintCloseProgress get() = _hintCloseProgress.floatValue
private var hintCloseDistance = 0f
init {
@@ -224,10 +225,10 @@ class ComposeBottomSheet<T>(context: Context)
private val HINT_CLOSE_PROGRESS = object : FloatProperty<ComposeBottomSheet<*>>("hintCloseProgress") {
override fun setValue(view: ComposeBottomSheet<*>, value: Float) {
view._hintCloseProgress.value = value
view._hintCloseProgress.floatValue = value
}
override fun get(view: ComposeBottomSheet<*>) = view._hintCloseProgress.value
override fun get(view: ComposeBottomSheet<*>) = view._hintCloseProgress.floatValue
}
fun <T> show(