mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-26 17:27:57 +00:00
refactor 2
This commit is contained in:
@@ -14,7 +14,6 @@ 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
|
||||
@@ -1137,19 +1136,7 @@ fun ChatLayout(
|
||||
}
|
||||
// Desktop selection copy button — last child of outer Box, on top of everything
|
||||
if (appPlatform.isDesktop) {
|
||||
val manager = LocalSelectionManager.current
|
||||
val range = manager?.range
|
||||
if (manager != null && manager.selectionState == SelectionState.Selected && range != null && manager.focusCharRect != Rect.Zero) {
|
||||
val draggingDown = range.startIndex > range.endIndex || (range.startIndex == range.endIndex && range.startOffset < range.endOffset)
|
||||
val gap = with(LocalDensity.current) { 4.dp.toPx() }
|
||||
var buttonSize by remember { mutableStateOf(IntSize.Zero) }
|
||||
SelectionCopyButton(
|
||||
modifier = Modifier
|
||||
.offset { manager.copyButtonOffset(draggingDown, gap, buttonSize) }
|
||||
.onSizeChanged { buttonSize = it },
|
||||
onCopy = { manager.onCopySelection?.invoke() }
|
||||
)
|
||||
}
|
||||
SelectionCopyButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,10 @@ import androidx.compose.ui.input.key.*
|
||||
import androidx.compose.ui.input.pointer.*
|
||||
import androidx.compose.ui.layout.boundsInWindow
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.layout.positionInWindow
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalViewConfiguration
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.TextLayoutResult
|
||||
@@ -404,14 +406,48 @@ fun setupItemSelection(selectionManager: SelectionManager?, selectionIndex: Int,
|
||||
return ItemSelection(highlightRange, positionModifier, onTextLayoutResult)
|
||||
}
|
||||
|
||||
// Sets up full-item selection for emoji items (no character-level tracking).
|
||||
@Composable
|
||||
fun SelectionCopyButton(modifier: Modifier = Modifier, onCopy: () -> Unit) {
|
||||
fun setupEmojiSelection(selectionManager: SelectionManager?, selectionIndex: Int, textLength: Int): Boolean {
|
||||
if (selectionManager == null || selectionIndex < 0) return false
|
||||
|
||||
val isAnchor = remember(selectionIndex) {
|
||||
derivedStateOf { selectionManager.range?.startIndex == selectionIndex && selectionManager.selectionState == SelectionState.Selecting }
|
||||
}
|
||||
LaunchedEffect(isAnchor.value) {
|
||||
if (!isAnchor.value) return@LaunchedEffect
|
||||
selectionManager.setAnchorOffset(0)
|
||||
}
|
||||
|
||||
val isFocus = remember(selectionIndex) {
|
||||
derivedStateOf { selectionManager.range?.endIndex == selectionIndex && selectionManager.selectionState == SelectionState.Selecting }
|
||||
}
|
||||
if (isFocus.value) {
|
||||
LaunchedEffect(Unit) {
|
||||
snapshotFlow { selectionManager.focusWindowY }
|
||||
.collect { selectionManager.updateFocusOffset(textLength) }
|
||||
}
|
||||
}
|
||||
|
||||
return remember(selectionIndex) { derivedStateOf { selectedRange(selectionManager.range, selectionIndex) != null } }.value
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SelectionCopyButton() {
|
||||
val manager = LocalSelectionManager.current ?: return
|
||||
val range = manager.range ?: return
|
||||
if (manager.selectionState != SelectionState.Selected || manager.focusCharRect == Rect.Zero) return
|
||||
val draggingDown = range.startIndex > range.endIndex || (range.startIndex == range.endIndex && range.startOffset < range.endOffset)
|
||||
val gap = with(LocalDensity.current) { 4.dp.toPx() }
|
||||
var buttonSize by remember { mutableStateOf(IntSize.Zero) }
|
||||
Row(
|
||||
modifier
|
||||
Modifier
|
||||
.offset { manager.copyButtonOffset(draggingDown, gap, buttonSize) }
|
||||
.onSizeChanged { buttonSize = it }
|
||||
.background(MaterialTheme.colors.surface, RoundedCornerShape(20.dp))
|
||||
.border(1.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.12f), RoundedCornerShape(20.dp))
|
||||
.clip(RoundedCornerShape(20.dp))
|
||||
.clickable { onCopy() }
|
||||
.clickable { manager.onCopySelection?.invoke() }
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
|
||||
@@ -22,33 +22,8 @@ val mediumEmojiFont: TextStyle = TextStyle(fontSize = 36.sp, fontFamily = EmojiF
|
||||
|
||||
@Composable
|
||||
fun EmojiItemView(chatItem: ChatItem, timedMessagesTTL: Int?, showViaProxy: Boolean, showTimestamp: Boolean) {
|
||||
val selectionManager = LocalSelectionManager.current
|
||||
val selectionIndex = LocalItemContext.current.selectionIndex
|
||||
val emojiText = chatItem.content.text.trim()
|
||||
|
||||
if (selectionManager != null && selectionIndex >= 0) {
|
||||
val isAnchor = remember(selectionIndex) {
|
||||
derivedStateOf { selectionManager.range?.startIndex == selectionIndex && selectionManager.selectionState == SelectionState.Selecting }
|
||||
}
|
||||
LaunchedEffect(isAnchor.value) {
|
||||
if (!isAnchor.value) return@LaunchedEffect
|
||||
selectionManager.setAnchorOffset(0)
|
||||
}
|
||||
|
||||
val isFocus = remember(selectionIndex) {
|
||||
derivedStateOf { selectionManager.range?.endIndex == selectionIndex && selectionManager.selectionState == SelectionState.Selecting }
|
||||
}
|
||||
if (isFocus.value) {
|
||||
LaunchedEffect(Unit) {
|
||||
snapshotFlow { selectionManager.focusWindowY }
|
||||
.collect { selectionManager.updateFocusOffset(emojiText.length) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val isSelected = if (selectionManager != null && selectionIndex >= 0) {
|
||||
remember(selectionIndex) { derivedStateOf { selectedRange(selectionManager.range, selectionIndex) != null } }.value
|
||||
} else false
|
||||
val isSelected = setupEmojiSelection(LocalSelectionManager.current, LocalItemContext.current.selectionIndex, emojiText.length)
|
||||
|
||||
Column(
|
||||
Modifier.padding(vertical = 8.dp, horizontal = 12.dp),
|
||||
|
||||
Reference in New Issue
Block a user