summary refs log tree commit diff
path: root/resources/qml/MessageInput.qml
diff options
context:
space:
mode:
Diffstat (limited to 'resources/qml/MessageInput.qml')
-rw-r--r--resources/qml/MessageInput.qml168
1 files changed, 166 insertions, 2 deletions
diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml

index 71da9cae..ae95cbb6 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml
@@ -2,6 +2,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 +import im.nheko 1.0 Rectangle { color: colors.window @@ -16,14 +17,18 @@ Rectangle { spacing: 16 ImageButton { + visible: TimelineManager.callsSupported Layout.alignment: Qt.AlignBottom hoverEnabled: true width: 22 height: 22 - image: ":/icons/icons/ui/place-call.png" + image: TimelineManager.isOnCall ? ":/icons/icons/ui/end-call.png" : ":/icons/icons/ui/place-call.png" + ToolTip.visible: hovered + ToolTip.text: TimelineManager.isOnCall ? qsTr("Hang up") : qsTr("Place a call") Layout.topMargin: 8 Layout.bottomMargin: 8 Layout.leftMargin: 16 + onClicked: TimelineManager.timeline.input.callButton() } ImageButton { @@ -34,6 +39,23 @@ Rectangle { image: ":/icons/icons/ui/paper-clip-outline.png" Layout.topMargin: 8 Layout.bottomMargin: 8 + Layout.leftMargin: TimelineManager.callsSupported ? 0 : 16 + onClicked: TimelineManager.timeline.input.openFileSelection() + ToolTip.visible: hovered + ToolTip.text: qsTr("Send a file") + + Rectangle { + anchors.fill: parent + color: colors.window + visible: TimelineManager.timeline.input.uploading + + NhekoBusyIndicator { + anchors.fill: parent + running: parent.visible + } + + } + } ScrollView { @@ -44,16 +66,145 @@ Rectangle { Layout.fillWidth: true TextArea { + id: textArea + + property int completerTriggeredAt: -1 + + function insertCompletion(completion) { + textArea.remove(completerTriggeredAt, cursorPosition); + textArea.insert(cursorPosition, completion); + } + + function openCompleter(pos, type) { + completerTriggeredAt = pos; + popup.completerName = type; + popup.open(); + popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition)); + } + placeholderText: qsTr("Write a message...") placeholderTextColor: colors.buttonText color: colors.text wrapMode: TextEdit.Wrap + focus: true + onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onCursorPositionChanged: { + TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text); + if (cursorPosition <= completerTriggeredAt) { + completerTriggeredAt = -1; + popup.close(); + } + if (popup.opened) + popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition)); + + } + onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + // Ensure that we get escape key press events first. + Keys.onShortcutOverride: event.accepted = (completerTriggeredAt != -1 && (event.key === Qt.Key_Escape || event.key === Qt.Key_Tab || event.key === Qt.Key_Enter)) + Keys.onPressed: { + if (event.matches(StandardKey.Paste)) { + TimelineManager.timeline.input.paste(false); + event.accepted = true; + } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_U) { + textArea.clear(); + } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_P) { + textArea.text = TimelineManager.timeline.input.previousText(); + } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) { + textArea.text = TimelineManager.timeline.input.nextText(); + } else if (event.key == Qt.Key_At) { + textArea.openCompleter(cursorPosition, "user"); + popup.open(); + } else if (event.key == Qt.Key_Colon) { + textArea.openCompleter(cursorPosition, "emoji"); + popup.open(); + } else if (event.key == Qt.Key_Escape && popup.opened) { + completerTriggeredAt = -1; + popup.completerName = ""; + event.accepted = true; + popup.close(); + } else if (event.matches(StandardKey.InsertParagraphSeparator)) { + if (popup.opened) { + var currentCompletion = popup.currentCompletion(); + popup.completerName = ""; + popup.close(); + if (currentCompletion) { + textArea.insertCompletion(currentCompletion); + event.accepted = true; + return ; + } + } + TimelineManager.timeline.input.send(); + textArea.clear(); + event.accepted = true; + } else if (event.key == Qt.Key_Tab) { + event.accepted = true; + if (popup.opened) { + popup.up(); + } else { + var pos = cursorPosition - 1; + while (pos > -1) { + var t = textArea.getText(pos, pos + 1); + console.log('"' + t + '"'); + if (t == '@' || t == ' ' || t == '\t') { + textArea.openCompleter(pos, "user"); + return ; + } else if (t == ':') { + textArea.openCompleter(pos, "emoji"); + return ; + } + pos = pos - 1; + } + // At start of input + textArea.openCompleter(0, "user"); + } + } else if (event.key == Qt.Key_Up && popup.opened) { + event.accepted = true; + popup.up(); + } else if (event.key == Qt.Key_Down && popup.opened) { + event.accepted = true; + popup.down(); + } + } + + Connections { + onTimelineChanged: { + textArea.clear(); + textArea.append(TimelineManager.timeline.input.text()); + textArea.completerTriggeredAt = -1; + popup.completerName = ""; + } + target: TimelineManager + } + + Connections { + onCompletionClicked: textArea.insertCompletion(completion) + target: popup + } + + Completer { + id: popup + + x: textArea.positionToRectangle(textArea.completerTriggeredAt).x + y: textArea.positionToRectangle(textArea.completerTriggeredAt).y - height + } + + Connections { + onInsertText: textArea.insert(textArea.cursorPosition, text) + target: TimelineManager.timeline.input + } MouseArea { // workaround for wrong cursor shape on some platforms anchors.fill: parent - acceptedButtons: Qt.NoButton + acceptedButtons: Qt.MiddleButton cursorShape: Qt.IBeamCursor + onClicked: TimelineManager.timeline.input.paste(true) + } + + NhekoDropArea { + anchors.fill: parent + roomid: TimelineManager.timeline.roomId() } background: Rectangle { @@ -65,6 +216,8 @@ Rectangle { } ImageButton { + id: emojiButton + Layout.alignment: Qt.AlignRight | Qt.AlignBottom hoverEnabled: true width: 22 @@ -72,6 +225,11 @@ Rectangle { image: ":/icons/icons/ui/smile.png" Layout.topMargin: 8 Layout.bottomMargin: 8 + ToolTip.visible: hovered + ToolTip.text: qsTr("Emoji") + onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(emojiButton, function(emoji) { + textArea.insert(textArea.cursorPosition, emoji); + }) } ImageButton { @@ -83,6 +241,12 @@ Rectangle { Layout.topMargin: 8 Layout.bottomMargin: 8 Layout.rightMargin: 16 + ToolTip.visible: hovered + ToolTip.text: qsTr("Send") + onClicked: { + TimelineManager.timeline.input.send(); + textArea.clear(); + } } }