2020-08-20 12:21:47 -04:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
|
|
|
|
import QtQuick 2.12
|
|
|
|
import QtQuick.Layouts 1.12
|
|
|
|
import "../../.."
|
|
|
|
import "../../../Base"
|
|
|
|
import "../../../Base/HTile"
|
|
|
|
|
2020-08-21 01:17:29 -04:00
|
|
|
// FIXME: a b -> a @p b → @p doesn't trigger completion
|
2020-08-20 12:21:47 -04:00
|
|
|
HListView {
|
2020-08-21 01:17:29 -04:00
|
|
|
id: root
|
2020-08-20 12:21:47 -04:00
|
|
|
|
|
|
|
property HTextArea textArea
|
|
|
|
property bool open: false
|
|
|
|
|
|
|
|
property string originalText: ""
|
|
|
|
property bool autoOpenCompleted: false
|
2020-08-21 01:17:29 -04:00
|
|
|
property var usersCompleted: ({}) // {displayName: userId}
|
2020-08-20 12:21:47 -04:00
|
|
|
|
|
|
|
readonly property bool autoOpen:
|
|
|
|
autoOpenCompleted || textArea.text.match(/.*(^|\W)@[^\s]+$/)
|
|
|
|
|
|
|
|
readonly property string wordToComplete:
|
|
|
|
open ?
|
|
|
|
(originalText || textArea.text).split(/\s/).slice(-1)[0].replace(
|
|
|
|
autoOpen ? /^@/ : "", "",
|
|
|
|
) :
|
|
|
|
""
|
|
|
|
|
2020-08-21 01:46:07 -04:00
|
|
|
function getLastWordStart() {
|
|
|
|
const lastWordMatch = /(?:^|\s)[^\s]+$/.exec(textArea.text)
|
|
|
|
if (! lastWordMatch) return textArea.length
|
|
|
|
|
|
|
|
if (! (lastWordMatch.index === 0 && ! textArea.text[0].match(/\s/)))
|
|
|
|
return lastWordMatch.index + 1
|
2020-08-20 12:21:47 -04:00
|
|
|
|
2020-08-21 01:46:07 -04:00
|
|
|
return lastWordMatch.index
|
|
|
|
}
|
2020-08-21 01:17:29 -04:00
|
|
|
|
2020-08-21 01:46:07 -04:00
|
|
|
function replaceLastWord(withText) {
|
|
|
|
textArea.remove(getLastWordStart(), textArea.length)
|
2020-08-20 12:21:47 -04:00
|
|
|
textArea.insertAtCursor(withText)
|
|
|
|
}
|
|
|
|
|
|
|
|
function previous() {
|
|
|
|
if (open) {
|
|
|
|
decrementCurrentIndex()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
open = true
|
|
|
|
const args = [model.modelId, wordToComplete]
|
|
|
|
py.callCoro("set_string_filter", args, decrementCurrentIndex)
|
|
|
|
}
|
|
|
|
|
|
|
|
function next() {
|
|
|
|
if (open) {
|
|
|
|
incrementCurrentIndex()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
open = true
|
|
|
|
const args = [model.modelId, wordToComplete]
|
|
|
|
py.callCoro("set_string_filter", args, incrementCurrentIndex)
|
|
|
|
}
|
|
|
|
|
2020-08-21 01:17:29 -04:00
|
|
|
function accept() {
|
|
|
|
if (currentIndex !== -1) {
|
|
|
|
const member = model.get(currentIndex)
|
|
|
|
usersCompleted[member.display_name] = member.id
|
|
|
|
usersCompletedChanged()
|
|
|
|
}
|
|
|
|
|
|
|
|
open = false
|
|
|
|
}
|
|
|
|
|
2020-08-20 12:21:47 -04:00
|
|
|
function cancel() {
|
|
|
|
if (originalText)
|
|
|
|
replaceLastWord(originalText.split(/\s/).splice(-1)[0])
|
|
|
|
|
2020-08-21 01:17:29 -04:00
|
|
|
currentIndex = -1
|
|
|
|
open = false
|
2020-08-20 12:21:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
visible: opacity > 0
|
|
|
|
opacity: open && count ? 1 : 0
|
|
|
|
implicitHeight: open && count ? Math.min(window.height, contentHeight) : 0
|
|
|
|
model: ModelStore.get(chat.userId, chat.roomId, "autocompleted_members")
|
|
|
|
|
|
|
|
delegate: HTile {
|
2020-08-21 01:17:29 -04:00
|
|
|
width: root.width
|
2020-08-20 12:21:47 -04:00
|
|
|
contentItem: HLabel { text: model.display_name + " (" + model.id + ")"}
|
|
|
|
onClicked: {
|
2020-08-21 01:17:29 -04:00
|
|
|
currentIndex = model.index
|
|
|
|
root.open = false
|
2020-08-20 12:21:47 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onCountChanged: if (! count && open) open = false
|
|
|
|
onAutoOpenChanged: open = autoOpen
|
|
|
|
onOpenChanged: if (! open) {
|
|
|
|
originalText = ""
|
|
|
|
currentIndex = -1
|
|
|
|
autoOpenCompleted = false
|
|
|
|
py.callCoro("set_string_filter", [model.modelId, ""])
|
|
|
|
}
|
|
|
|
|
|
|
|
onWordToCompleteChanged: {
|
|
|
|
if (! open) return
|
|
|
|
py.callCoro("set_string_filter", [model.modelId, wordToComplete])
|
|
|
|
}
|
|
|
|
|
|
|
|
onCurrentIndexChanged: {
|
|
|
|
if (currentIndex === -1) return
|
|
|
|
if (! originalText) originalText = textArea.text
|
|
|
|
if (autoOpen) autoOpenCompleted = true
|
|
|
|
|
|
|
|
replaceLastWord(model.get(currentIndex).display_name)
|
|
|
|
}
|
|
|
|
|
|
|
|
Behavior on opacity { HNumberAnimation {} }
|
|
|
|
Behavior on implicitHeight { HNumberAnimation {} }
|
2020-08-21 01:17:29 -04:00
|
|
|
|
|
|
|
Connections {
|
|
|
|
target: root.textArea
|
|
|
|
|
2020-08-21 01:46:07 -04:00
|
|
|
function onCursorPositionChanged() {
|
|
|
|
if (root.open && root.textArea.cursorPosition < getLastWordStart())
|
|
|
|
root.accept()
|
|
|
|
}
|
|
|
|
|
2020-08-21 01:17:29 -04:00
|
|
|
function onTextChanged() {
|
|
|
|
let changed = false
|
|
|
|
|
|
|
|
for (const displayName of Object.keys(root.usersCompleted)) {
|
|
|
|
if (! root.textArea.text.includes(displayName)) {
|
|
|
|
delete root.usersCompleted[displayName]
|
|
|
|
changed = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed) root.usersCompletedChanged()
|
|
|
|
}
|
|
|
|
}
|
2020-08-20 12:21:47 -04:00
|
|
|
}
|