Status Update
Comments
is...@google.com <is...@google.com>
[Deleted User] <[Deleted User]> #2
Does the program work without the compiler switch. That is, is `"-P", "plugin:androidx.compose.compiler.plugins.kotlin:experimentalStrongSkipping=true",` required to reproduce or is just changing the runtime enough?
os...@google.com <os...@google.com>
ho...@google.com <ho...@google.com> #3
Sorry for that, I will try to extract an example when I'm free.
ti...@gmail.com <ti...@gmail.com> #4
I have find a sample code to reproduce that
setContent {
val dialogState = remember { DialogState() }
dialogState.Intercept()
LaunchedEffect(Unit) {
delay(1000)
dialogState.bgWork {
delay(5000)
}
dialogState.showSelectActions {
onSelect("a") {
}
onSelect("b") {
}
}
}
}
You can find implementation of DialogState
here
[Deleted User] <[Deleted User]> #5
Let me sort it out
The first crash
Reproduce: navigate to a gallery and navigate back
The reason is we have some code assume the forget order of RememberObserver(DisposableEffect), and 52835066c9044647a65dfb566f03131aab46e793
changed the order. Seems this is a intended behaviour.
I will fix it from my side. My bad
The second crash
Reproduce: #4 comment
StackTrace:
We got a wrong object from SlotTable during recompose
ap...@google.com <ap...@google.com> #6
And interestingly, if we insert delay(1000) between two dialog suspend usage
dialogState.bgWork {
delay(5000)
}
delay(1000)
dialogState.showSelectActions {
onSelect("a") {
}
onSelect("b") {
}
}
It will not crash
ri...@ffw.com <ri...@ffw.com> #7
As for the order of `onForgotten`, it may be you are seeing and issue that I fixed in a subsequent version as this, for the snapshot builds, was broken for a few weeks when using the non-skipping group optimization even indirectly.
os...@google.com <os...@google.com> #8
pr...@google.com <pr...@google.com> #9
I tried cutting down the example myself and was not able to reproduce this.
The primary dependency chagnes I made were:
compose-material3 = { module = "androidx.compose.material3:material3", version = "1.3.0-SNAPSHOT" }
compose-foundation = { module = "androidx.compose.foundation:foundation-android", version = "1.7.0-SNAPSHOT" }
I only included the part of the Dialog.kt that was needed by the above,
class DialogState {
var content: (@Composable () -> Unit)? by mutableStateOf(null)
@Composable
fun Intercept() = content?.invoke()
fun dismiss() {
content = null
}
suspend inline fun <R> dialog(crossinline block: @Composable (CancellableContinuation<R>) -> Unit) = suspendCancellableCoroutine<R> { cont ->
cont.invokeOnCancellation { dismiss() }
val realContinuation = object : CancellableContinuation<R> by cont {
override fun resumeWith(result: Result<R>) {
dismiss()
cont.resumeWith(result)
}
}
content = { block(realContinuation) }
}
suspend inline fun showSelectActions(
title: String? = null,
builder: ActionScope.() -> Unit,
) {
val (items, actions) = buildList { builder(ActionScope { action, that -> add(action to that) }) }.unzip()
val selected = showSelectItem(items, title)
actions[selected].invoke()
}
suspend fun showSelectItem(
items: List<String>,
title: String?,
respectDefaultWidth: Boolean = true,
): Int = showNoButton(respectDefaultWidth) {
Column(modifier = Modifier.padding(vertical = 8.dp)) {
if (title != null) {
Text(
text = title,
modifier = Modifier.padding(horizontal = 24.dp, vertical = 8.dp),
style = MaterialTheme.typography.headlineSmall,
)
}
LazyColumn {
itemsIndexed(items) { index, text ->
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.tertiary) {
Text(
text = text,
modifier = Modifier.clickable { dismissWith(index) }.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 16.dp),
style = MaterialTheme.typography.titleMedium,
)
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
suspend fun <R> showNoButton(respectDefaultWidth: Boolean = true, block: @Composable DismissDialogScope<R>.() -> Unit): R {
return dialog { cont ->
val impl = remember(cont) {
DismissDialogScope<R> {
cont.resume(it)
}
}
BasicAlertDialog(
onDismissRequest = { cont.cancel() },
properties = DialogProperties(usePlatformDefaultWidth = respectDefaultWidth),
content = {
Surface(
modifier = with(Modifier) { if (!respectDefaultWidth) defaultMinSize(280.dp) else width(280.dp) },
shape = AlertDialogDefaults.shape,
color = AlertDialogDefaults.containerColor,
tonalElevation = AlertDialogDefaults.TonalElevation,
content = { block(impl) },
)
},
)
}
}
}
fun interface ActionScope {
fun onSelect(action: String, that: suspend () -> Unit)
}
fun interface DismissDialogScope<R> {
fun dismissWith(value: R)
}
This shows the "Please wait" and then selection between "a" and "b" as I expected.
Description
I'm using a Composable which take a content @Composable in parameter, and it seems that with the final version of ConstraintLayout, there is no update.
Here is the code
@Composable
Example(
modifier : Modifier = Modifier,
content : @Composable () -> Unit
) {
ConstraintLayout(modifier = modifier
.fillMaxSize()
.background(color = Color.Blue)
) {
val (title, someContent) = createRefs()
Text(text = "a text", modifier = Modifier.constrainAs(title) {
top.linkTo(parent.top)
height = Dimension.wrapContent
width = Dimension.wrapContent
})
Box(modifier = Modifier
.constrainAs(someContent) {
width = Dimension.fillToConstraints
linkTo(start = parent.start, end = parent.end)
linkTo(top = parent.top, bottom = parent.bottom, bias = 1.0f)
height = Dimension.preferredWrapContent
}
.background(color = Color.Yellow)) {
content()
}
}
}
The Box height is initialized with the fist element received by the composable and does not change anymore.
For example, I send to this composable a Column with [Button + result of a Webservice]. The button is displayed at startup, and then after some times I received the result of the API, it does not recompose correctly, the size of the Box stays wrapcontent with the button only!
Moreover, it seems that the behaviour in a compose MotionLayout is the same (no update)