Move UserAutoCompletion outside of Composer

This commit is contained in:
miruka
2020-08-21 05:39:46 -04:00
parent 4ea3a7d52a
commit 6dcc244998
3 changed files with 49 additions and 46 deletions

View File

@@ -3,69 +3,63 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import "../../../Base"
import "../AutoCompletion"
Rectangle {
property UserAutoCompletion userCompletion
property alias eventList: messageArea.eventList
readonly property bool hasFocus: messageArea.activeFocus
readonly property alias messageArea: messageArea
function takeFocus() { messageArea.forceActiveFocus() }
implicitHeight: Math.max(theme.baseElementsHeight, column.implicitHeight)
implicitHeight: Math.max(theme.baseElementsHeight, row.implicitHeight)
color: theme.chat.composer.background
HColumnLayout {
id: column
HRowLayout {
id: row
anchors.fill: parent
UserAutoCompletion {
id: userCompletion
textArea: messageArea
HUserAvatar {
id: avatar
radius: 0
userId: messageArea.writingUserId
Layout.fillWidth: true
Layout.maximumHeight: chat.height / 3
mxc:
messageArea.writingUserInfo ?
messageArea.writingUserInfo.avatar_url :
""
displayName:
messageArea.writingUserInfo ?
messageArea.writingUserInfo.display_name :
""
}
HRowLayout {
HUserAvatar {
id: avatar
radius: 0
userId: messageArea.writingUserId
HScrollView {
Layout.fillHeight: true
Layout.fillWidth: true
mxc:
messageArea.writingUserInfo ?
messageArea.writingUserInfo.avatar_url :
""
MessageArea {
id: messageArea
autoCompletionOpen: userCompletion.open
usersCompleted: userCompletion.usersCompleted
displayName:
messageArea.writingUserInfo ?
messageArea.writingUserInfo.display_name :
""
onAutoCompletePrevious: userCompletion.previous()
onAutoCompleteNext: userCompletion.next()
onCancelAutoCompletion: userCompletion.cancel()
onAcceptAutoCompletion:
! userCompletion.autoOpen ||
userCompletion.autoOpenCompleted ?
userCompletion.accept() :
null
}
}
HScrollView {
Layout.fillHeight: true
Layout.fillWidth: true
MessageArea {
id: messageArea
autoCompletionOpen: userCompletion.open
usersCompleted: userCompletion.usersCompleted
onAutoCompletePrevious: userCompletion.previous()
onAutoCompleteNext: userCompletion.next()
onCancelAutoCompletion: userCompletion.cancel()
onAcceptAutoCompletion:
! userCompletion.autoOpen ||
userCompletion.autoOpenCompleted ?
userCompletion.accept() :
null
}
}
UploadButton {
Layout.fillHeight: true
}
UploadButton {
Layout.fillHeight: true
}
}
}

View File

@@ -1,159 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
import QtQuick 2.12
import QtQuick.Layouts 1.12
import "../../.."
import "../../../Base"
import "../../../Base/HTile"
HListView {
id: root
property HTextArea textArea
property bool open: false
property var originalWord: null
property bool autoOpenCompleted: false
property var usersCompleted: ({}) // {displayName: userId}
readonly property bool autoOpen: {
if (autoOpenCompleted) return true
const current = textArea.getWordBehindCursor()
return current ? /^@.+/.test(current.word) : false
}
readonly property var wordToComplete:
open ? originalWord || textArea.getWordBehindCursor() : null
readonly property string modelFilter:
autoOpen && wordToComplete ? wordToComplete.word.replace(/^@/, "") :
open && wordToComplete ? wordToComplete.word :
""
function getCurrentWordStart() {
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
return lastWordMatch.index
}
function replaceCurrentWord(withText) {
const current = textArea.getWordBehindCursor()
if (current) {
textArea.remove(current.start, current.end + 1)
textArea.insertAtCursor(withText)
}
}
function previous() {
if (open) {
decrementCurrentIndex()
return
}
open = true
const args = [model.modelId, modelFilter]
py.callCoro("set_string_filter", args, decrementCurrentIndex)
}
function next() {
if (open) {
incrementCurrentIndex()
return
}
open = true
const args = [model.modelId, modelFilter]
py.callCoro("set_string_filter", args, incrementCurrentIndex)
}
function accept() {
if (currentIndex !== -1) {
const member = model.get(currentIndex)
usersCompleted[member.display_name] = member.id
usersCompletedChanged()
}
open = false
}
function cancel() {
if (originalWord) replaceCurrentWord(originalWord.word)
currentIndex = -1
open = false
}
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 {
width: root.width
contentItem: HLabel { text: model.display_name + " (" + model.id + ")"}
onClicked: {
currentIndex = model.index
root.open = false
}
}
onAutoOpenChanged: open = autoOpen
onOpenChanged: if (! open) {
originalWord = null
currentIndex = -1
autoOpenCompleted = false
py.callCoro("set_string_filter", [model.modelId, ""])
}
onModelFilterChanged: {
if (! open) return
py.callCoro("set_string_filter", [model.modelId, modelFilter])
}
onCurrentIndexChanged: {
if (currentIndex === -1) return
if (! originalWord) originalWord = textArea.getWordBehindCursor()
if (autoOpen) autoOpenCompleted = true
replaceCurrentWord(model.get(currentIndex).display_name)
}
Behavior on opacity { HNumberAnimation {} }
Behavior on implicitHeight { HNumberAnimation {} }
Connections {
target: root.textArea
function onCursorPositionChanged() {
if (! root.open) return
const pos = root.textArea.cursorPosition
const start = root.wordToComplete.start
const end =
currentIndex === -1 ?
root.wordToComplete.end + 1 :
root.wordToComplete.start +
model.get(currentIndex).display_name.length
if (pos < start || pos > end) root.accept()
}
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()
}
}
}