fix: replace compose cursor position code with view
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
e2dfb7ecc0
commit
afa1f5941f
|
|
@ -78,7 +78,8 @@ fun NativeMessageField(
|
||||||
disabled: Boolean = false,
|
disabled: Boolean = false,
|
||||||
editMode: Boolean = false,
|
editMode: Boolean = false,
|
||||||
cancelEdit: () -> Unit = {},
|
cancelEdit: () -> Unit = {},
|
||||||
onFocusChange: (Boolean) -> Unit = {}
|
onFocusChange: (Boolean) -> Unit = {},
|
||||||
|
onSelectionChange: (Pair<Int, Int>) -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val placeholderResource = when (channelType) {
|
val placeholderResource = when (channelType) {
|
||||||
ChannelType.DirectMessage -> R.string.message_field_placeholder_dm
|
ChannelType.DirectMessage -> R.string.message_field_placeholder_dm
|
||||||
|
|
@ -155,6 +156,11 @@ fun NativeMessageField(
|
||||||
}
|
}
|
||||||
return ic
|
return ic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSelectionChanged(selStart: Int, selEnd: Int) {
|
||||||
|
super.onSelectionChanged(selStart, selEnd)
|
||||||
|
onSelectionChange(selStart to selEnd)
|
||||||
|
}
|
||||||
}.apply {
|
}.apply {
|
||||||
background = null
|
background = null
|
||||||
textSize = 16f
|
textSize = 16f
|
||||||
|
|
@ -319,6 +325,7 @@ fun NativeMessageFieldPreview() {
|
||||||
disabled = false,
|
disabled = false,
|
||||||
editMode = false,
|
editMode = false,
|
||||||
cancelEdit = {},
|
cancelEdit = {},
|
||||||
onFocusChange = {}
|
onFocusChange = {},
|
||||||
|
onSelectionChange = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
|
@ -91,10 +90,10 @@ import chat.revolt.sheets.ChannelInfoSheet
|
||||||
import chat.revolt.sheets.MessageContextSheet
|
import chat.revolt.sheets.MessageContextSheet
|
||||||
import com.discord.simpleast.core.simple.SimpleMarkdownRules
|
import com.discord.simpleast.core.simple.SimpleMarkdownRules
|
||||||
import com.discord.simpleast.core.simple.SimpleRenderer
|
import com.discord.simpleast.core.simple.SimpleRenderer
|
||||||
import java.io.File
|
|
||||||
import java.io.FileNotFoundException
|
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -180,13 +179,6 @@ fun ChannelScreen(
|
||||||
label = "ScrollDownFABPadding"
|
label = "ScrollDownFABPadding"
|
||||||
)
|
)
|
||||||
|
|
||||||
val fieldContent = remember(viewModel.pendingMessageContent, viewModel.textSelection) {
|
|
||||||
TextFieldValue(
|
|
||||||
viewModel.pendingMessageContent,
|
|
||||||
viewModel.textSelection
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(channelId) {
|
LaunchedEffect(channelId) {
|
||||||
viewModel.activeChannelId = channelId
|
viewModel.activeChannelId = channelId
|
||||||
viewModel.fetchChannel(channelId)
|
viewModel.fetchChannel(channelId)
|
||||||
|
|
@ -479,7 +471,7 @@ fun ChannelScreen(
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
NativeMessageField(
|
NativeMessageField(
|
||||||
value = fieldContent.text,
|
value = viewModel.pendingMessageContent,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
viewModel.pendingMessageContent = it
|
viewModel.pendingMessageContent = it
|
||||||
// viewModel.textSelection = it.selection
|
// viewModel.textSelection = it.selection
|
||||||
|
|
@ -528,6 +520,9 @@ fun ChannelScreen(
|
||||||
if (nowFocused && viewModel.currentBottomPane != BottomPane.None) {
|
if (nowFocused && viewModel.currentBottomPane != BottomPane.None) {
|
||||||
viewModel.currentBottomPane = BottomPane.None
|
viewModel.currentBottomPane = BottomPane.None
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onSelectionChange = {
|
||||||
|
viewModel.textSelection = it
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.runtime.toMutableStateList
|
import androidx.compose.runtime.toMutableStateList
|
||||||
import androidx.compose.ui.text.TextRange
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import chat.revolt.R
|
import chat.revolt.R
|
||||||
|
|
@ -71,7 +70,7 @@ class ChannelScreenViewModel : ViewModel() {
|
||||||
var hasNoMoreMessages by mutableStateOf(false)
|
var hasNoMoreMessages by mutableStateOf(false)
|
||||||
|
|
||||||
var pendingMessageContent by mutableStateOf("")
|
var pendingMessageContent by mutableStateOf("")
|
||||||
var textSelection by mutableStateOf(TextRange(0))
|
var textSelection by mutableStateOf(0 to 0)
|
||||||
var pendingReplies = mutableStateListOf<SendMessageReply>()
|
var pendingReplies = mutableStateListOf<SendMessageReply>()
|
||||||
var pendingAttachments = mutableStateListOf<FileArgs>()
|
var pendingAttachments = mutableStateListOf<FileArgs>()
|
||||||
|
|
||||||
|
|
@ -404,7 +403,8 @@ class ChannelScreenViewModel : ViewModel() {
|
||||||
msg.id == it.messageId
|
msg.id == it.messageId
|
||||||
} ?: return@onEach
|
} ?: return@onEach
|
||||||
pendingMessageContent = message.content ?: ""
|
pendingMessageContent = message.content ?: ""
|
||||||
textSelection = TextRange(message.content?.length ?: 0)
|
textSelection =
|
||||||
|
(message.content?.length ?: 0) to (message.content?.length ?: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.catch {
|
}.catch {
|
||||||
|
|
@ -456,18 +456,20 @@ class ChannelScreenViewModel : ViewModel() {
|
||||||
val currentSelection = textSelection
|
val currentSelection = textSelection
|
||||||
|
|
||||||
// if out of bounds, just append
|
// if out of bounds, just append
|
||||||
if (currentSelection.start > currentContent.length) {
|
if (currentSelection.first > currentContent.length) {
|
||||||
pendingMessageContent = currentContent + content
|
pendingMessageContent = currentContent + content
|
||||||
textSelection = TextRange(currentContent.length + content.length)
|
textSelection =
|
||||||
|
currentSelection.first + content.length to currentSelection.first + content.length
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val newContent = currentContent.substring(0, currentSelection.start) +
|
val newContent = currentContent.substring(0, currentSelection.first) +
|
||||||
content +
|
content +
|
||||||
currentContent.substring(currentSelection.end)
|
currentContent.substring(currentSelection.second)
|
||||||
|
|
||||||
pendingMessageContent = newContent
|
pendingMessageContent = newContent
|
||||||
textSelection = TextRange(currentSelection.start + content.length)
|
textSelection =
|
||||||
|
currentSelection.first + content.length to currentSelection.first + content.length
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun checkShouldDenyMessageField() {
|
suspend fun checkShouldDenyMessageField() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue