fix(chat/mentions) fixes in mentions behavior

Changed cursor behavior to jump over text when it
reaches a mention, either on left or right side.
Also made mention to behave as link when hovered
with mouse so that it cannot be clicked and place
cursor inside it.

Also fixed keyboard focus to navigate only in the
suggestions list when this is opened.

Closes #4423
This commit is contained in:
Alexandra Betouni 2022-02-21 21:51:41 +02:00 committed by Iuri Matias
parent 3985272037
commit 5c30daab07
3 changed files with 50 additions and 12 deletions

View File

@ -43,6 +43,7 @@ Rectangle {
property int cursorPosition property int cursorPosition
signal itemSelected(var item, int lastAtPosition, int lastCursorPosition) signal itemSelected(var item, int lastAtPosition, int lastCursorPosition)
property alias listView: listView property alias listView: listView
property var inputField
property bool shouldHide: false property bool shouldHide: false
Timer { Timer {
@ -77,6 +78,9 @@ Rectangle {
// We change it back to 0 so that it can be used to select using the keyboard // We change it back to 0 so that it can be used to select using the keyboard
listView.currentIndex = 0 listView.currentIndex = 0
} }
if (visible) {
listView.forceActiveFocus();
}
} }
z: parent.z + 100 z: parent.z + 100
@ -122,7 +126,17 @@ Rectangle {
anchors.rightMargin: Style.current.halfPadding anchors.rightMargin: Style.current.halfPadding
anchors.bottomMargin: Style.current.halfPadding anchors.bottomMargin: Style.current.halfPadding
clip: true clip: true
Keys.priority: Keys.AfterItem
Keys.forwardTo: container.inputField
Keys.onPressed: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
container.itemSelected(mentionsListDelegate.items.get(listView.currentIndex).model, filterItem.lastAtPosition, filterItem.cursorPosition)
} else if (event.key === Qt.Key_Escape) {
container.hide();
} else if (event.key !== Qt.Key_Up && event.key !== Qt.Key_Down) {
event.accepted = false;
}
}
property int selectedIndex property int selectedIndex
property var selectedItem: selectedIndex == -1 ? null : model[selectedIndex] property var selectedItem: selectedIndex == -1 ? null : model[selectedIndex]
signal suggestionClicked(var item) signal suggestionClicked(var item)

View File

