Fix crash with ScrollView

This commit is contained in:
Nicolas Werner 2021-01-17 04:05:02 +01:00
parent 551515860e
commit 07e71e6eae
6 changed files with 78 additions and 45 deletions

View file

@ -8,7 +8,7 @@ import im.nheko 1.0
Rectangle { Rectangle {
color: colors.window color: colors.window
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: textInput.height Layout.preferredHeight: textInput.height + 16
Layout.minimumHeight: 40 Layout.minimumHeight: 40
Component { Component {
@ -23,6 +23,7 @@ Rectangle {
id: inputBar id: inputBar
anchors.fill: parent anchors.fill: parent
anchors.margins: 8
spacing: 16 spacing: 16
ImageButton { ImageButton {
@ -35,9 +36,7 @@ Rectangle {
image: CallManager.isOnCall ? ":/icons/icons/ui/end-call.png" : ":/icons/icons/ui/place-call.png" image: CallManager.isOnCall ? ":/icons/icons/ui/end-call.png" : ":/icons/icons/ui/place-call.png"
ToolTip.visible: hovered ToolTip.visible: hovered
ToolTip.text: CallManager.isOnCall ? qsTr("Hang up") : qsTr("Place a call") ToolTip.text: CallManager.isOnCall ? qsTr("Hang up") : qsTr("Place a call")
Layout.topMargin: 8 Layout.leftMargin: 8
Layout.bottomMargin: 8
Layout.leftMargin: 16
onClicked: { onClicked: {
if (TimelineManager.timeline) { if (TimelineManager.timeline) {
if (CallManager.haveCallInvite) { if (CallManager.haveCallInvite) {
@ -59,9 +58,7 @@ Rectangle {
width: 22 width: 22
height: 22 height: 22
image: ":/icons/icons/ui/paper-clip-outline.png" image: ":/icons/icons/ui/paper-clip-outline.png"
Layout.topMargin: 8 Layout.leftMargin: CallManager.callsSupported ? 0 : 8
Layout.bottomMargin: 8
Layout.leftMargin: CallManager.callsSupported ? 0 : 16
onClicked: TimelineManager.timeline.input.openFileSelection() onClicked: TimelineManager.timeline.input.openFileSelection()
ToolTip.visible: hovered ToolTip.visible: hovered
ToolTip.text: qsTr("Send a file") ToolTip.text: qsTr("Send a file")
@ -80,12 +77,30 @@ Rectangle {
} }
ScrollView { Flickable {
id: textInput 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.alignment: Qt.AlignBottom
Layout.maximumHeight: Window.height / 4 Layout.maximumHeight: Window.height / 4
Layout.minimumHeight: Settings.fontSize
Layout.fillWidth: true Layout.fillWidth: true
clip: true
boundsBehavior: Flickable.StopAtBounds
implicitWidth: textArea.width
implicitHeight: textArea.height
contentWidth: textArea.width
contentHeight: textArea.height
TextArea { TextArea {
id: textArea id: textArea
@ -104,13 +119,17 @@ Rectangle {
popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition)); popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition));
} }
text: "asfkajsdf"
selectByMouse: true selectByMouse: true
placeholderText: qsTr("Write a message...") placeholderText: qsTr("Write a message...")
placeholderTextColor: colors.buttonText placeholderTextColor: colors.buttonText
color: colors.text color: colors.text
width: textInput.width
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
padding: 0
focus: true focus: true
onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text)
onCursorRectangleChanged: textInput.ensureVisible(cursorRectangle)
onCursorPositionChanged: { onCursorPositionChanged: {
TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text); TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text);
if (cursorPosition <= completerTriggeredAt) { if (cursorPosition <= completerTriggeredAt) {
@ -189,6 +208,7 @@ Rectangle {
popup.down(); popup.down();
} }
} }
background: null
Connections { Connections {
onTimelineChanged: { onTimelineChanged: {
@ -230,10 +250,9 @@ Rectangle {
roomid: TimelineManager.timeline.roomId() roomid: TimelineManager.timeline.roomId()
} }
background: Rectangle { }
color: colors.window
}
ScrollBar.vertical: ScrollBar {
} }
} }
@ -246,8 +265,6 @@ Rectangle {
width: 22 width: 22
height: 22 height: 22
image: ":/icons/icons/ui/smile.png" image: ":/icons/icons/ui/smile.png"
Layout.topMargin: 8
Layout.bottomMargin: 8
ToolTip.visible: hovered ToolTip.visible: hovered
ToolTip.text: qsTr("Emoji") ToolTip.text: qsTr("Emoji")
onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(emojiButton, function(emoji) { onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(emojiButton, function(emoji) {
@ -261,9 +278,7 @@ Rectangle {
width: 22 width: 22
height: 22 height: 22
image: ":/icons/icons/ui/cursor.png" image: ":/icons/icons/ui/cursor.png"
Layout.topMargin: 8 Layout.rightMargin: 8
Layout.bottomMargin: 8
Layout.rightMargin: 16
ToolTip.visible: hovered ToolTip.visible: hovered
ToolTip.text: qsTr("Send") ToolTip.text: qsTr("Send")
onClicked: { onClicked: {

View file

@ -20,9 +20,10 @@ ListView {
spacing: 4 spacing: 4
verticalLayoutDirection: ListView.BottomToTop verticalLayoutDirection: ListView.BottomToTop
onCountChanged: { onCountChanged: {
// Mark timeline as read // Mark timeline as read
if (atYEnd) if (atYEnd)
model.currentIndex = 0; model.currentIndex = 0;
} }
ScrollHelper { ScrollHelper {

View file

@ -57,6 +57,7 @@ Page {
CallInvite { CallInvite {
} }
} }
Menu { Menu {
@ -202,6 +203,7 @@ Page {
Rectangle { Rectangle {
id: msgView id: msgView
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
color: colors.base color: colors.base

View file

@ -1,6 +1,6 @@
import QtGraphicalEffects 1.0
import QtQuick 2.10 import QtQuick 2.10
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
import QtGraphicalEffects 1.0
Item { Item {
id: ripple id: ripple

View file

@ -6,12 +6,12 @@ import im.nheko 1.0
Popup { Popup {
modal: true modal: true
palette: colors palette: colors
// only set the anchors on Qt 5.12 or higher // 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 // see https://doc.qt.io/qt-5/qml-qtquick-controls2-popup.html#anchors.centerIn-prop
Component.onCompleted: { Component.onCompleted: {
if (anchors) if (anchors)
anchors.centerIn = parent; anchors.centerIn = parent;
} }
ColumnLayout { ColumnLayout {

View file

@ -9,23 +9,21 @@ Popup {
width: parent.width width: parent.width
height: parent.height height: parent.height
palette: colors palette: colors
background: Rectangle {
color: colors.window
border.color: colors.windowText
}
Component { Component {
id: deviceError id: deviceError
DeviceError { DeviceError {
} }
} }
Connections { Connections {
target: CallManager target: CallManager
onNewInviteState: { onNewInviteState: {
if (!CallManager.haveCallInvite) { if (!CallManager.haveCallInvite)
close(); close();
}
} }
} }
@ -56,9 +54,10 @@ Popup {
Image { Image {
property string image: CallManager.isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png" property string image: CallManager.isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png"
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: msgView.height / 10 Layout.preferredWidth: msgView.height / 10
Layout.preferredHeight: msgView.height / 10 Layout.preferredHeight: msgView.height / 10
source: "image://colorimage/" + image + "?" + colors.windowText source: "image://colorimage/" + image + "?" + colors.windowText
} }
@ -68,17 +67,18 @@ Popup {
font.pointSize: fontMetrics.font.pointSize * 2 font.pointSize: fontMetrics.font.pointSize * 2
color: colors.windowText color: colors.windowText
} }
} }
ColumnLayout { ColumnLayout {
id: deviceCombos id: deviceCombos
property int imageSize: msgView.height / 20 property int imageSize: msgView.height / 20
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.bottomMargin: msgView.height / 25 Layout.bottomMargin: msgView.height / 25
RowLayout { RowLayout {
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Image { Image {
@ -89,13 +89,14 @@ Popup {
ComboBox { ComboBox {
id: micCombo id: micCombo
Layout.fillWidth: true Layout.fillWidth: true
model: CallManager.mics model: CallManager.mics
} }
} }
RowLayout { RowLayout {
visible: CallManager.isVideo && CallManager.cameras.length > 0 visible: CallManager.isVideo && CallManager.cameras.length > 0
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
@ -107,18 +108,19 @@ Popup {
ComboBox { ComboBox {
id: cameraCombo id: cameraCombo
Layout.fillWidth: true Layout.fillWidth: true
model: CallManager.cameras model: CallManager.cameras
} }
} }
} }
RowLayout { RowLayout {
id: buttonLayout id: buttonLayout
property int buttonSize: msgView.height / 8 property int buttonSize: msgView.height / 8
Layout.alignment: Qt.AlignCenter
spacing: msgView.height / 6
function validateMic() { function validateMic() {
if (CallManager.mics.length == 0) { if (CallManager.mics.length == 0) {
@ -132,51 +134,64 @@ Popup {
return true; return true;
} }
Layout.alignment: Qt.AlignCenter
spacing: msgView.height / 6
RoundButton { RoundButton {
implicitWidth: buttonLayout.buttonSize implicitWidth: buttonLayout.buttonSize
implicitHeight: buttonLayout.buttonSize implicitHeight: buttonLayout.buttonSize
onClicked: {
CallManager.hangUp();
close();
}
background: Rectangle { background: Rectangle {
radius: buttonLayout.buttonSize / 2 radius: buttonLayout.buttonSize / 2
color: "#ff0000" color: "#ff0000"
} }
contentItem : Image { contentItem: Image {
source: "image://colorimage/:/icons/icons/ui/end-call.png?#ffffff" source: "image://colorimage/:/icons/icons/ui/end-call.png?#ffffff"
} }
onClicked: {
CallManager.hangUp();
close();
}
} }
RoundButton { RoundButton {
id: acceptButton id: acceptButton
property string image: CallManager.isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png" property string image: CallManager.isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png"
implicitWidth: buttonLayout.buttonSize implicitWidth: buttonLayout.buttonSize
implicitHeight: 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 { background: Rectangle {
radius: buttonLayout.buttonSize / 2 radius: buttonLayout.buttonSize / 2
color: "#00ff00" color: "#00ff00"
} }
contentItem : Image { contentItem: Image {
source: "image://colorimage/" + acceptButton.image + "?#ffffff" 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
}
} }