Skip to content
Snippets Groups Projects
MessageInput.qml 8.4 KiB
Newer Older
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
Nicolas Werner's avatar
Nicolas Werner committed
import im.nheko 1.0

Rectangle {
    color: colors.window
    Layout.fillWidth: true
    Layout.preferredHeight: textInput.height
    Layout.minimumHeight: 40

    RowLayout {
        id: inputBar

        anchors.fill: parent
        spacing: 16

        ImageButton {
            visible: TimelineManager.callsSupported
            Layout.alignment: Qt.AlignBottom
            hoverEnabled: true
            width: 22
            height: 22
            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 {
            Layout.alignment: Qt.AlignBottom
            hoverEnabled: true
            width: 22
            height: 22
            image: ":/icons/icons/ui/paper-clip-outline.png"
            Layout.topMargin: 8
            Layout.bottomMargin: 8
            Layout.leftMargin: TimelineManager.callsSupported ? 0 : 16
Nicolas Werner's avatar
Nicolas Werner committed
            onClicked: TimelineManager.timeline.input.openFileSelection()
            ToolTip.visible: hovered
            ToolTip.text: qsTr("Send a file")
Nicolas Werner's avatar
Nicolas Werner committed

            Rectangle {
                anchors.fill: parent
                color: colors.window
                visible: TimelineManager.timeline.input.uploading

                NhekoBusyIndicator {
                    anchors.fill: parent
                    running: parent.visible
                }

            }

        }

        ScrollView {
            id: textInput

            Layout.alignment: Qt.AlignBottom
            Layout.maximumHeight: Window.height / 4
            Layout.fillWidth: true

            TextArea {
Nicolas Werner's avatar
Nicolas Werner committed
                id: textArea

Nicolas Werner's avatar
Nicolas Werner committed
                property int completerTriggeredAt: -1

                placeholderText: qsTr("Write a message...")
                placeholderTextColor: colors.buttonText
                color: colors.text
                wrapMode: TextEdit.Wrap
Nicolas Werner's avatar
Nicolas Werner committed
                onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text)
Nicolas Werner's avatar
Nicolas Werner committed
                onCursorPositionChanged: {
                    TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text);
Nicolas Werner's avatar
Nicolas Werner committed
                    if (cursorPosition <= completerTriggeredAt) {
Nicolas Werner's avatar
Nicolas Werner committed
                        completerTriggeredAt = -1;
                        popup.close();
                    }
                }
Nicolas Werner's avatar
Nicolas Werner committed
                onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text)
                onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text)
Nicolas Werner's avatar
Nicolas Werner committed
                Keys.onShortcutOverride: event.accepted = (completerTriggeredAt != -1 && (event.key === Qt.Key_Escape || event.key === Qt.Key_Tab || event.key === Qt.Key_Enter))
Nicolas Werner's avatar
Nicolas Werner committed
                Keys.onPressed: {
                    if (event.matches(StandardKey.Paste)) {
Nicolas Werner's avatar
Nicolas Werner committed
                        TimelineManager.timeline.input.paste(false);
                        event.accepted = true;
Nicolas Werner's avatar
Nicolas Werner committed
                    } 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) {
Nicolas Werner's avatar
Nicolas Werner committed
                        completerTriggeredAt = cursorPosition;
Nicolas Werner's avatar
Nicolas Werner committed
                        popup.completerName = "user";
                        popup.open();
Nicolas Werner's avatar
Nicolas Werner committed
                    } else if (event.key == Qt.Key_Colon) {
                        completerTriggeredAt = cursorPosition;
                        popup.completerName = "emoji";
                        popup.open();
Nicolas Werner's avatar
Nicolas Werner committed
                    } else if (event.key == Qt.Key_Escape && popup.opened) {
                        completerTriggeredAt = -1;
Nicolas Werner's avatar
Nicolas Werner committed
                        popup.completerName = "";
Nicolas Werner's avatar
Nicolas Werner committed
                        event.accepted = true;
                        popup.close();
                    } else if (event.matches(StandardKey.InsertParagraphSeparator) && popup.opened) {
                        var currentCompletion = popup.currentCompletion();
Nicolas Werner's avatar
Nicolas Werner committed
                        popup.completerName = "";
Nicolas Werner's avatar
Nicolas Werner committed
                        popup.close();
                        if (currentCompletion) {
Nicolas Werner's avatar
Nicolas Werner committed
                            textArea.remove(completerTriggeredAt, cursorPosition);
Nicolas Werner's avatar
Nicolas Werner committed
                            textArea.insert(cursorPosition, currentCompletion);
                            event.accepted = true;
                            return ;
                        }
                    } else if (event.key == Qt.Key_Tab && popup.opened) {
                        event.accepted = true;
                        popup.down();
                    } 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();
Nicolas Werner's avatar
Nicolas Werner committed
                    } else if (event.matches(StandardKey.InsertParagraphSeparator)) {
                        TimelineManager.timeline.input.send();
                        textArea.clear();
                        event.accepted = true;
Nicolas Werner's avatar
Nicolas Werner committed
                    }
                    if (popup.opened)
                        popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition) + event.text);
Nicolas Werner's avatar
Nicolas Werner committed
                Connections {
                    onTimelineChanged: {
                        textArea.clear();
                        textArea.append(TimelineManager.timeline.input.text());
                        textArea.completerTriggeredAt = -1;
                        popup.completerName = "";
                    }
                    target: TimelineManager
                }
                // Ensure that we get escape key press events first.

Nicolas Werner's avatar
Nicolas Werner committed
                Completer {
                    id: popup

                    x: textArea.positionToRectangle(textArea.completerTriggeredAt).x
                    y: textArea.positionToRectangle(textArea.completerTriggeredAt).y - height
Nicolas Werner's avatar
Nicolas Werner committed
                }

                Connections {
                    onInsertText: textArea.insert(textArea.cursorPosition, text)
Nicolas Werner's avatar
Nicolas Werner committed
                    target: TimelineManager.timeline.input
                MouseArea {
                    // workaround for wrong cursor shape on some platforms
                    anchors.fill: parent
Nicolas Werner's avatar
Nicolas Werner committed
                    acceptedButtons: Qt.MiddleButton
                    cursorShape: Qt.IBeamCursor
Nicolas Werner's avatar
Nicolas Werner committed
                    onClicked: TimelineManager.timeline.input.paste(true)
                }

                background: Rectangle {
                    color: colors.window
                }

            }

        }

        ImageButton {
            id: emojiButton

            Layout.alignment: Qt.AlignRight | Qt.AlignBottom
            hoverEnabled: true
            width: 22
            height: 22
            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 {
            Layout.alignment: Qt.AlignRight | Qt.AlignBottom
            hoverEnabled: true
            width: 22
            height: 22
            image: ":/icons/icons/ui/cursor.png"
            Layout.topMargin: 8
            Layout.bottomMargin: 8
            Layout.rightMargin: 16
            ToolTip.visible: hovered
            ToolTip.text: qsTr("Send")
Nicolas Werner's avatar
Nicolas Werner committed
            onClicked: {
                TimelineManager.timeline.input.send();
                textArea.clear();
            }