@ -118,15 +118,17 @@ Rectangle {
} }
} }
property var mentionsPos: []
function insertMention(aliasName, lastAtPosition, lastCursorPosition) { function insertMention(aliasName, lastAtPosition, lastCursorPosition) {
const hasEmoji = Emoji.hasEmoji(messageInputField.text) const hasEmoji = Emoji.hasEmoji(messageInputField.text)
const spanPlusAlias = `${Constants.mentionSpanTag}@${aliasName}</span> ` const spanPlusAlias = `${Constants.mentionSpanTag}@${aliasName}</a></span> `
let rightIndex = hasEmoji ? lastCursorPosition + 2 : lastCursorPosition let rightIndex = hasEmoji ? lastCursorPosition + 2 : lastCursorPosition
messageInputField.remove(lastAtPosition, rightIndex) messageInputField.remove(lastAtPosition, rightIndex)
messageInputField.insert(lastAtPosition, spanPlusAlias) messageInputField.insert(lastAtPosition, spanPlusAlias)
messageInputField.cursorPosition = lastAtPosition + aliasName.length + 2 messageInputField.cursorPosition = lastAtPosition + aliasName.length + 2;
mentionsPos.push({"leftIndex":lastAtPosition, "rightIndex": (messageInputField.cursorPosition-1)});
if (messageInputField.cursorPosition === 0) { if (messageInputField.cursorPosition === 0) {
// It reset to 0 for some reason, go back to the end // It reset to 0 for some reason, go back to the end
@ -161,7 +163,7 @@ Rectangle {
return false return false
} }
function onKeyPress(event){ function onKeyPress(event) {
if (event.modifiers === Qt.NoModifier && (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) { if (event.modifiers === Qt.NoModifier && (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) {
if (checkTextInsert()) { if (checkTextInsert()) {
event.accepted = true; event.accepted = true;
@ -225,16 +227,11 @@ Rectangle {
} }
if (event.key === Qt.Key_Down) { if (event.key === Qt.Key_Down) {
suggestionsBox.listView.incrementCurrentIndex()
return emojiSuggestions.listView.incrementCurrentIndex() return emojiSuggestions.listView.incrementCurrentIndex()
} }
if (event.key === Qt.Key_Up) { if (event.key === Qt.Key_Up) {
suggestionsBox.listView.decrementCurrentIndex()
return emojiSuggestions.listView.decrementCurrentIndex() return emojiSuggestions.listView.decrementCurrentIndex()
} }
if (event.key === Qt.Key_Escape) {
suggestionsBox.hide()
}
isColonPressed = (event.key === Qt.Key_Colon) && (event.modifiers & Qt.ShiftModifier); isColonPressed = (event.key === Qt.Key_Colon) && (event.modifiers & Qt.ShiftModifier);
@ -252,6 +249,21 @@ Rectangle {
suggestionsBox.hide(); suggestionsBox.hide();
} }
} }
if (mentionsPos.length > 0) {
for (var i = 0; i < mentionsPos.length; i++) {
if ((messageInputField.cursorPosition === mentionsPos[i].leftIndex) && (event.key === Qt.Key_Right)) {
messageInputField.cursorPosition = mentionsPos[i].rightIndex;
} else if ((messageInputField.cursorPosition === mentionsPos[i].rightIndex)) {
if ((event.key === Qt.Key_Backspace || event.key === Qt.Key_Delete)) {
messageInputField.remove(mentionsPos[i].rightIndex, mentionsPos[i].leftIndex);
mentionsPos.pop(i);
} else if (event.key === Qt.Key_Left) {
messageInputField.cursorPosition = mentionsPos[i].leftIndex;
}
}
}
}
} }
function wrapSelection(wrapWith) { function wrapSelection(wrapWith) {
@ -646,11 +658,18 @@ Rectangle {
filter: messageInputField.text filter: messageInputField.text
cursorPosition: messageInputField.cursorPosition cursorPosition: messageInputField.cursorPosition
property: ["name", "nickname", "ensName", "alias"] property: ["name", "nickname", "ensName", "alias"]
inputField: messageInputField
onItemSelected: function (item, lastAtPosition, lastCursorPosition) { onItemSelected: function (item, lastAtPosition, lastCursorPosition) {
messageInputField.forceActiveFocus();
let name = item.name.replace("@", "") let name = item.name.replace("@", "")
insertMention(name, lastAtPosition, lastCursorPosition) insertMention(name, lastAtPosition, lastCursorPosition)
suggestionsBox.suggestionsModel.clear() suggestionsBox.suggestionsModel.clear()
} }
onVisibleChanged: {
if (!visible) {
messageInputField.forceActiveFocus();
}
}
} }
ChatCommandsPopup { ChatCommandsPopup {
@ -949,7 +968,12 @@ Rectangle {
StatusSyntaxHighlighter { StatusSyntaxHighlighter {
quickTextDocument: messageInputField.textDocument quickTextDocument: messageInputField.textDocument
} }
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
enabled: parent.hoveredLink
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
StatusTextFormatMenu { StatusTextFormatMenu {
id: textFormatMenu id: textFormatMenu

View File

@ -178,7 +178,7 @@ QtObject {
readonly property var acceptedImageExtensions: [".png", ".jpg", ".jpeg", ".svg", ".gif"] readonly property var acceptedImageExtensions: [".png", ".jpg", ".jpeg", ".svg", ".gif"]
readonly property var acceptedDragNDropImageExtensions: [".png", ".jpg", ".jpeg", ".heif", "tif", ".tiff"] readonly property var acceptedDragNDropImageExtensions: [".png", ".jpg", ".jpeg", ".heif", "tif", ".tiff"]
readonly property string mentionSpanTag: `<span style="color:${Style.current.mentionColor}; background-color: ${Style.current.mentionBgColor};">` readonly property string mentionSpanTag: `<span style="color:${Style.current.mentionColor}; background-color: ${Style.current.mentionBgColor};"><a style="text-decoration:none" href='http://'>`
readonly property string ens_taken: "taken" readonly property string ens_taken: "taken"
readonly property string ens_taken_custom: "taken-custom" readonly property string ens_taken_custom: "taken-custom"