I've seen a good practice of Jetpack Compose that ...
# compose
b
I've seen a good practice of Jetpack Compose that is to group Composable methods inside Objects, but never managed to use it because of one problem.
Copy code
object ButtonActionBar {   
    @Composable
    fun RowScope.CancelButton(onClick: () -> Unit) {
        Button(
            modifier = Modifier.weight(2f),
            onClick = onClick
        ) {
            Text(
                text = "Cancel"
            )
        }
    }
}

@Composable
fun RowScope.PublishButton(onClick: () -> Unit) {
    Button(
        modifier = Modifier.weight(2f),
        onClick = onClick
    ) {
        Text(
            text = "Publish"
        )
    }
}
Copy code
Row(
   modifier = Modifier.height(48.dp)
) {
   SessionActionBar.CancelButton() {}
   PublishButton {}
}
In this example the
PublishButton
work fine but not the
CancelButton
, if I remove the
RowScope
it kinda work (but then I don't have access to
weight
modifier) or need to move it outside of
ButtonActionBar
object as the
PublishButton
j
you will have to do this with context/multiple receivers in 1.6.20
b
@Javier Interesting thanks. So there is no other way using Jetpack Compose 1.1.1 & Kotlin 1.6.10 than move it out of the Object?
j
yeah, looks like the same use case about declaring
val Int.dp
that can only be used in
Activity
or
Fragment
, and that example is in the context receivers keep docs
n
the above code is working for me though 🤔 i don't see why it wouldn't work
well sorry, it works because I write
CancelButton { }
directly, not
ButtonActionBar.CancelButton
I'm not sure the context received will help here as you're not in the context of your object
j
context receivers allow adding context to objects too, not only functions
so you could do
Copy code
context(RowScope)
object ButtonActionBar
so you will be able to use
ButtonActionBar
only when the context is a row scope
n
now I'm triggered and I have to CHECK 😄 btw @Benjamin Deroche, I don't think you should for the use of RowScope in your component, it's actually a bad idea as it restrict it to one kind of composable (imagine you want it in a column now) What you should do is remove the RowScope and pass a Modifier as a parameter (which would be
Modifier.weight(2f)
)
b
Very good idea, thanks !
n
welp I tried to use context receiver but I can't make it (ide say I need to use a compiler flag which I did, and compilation shot IR backend error) but I stand on my ground and think even with context receiver it wouldn't work, as the issue is using the syntax object.extensionmethod() instead of extensionmethod() directly context receiver solve the case when you can to use extensionmethod() only from "inside" of object() (which is not the case here) I'll recheck when it will be officially available
a
Btw I don’t think this is a good practice. See this thread.
👍 1
b
@Albert Chang What are the guidelines/good practices you use to organize your Compose UI code then?
s
Probably the organization can happen module-wise. If something is used by everything, it can be in a common module and if it’s in a specific feature in can be internal there. If the app has no modules this does indeed feel like a problem. A lot of them will have to be public if they’re used from let’s say 2 different places making them unable to be private, but I guess that’s the best one can do
☝️ 1
n
I have high hopes for this kotlin feature : https://youtrack.jetbrains.com/issue/KT-29227
s
I wouldn’t hold my breath
👍 1
🙏 1