I am seeing some super weird behavior with draggin...
# compose-desktop
a
I am seeing some super weird behavior with dragging. I get delays and yanking when I drag vertically, but not when I drag horizontally. I simply use the
onDrag
modifier.
a
Can you post a short snippet to reproduce it?
d
Hey dude! This looks like some pretty sweet drag and drop playground! Would you mind sharing the code for this?
a
@dewildte thanks. I can but keep in mind it is part of an experiment of mine where I try to use a clean architecture (interactors, observers, stores, viewmodels) for complex UI. So it is not idiomatic. It is inspired by the Tivi app repository. I’ll see if I can share it somehow. However, I must say this architecture looks to be pretty scalable
@Alexander Maryanovsky https://github.com/avwie/kotlinx/tree/bug/vertical-drag-fail/demos/flow Here you go. Run the App.kt in the jvmMain of
demos/flow
. Please mind that it is part of a larger repository, so it is a big repo with plugins and whatnot... However, the jest should be clear. I simplified the example. As you can see in the movie I show some console logging. It happens in the
onDrag
modifier.
@dewildte Here you go for the current example. Heavily WIP: https://github.com/avwie/kotlinx/tree/feature/flow, and go to the demos/flow project. Basically: • stores store the mutable state and expose (stateflows) and methods to modify the state. They typically model 1 specific piece of state. Like icons, or grid, or a selectionbox. • observers observe some state of stores and expose them as flows and model the observable use-cases • interactors modify stores and model the mutation use-cases • viewmodels model the view and can only address interactors and observers and expose view state (based on observers) and methods (based on interactors) • compose ui can only interact with viewmodels and contains no mutable state (maybe for local effects only, like animations). Everything is passed via props. • everything is wired up with KodeinDI This way you have a very clear separation and dataflow. ViewModel -> Interactor -> Store -> Observer -> ViewModel. It is Single Responsibility Principle in the extreme. This is just a POC to see how it fares with a more complicated UI example. So far I am happy with it.
a
Ok, I’ll take a look later today.
a
@Alexander Maryanovsky Let me know if you need more input. I can see if I can make a smaller example if needed.
@Alexander Maryanovsky I created a minimal example here: https://gist.github.com/avwie/2248cd9642f7d8f3a60347f4b4495ac4 Just initiate a brand new Compose Multiplatform project in IntelliJ for Desktop only and paste this in
Main.kt
My environment: JVM: Coretto 17 aarm64 (but tried different ones) Mac M1 Air Kotlin 1.8.20 Compose 1.3.0
a
Did you try compose 1.4?
a
Yup, no difference. I just tried it 5 seconds ago.
My original example was Compose 1.4.0
It is so strange that it only happens for 'dominant' vertical movement
a
Indeed
a
Amazing, thanks!
a
Should be fixed in the next Compose for desktop release.
In the meanwhile you can use this workaround:
Copy code
data class NoSlopViewConfiguration(
    override val longPressTimeoutMillis: Long,
    override val doubleTapTimeoutMillis: Long,
    override val doubleTapMinTimeMillis: Long,
    override val touchSlop: Float,
): ViewConfiguration

fun noSlopViewConfiguration(viewConfiguration: ViewConfiguration) = NoSlopViewConfiguration(
    longPressTimeoutMillis = viewConfiguration.longPressTimeoutMillis,
    doubleTapTimeoutMillis = viewConfiguration.doubleTapTimeoutMillis,
    doubleTapMinTimeMillis = viewConfiguration.doubleTapMinTimeMillis,
    touchSlop = 0f
)

@OptIn(ExperimentalFoundationApi::class)
@Composable fun Entity(
    state: Entity,
    onDragStart: () -> Unit = {},
    onDrag: (DpOffset) -> Unit = {},
    onDragEnd: () -> Unit = {}
) {
    with(LocalDensity.current) {
        val viewConfig = LocalViewConfiguration.current
        CompositionLocalProvider(LocalViewConfiguration provides noSlopViewConfiguration(viewConfig)){
            ...
        }
    }
}