From 07e71e6eaedeb8da96c307b88506195317b41a16 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 17 Jan 2021 04:05:02 +0100 Subject: [PATCH] Fix crash with ScrollView --- resources/qml/MessageInput.qml | 47 ++++++++++++++------- resources/qml/MessageView.qml | 3 +- resources/qml/TimelineView.qml | 2 + resources/qml/ui/Ripple.qml | 2 +- resources/qml/voip/CallDevices.qml | 2 +- resources/qml/voip/CallInvite.qml | 67 ++++++++++++++++++------------ 6 files changed, 78 insertions(+), 45 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 0090ea95..0e8788d5 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -8,7 +8,7 @@ import im.nheko 1.0 Rectangle { color: colors.window Layout.fillWidth: true - Layout.preferredHeight: textInput.height + Layout.preferredHeight: textInput.height + 16 Layout.minimumHeight: 40 Component { @@ -23,6 +23,7 @@ Rectangle { id: inputBar anchors.fill: parent + anchors.margins: 8 spacing: 16 ImageButton { @@ -35,9 +36,7 @@ Rectangle { image: CallManager.isOnCall ? ":/icons/icons/ui/end-call.png" : ":/icons/icons/ui/place-call.png" ToolTip.visible: hovered ToolTip.text: CallManager.isOnCall ? qsTr("Hang up") : qsTr("Place a call") - Layout.topMargin: 8 - Layout.bottomMargin: 8 - Layout.leftMargin: 16 + Layout.leftMargin: 8 onClicked: { if (TimelineManager.timeline) { if (CallManager.haveCallInvite) { @@ -59,9 +58,7 @@ Rectangle { width: 22 height: 22 image: ":/icons/icons/ui/paper-clip-outline.png" - Layout.topMargin: 8 - Layout.bottomMargin: 8 - Layout.leftMargin: CallManager.callsSupported ? 0 : 16 + Layout.leftMargin: CallManager.callsSupported ? 0 : 8 onClicked: TimelineManager.timeline.input.openFileSelection() ToolTip.visible: hovered ToolTip.text: qsTr("Send a file") @@ -80,12 +77,30 @@ Rectangle { } - ScrollView { + Flickable { id: textInput + function ensureVisible(r) { + if (contentX >= r.x) + contentX = r.x; + else if (contentX + width <= r.x + r.width) + contentX = r.x + r.width - width; + if (contentY >= r.y) + contentY = r.y; + else if (contentY + height <= r.y + r.height) + contentY = r.y + r.height - height; + } + Layout.alignment: Qt.AlignBottom Layout.maximumHeight: Window.height / 4 + Layout.minimumHeight: Settings.fontSize Layout.fillWidth: true + clip: true + boundsBehavior: Flickable.StopAtBounds + implicitWidth: textArea.width + implicitHeight: textArea.height + contentWidth: textArea.width + contentHeight: textArea.height TextArea { id: textArea @@ -104,13 +119,17 @@ Rectangle { popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition)); } + text: "asfkajsdf" selectByMouse: true placeholderText: qsTr("Write a message...") placeholderTextColor: colors.buttonText color: colors.text + width: textInput.width wrapMode: TextEdit.Wrap + padding: 0 focus: true onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onCursorRectangleChanged: textInput.ensureVisible(cursorRectangle) onCursorPositionChanged: { TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text); if (cursorPosition <= completerTriggeredAt) { @@ -189,6 +208,7 @@ Rectangle { popup.down(); } } + background: null Connections { onTimelineChanged: { @@ -230,10 +250,9 @@ Rectangle { roomid: TimelineManager.timeline.roomId() } - background: Rectangle { - color: colors.window - } + } + ScrollBar.vertical: ScrollBar { } } @@ -246,8 +265,6 @@ Rectangle { 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) { @@ -261,9 +278,7 @@ Rectangle { width: 22 height: 22 image: ":/icons/icons/ui/cursor.png" - Layout.topMargin: 8 - Layout.bottomMargin: 8 - Layout.rightMargin: 16 + Layout.rightMargin: 8 ToolTip.visible: hovered ToolTip.text: qsTr("Send") onClicked: { diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index e3222054..0858be83 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -20,9 +20,10 @@ ListView { spacing: 4 verticalLayoutDirection: ListView.BottomToTop onCountChanged: { - // Mark timeline as read + // Mark timeline as read if (atYEnd) model.currentIndex = 0; + } ScrollHelper { diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index fd08f0ca..38e3a928 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -57,6 +57,7 @@ Page { CallInvite { } + } Menu { @@ -202,6 +203,7 @@ Page { Rectangle { id: msgView + Layout.fillWidth: true Layout.fillHeight: true color: colors.base diff --git a/resources/qml/ui/Ripple.qml b/resources/qml/ui/Ripple.qml index 47cb553e..ccf93c83 100644 --- a/resources/qml/ui/Ripple.qml +++ b/resources/qml/ui/Ripple.qml @@ -1,6 +1,6 @@ +import QtGraphicalEffects 1.0 import QtQuick 2.10 import QtQuick.Controls 2.3 -import QtGraphicalEffects 1.0 Item { id: ripple diff --git a/resources/qml/voip/CallDevices.qml b/resources/qml/voip/CallDevices.qml index fd6b6005..e19a2064 100644 --- a/resources/qml/voip/CallDevices.qml +++ b/resources/qml/voip/CallDevices.qml @@ -6,12 +6,12 @@ import im.nheko 1.0 Popup { modal: true palette: colors - // only set the anchors on Qt 5.12 or higher // see https://doc.qt.io/qt-5/qml-qtquick-controls2-popup.html#anchors.centerIn-prop Component.onCompleted: { if (anchors) anchors.centerIn = parent; + } ColumnLayout { diff --git a/resources/qml/voip/CallInvite.qml b/resources/qml/voip/CallInvite.qml index 1e9a31c2..00dcc77f 100644 --- a/resources/qml/voip/CallInvite.qml +++ b/resources/qml/voip/CallInvite.qml @@ -9,23 +9,21 @@ Popup { width: parent.width height: parent.height palette: colors - background: Rectangle { - color: colors.window - border.color: colors.windowText - } Component { id: deviceError + DeviceError { } + } Connections { target: CallManager onNewInviteState: { - if (!CallManager.haveCallInvite) { + if (!CallManager.haveCallInvite) close(); - } + } } @@ -56,9 +54,10 @@ Popup { Image { property string image: CallManager.isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png" + Layout.alignment: Qt.AlignCenter Layout.preferredWidth: msgView.height / 10 - Layout.preferredHeight: msgView.height / 10 + Layout.preferredHeight: msgView.height / 10 source: "image://colorimage/" + image + "?" + colors.windowText } @@ -68,17 +67,18 @@ Popup { font.pointSize: fontMetrics.font.pointSize * 2 color: colors.windowText } + } ColumnLayout { id: deviceCombos property int imageSize: msgView.height / 20 + Layout.alignment: Qt.AlignCenter Layout.bottomMargin: msgView.height / 25 RowLayout { - Layout.alignment: Qt.AlignCenter Image { @@ -89,13 +89,14 @@ Popup { ComboBox { id: micCombo + Layout.fillWidth: true model: CallManager.mics } + } RowLayout { - visible: CallManager.isVideo && CallManager.cameras.length > 0 Layout.alignment: Qt.AlignCenter @@ -107,18 +108,19 @@ Popup { ComboBox { id: cameraCombo + Layout.fillWidth: true model: CallManager.cameras } + } + } RowLayout { id: buttonLayout property int buttonSize: msgView.height / 8 - Layout.alignment: Qt.AlignCenter - spacing: msgView.height / 6 function validateMic() { if (CallManager.mics.length == 0) { @@ -132,51 +134,64 @@ Popup { return true; } + Layout.alignment: Qt.AlignCenter + spacing: msgView.height / 6 + RoundButton { implicitWidth: buttonLayout.buttonSize implicitHeight: buttonLayout.buttonSize + onClicked: { + CallManager.hangUp(); + close(); + } background: Rectangle { radius: buttonLayout.buttonSize / 2 color: "#ff0000" } - contentItem : Image { + contentItem: Image { source: "image://colorimage/:/icons/icons/ui/end-call.png?#ffffff" } - onClicked: { - CallManager.hangUp(); - close(); - } } RoundButton { id: acceptButton property string image: CallManager.isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png" + implicitWidth: buttonLayout.buttonSize implicitHeight: buttonLayout.buttonSize + onClicked: { + if (buttonLayout.validateMic()) { + Settings.microphone = micCombo.currentText; + if (cameraCombo.visible) + Settings.camera = cameraCombo.currentText; + + CallManager.acceptInvite(); + close(); + } + } background: Rectangle { radius: buttonLayout.buttonSize / 2 color: "#00ff00" } - contentItem : Image { + contentItem: Image { source: "image://colorimage/" + acceptButton.image + "?#ffffff" } - onClicked: { - if (buttonLayout.validateMic()) { - Settings.microphone = micCombo.currentText; - if (cameraCombo.visible) - Settings.camera = cameraCombo.currentText; - CallManager.acceptInvite(); - close(); - } - } } + } + } + + background: Rectangle { + color: colors.window + border.color: colors.windowText + } + }