mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-26 19:35:48 +00:00
moare better
This commit is contained in:
+21
-12
@@ -14,6 +14,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.*
|
||||
import androidx.compose.ui.draw.*
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.*
|
||||
import androidx.compose.ui.graphics.layer.GraphicsLayer
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
@@ -1142,18 +1143,26 @@ fun ChatLayout(
|
||||
val draggingDown = range.startIndex > range.endIndex
|
||||
val gap = with(LocalDensity.current) { 4.dp.toPx() }
|
||||
var buttonSize by remember { mutableStateOf(IntSize.Zero) }
|
||||
val x = if (draggingDown) manager.focusWindowX
|
||||
else (manager.focusWindowX - buttonSize.width).coerceAtLeast(0f)
|
||||
val y = if (draggingDown) manager.focusWindowY + gap
|
||||
else (manager.focusWindowY - buttonSize.height - gap).coerceAtLeast(0f)
|
||||
val clampedX = x.coerceIn(0f, (manager.viewportWidth - buttonSize.width).coerceAtLeast(0f))
|
||||
val clampedY = y.coerceIn(0f, (manager.viewportHeight - buttonSize.height).coerceAtLeast(0f))
|
||||
SelectionCopyButton(
|
||||
modifier = Modifier
|
||||
.offset { IntOffset(clampedX.toInt(), clampedY.toInt()) }
|
||||
.onSizeChanged { buttonSize = it },
|
||||
onCopy = { manager.onCopySelection?.invoke() }
|
||||
)
|
||||
val ls = manager.listState?.value
|
||||
val itemInfo = ls?.layoutInfo?.visibleItemsInfo?.find { it.index == range.endIndex }
|
||||
if (ls != null && itemInfo != null && manager.focusCharRect != Rect.Zero) {
|
||||
val itemWindowY = (ls.layoutInfo.viewportEndOffset - itemInfo.offset - itemInfo.size).toFloat()
|
||||
val cr = manager.focusCharRect
|
||||
val charX = if (draggingDown) cr.right else cr.left
|
||||
val charY = itemWindowY + if (draggingDown) cr.bottom else cr.top
|
||||
val x = if (draggingDown) charX
|
||||
else (charX - buttonSize.width).coerceAtLeast(0f)
|
||||
val y = if (draggingDown) charY + gap
|
||||
else (charY - buttonSize.height - gap).coerceAtLeast(0f)
|
||||
val clampedX = x.coerceIn(0f, (manager.viewportWidth - buttonSize.width).coerceAtLeast(0f))
|
||||
val clampedY = y.coerceIn(0f, (manager.viewportHeight - buttonSize.height).coerceAtLeast(0f))
|
||||
SelectionCopyButton(
|
||||
modifier = Modifier
|
||||
.offset { IntOffset(clampedX.toInt(), clampedY.toInt()) }
|
||||
.onSizeChanged { buttonSize = it },
|
||||
onCopy = { manager.onCopySelection?.invoke() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -16,6 +16,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.key.*
|
||||
import androidx.compose.ui.input.pointer.*
|
||||
@@ -66,6 +67,8 @@ class SelectionManager {
|
||||
var focusWindowX by mutableStateOf(0f)
|
||||
var viewportWidth by mutableStateOf(0f)
|
||||
var viewportHeight by mutableStateOf(0f)
|
||||
var focusCharRect by mutableStateOf(Rect.Zero) // X: absolute window, Y: relative to item
|
||||
var listState: State<LazyListState>? = null
|
||||
var onCopySelection: (() -> Unit)? = null
|
||||
|
||||
fun startSelection(startIndex: Int, anchorY: Float, anchorX: Float) {
|
||||
@@ -85,9 +88,10 @@ class SelectionManager {
|
||||
range = r.copy(endIndex = index)
|
||||
}
|
||||
|
||||
fun updateFocusOffset(offset: Int) {
|
||||
fun updateFocusOffset(offset: Int, charRect: Rect = Rect.Zero) {
|
||||
val r = range ?: return
|
||||
range = r.copy(endOffset = offset)
|
||||
focusCharRect = charRect
|
||||
}
|
||||
|
||||
fun endSelection() {
|
||||
@@ -171,6 +175,7 @@ fun BoxScope.SelectionHandler(
|
||||
}
|
||||
}
|
||||
|
||||
manager.listState = listState
|
||||
manager.onCopySelection = {
|
||||
clipboard.setText(AnnotatedString(manager.getSelectedText(mergedItems.value.items, linkMode)))
|
||||
}
|
||||
|
||||
+14
-2
@@ -405,8 +405,20 @@ fun CIMarkdownText(
|
||||
val bounds = boundsState.value ?: return@collect
|
||||
val layout = layoutResultState.value ?: return@collect
|
||||
val offset = layout.getOffsetForPosition(Offset(px - bounds.left, py - bounds.top))
|
||||
Log.e(TAG, "focusOffset idx=$selectionIndex offset=$offset bounds=$bounds pointer=($px,$py)")
|
||||
selectionManager.updateFocusOffset(offset)
|
||||
val charBox = layout.getBoundingBox(offset.coerceIn(0, layout.layoutInput.text.length - 1))
|
||||
val ls = selectionManager.listState?.value
|
||||
val itemInfo = ls?.layoutInfo?.visibleItemsInfo?.find { it.index == selectionIndex }
|
||||
val charRect = if (ls != null && itemInfo != null) {
|
||||
val itemWindowY = (ls.layoutInfo.viewportEndOffset - itemInfo.offset - itemInfo.size).toFloat()
|
||||
Rect(
|
||||
left = bounds.left + charBox.left, // absolute window X
|
||||
top = bounds.top + charBox.top - itemWindowY, // relative to item Y
|
||||
right = bounds.left + charBox.right, // absolute window X
|
||||
bottom = bounds.top + charBox.bottom - itemWindowY // relative to item Y
|
||||
)
|
||||
} else Rect.Zero
|
||||
Log.e(TAG, "focusOffset idx=$selectionIndex offset=$offset bounds=$bounds pointer=($px,$py) charRect=$charRect")
|
||||
selectionManager.updateFocusOffset(offset, charRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user