mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
Fix drag & drop
This commit is contained in:
@@ -69,23 +69,39 @@ object AttachmentDropHighlight {
|
|||||||
var activeBridge by mutableStateOf<AttachmentDropBridge?>(null)
|
var activeBridge by mutableStateOf<AttachmentDropBridge?>(null)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private val boundsByBridge = mutableMapOf<AttachmentDropBridge, Rect>()
|
private val boundsByKey = mutableMapOf<Any, Pair<AttachmentDropBridge, Rect>>()
|
||||||
|
private var lastPointer by mutableStateOf<Offset?>(null)
|
||||||
|
|
||||||
fun register(bridge: AttachmentDropBridge, bounds: Rect) {
|
fun register(key: Any, bridge: AttachmentDropBridge, bounds: Rect) {
|
||||||
boundsByBridge[bridge] = bounds
|
boundsByKey[key] = bridge to bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unregister(bridge: AttachmentDropBridge) {
|
fun unregister(key: Any) {
|
||||||
boundsByBridge.remove(bridge)
|
boundsByKey.remove(key)
|
||||||
if (activeBridge === bridge) activeBridge = null
|
if (activeBridge != null && boundsByKey.values.none { it.first === activeBridge }) {
|
||||||
|
activeBridge = hitTest(lastPointer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun syncFromPointer(windowPoint: Offset) {
|
fun syncFromPointer(windowPoint: Offset) {
|
||||||
|
lastPointer = windowPoint
|
||||||
activeBridge = hitTest(windowPoint)
|
activeBridge = hitTest(windowPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
activeBridge = null
|
activeBridge = null
|
||||||
|
lastPointer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isHighlightActive(bridge: AttachmentDropBridge): Boolean {
|
||||||
|
if (!AttachmentDragSession.isActive) return false
|
||||||
|
val point = lastPointer
|
||||||
|
if (point != null) {
|
||||||
|
return boundsByKey.values.any { (owner, bounds) ->
|
||||||
|
owner === bridge && bounds.contains(point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return activeBridge === bridge
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Delivers to the currently hovered target. Returns true if handled. */
|
/** Delivers to the currently hovered target. Returns true if handled. */
|
||||||
@@ -97,10 +113,11 @@ object AttachmentDropHighlight {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hitTest(windowPoint: Offset): AttachmentDropBridge? {
|
private fun hitTest(windowPoint: Offset?): AttachmentDropBridge? {
|
||||||
|
if (windowPoint == null) return null
|
||||||
var best: AttachmentDropBridge? = null
|
var best: AttachmentDropBridge? = null
|
||||||
var bestArea = Float.POSITIVE_INFINITY
|
var bestArea = Float.POSITIVE_INFINITY
|
||||||
boundsByBridge.forEach { (bridge, bounds) ->
|
boundsByKey.values.forEach { (bridge, bounds) ->
|
||||||
if (!bounds.contains(windowPoint)) return@forEach
|
if (!bounds.contains(windowPoint)) return@forEach
|
||||||
val area = bounds.width * bounds.height
|
val area = bounds.width * bounds.height
|
||||||
if (area > 0f && area < bestArea) {
|
if (area > 0f && area < bestArea) {
|
||||||
@@ -169,7 +186,7 @@ fun rememberAttachmentDropBridge(): AttachmentDropBridge = remember { Attachment
|
|||||||
/** Whether [bridge] currently owns the exclusive drop highlight. */
|
/** Whether [bridge] currently owns the exclusive drop highlight. */
|
||||||
@Composable
|
@Composable
|
||||||
fun AttachmentDropBridge.isDropHighlightActive(): Boolean =
|
fun AttachmentDropBridge.isDropHighlightActive(): Boolean =
|
||||||
AttachmentDropHighlight.activeBridge === this
|
AttachmentDropHighlight.isHighlightActive(this)
|
||||||
|
|
||||||
fun urisToSelectedAttachments(
|
fun urisToSelectedAttachments(
|
||||||
uris: List<String>,
|
uris: List<String>,
|
||||||
@@ -223,8 +240,9 @@ fun Modifier.chatAttachmentDropTarget(
|
|||||||
): Modifier = composed {
|
): Modifier = composed {
|
||||||
if (!enabled) return@composed Modifier
|
if (!enabled) return@composed Modifier
|
||||||
val permissionsHost = rememberAttachmentDropPermissionsHost()
|
val permissionsHost = rememberAttachmentDropPermissionsHost()
|
||||||
DisposableEffect(bridge) {
|
val registrationKey = remember { Any() }
|
||||||
onDispose { AttachmentDropHighlight.unregister(bridge) }
|
DisposableEffect(registrationKey) {
|
||||||
|
onDispose { AttachmentDropHighlight.unregister(registrationKey) }
|
||||||
}
|
}
|
||||||
val target = remember(bridge, permissionsHost) {
|
val target = remember(bridge, permissionsHost) {
|
||||||
object : DragAndDropTarget {
|
object : DragAndDropTarget {
|
||||||
@@ -260,7 +278,7 @@ fun Modifier.chatAttachmentDropTarget(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onGloballyPositioned { coords ->
|
onGloballyPositioned { coords ->
|
||||||
AttachmentDropHighlight.register(bridge, coords.boundsInRoot())
|
AttachmentDropHighlight.register(registrationKey, bridge, coords.boundsInRoot())
|
||||||
}.dragAndDropTarget(
|
}.dragAndDropTarget(
|
||||||
shouldStartDragAndDrop = { acceptsAttachmentDrop(it) },
|
shouldStartDragAndDrop = { acceptsAttachmentDrop(it) },
|
||||||
target = target,
|
target = target,
|
||||||
|
|||||||
Reference in New Issue
Block a user