summary refs log tree commit diff
path: root/resources/qml
diff options
context:
space:
mode:
Diffstat (limited to 'resources/qml')
-rw-r--r--resources/qml/Avatar.qml5
-rw-r--r--resources/qml/EncryptionIndicator.qml9
-rw-r--r--resources/qml/ImageButton.qml4
-rw-r--r--resources/qml/MatrixText.qml8
-rw-r--r--resources/qml/MessageInput.qml20
-rw-r--r--resources/qml/MessageView.qml320
-rw-r--r--resources/qml/ReplyPopup.qml21
-rw-r--r--resources/qml/TimelineRow.qml60
-rw-r--r--resources/qml/TimelineView.qml11
-rw-r--r--resources/qml/UserProfile.qml13
-rw-r--r--resources/qml/delegates/FileMessage.qml12
-rw-r--r--resources/qml/delegates/ImageMessage.qml16
-rw-r--r--resources/qml/delegates/NoticeMessage.qml2
-rw-r--r--resources/qml/delegates/PlayableMediaMessage.qml11
-rw-r--r--resources/qml/delegates/Reply.qml16
-rw-r--r--resources/qml/delegates/TextMessage.qml3
-rw-r--r--resources/qml/emoji/EmojiButton.qml1
17 files changed, 317 insertions, 215 deletions
diff --git a/resources/qml/Avatar.qml b/resources/qml/Avatar.qml

index a459fe5a..f01911bb 100644 --- a/resources/qml/Avatar.qml +++ b/resources/qml/Avatar.qml
@@ -90,4 +90,9 @@ Rectangle { } } + CursorShape { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + } + } diff --git a/resources/qml/EncryptionIndicator.qml b/resources/qml/EncryptionIndicator.qml
index 46ca62c5..00efe9e4 100644 --- a/resources/qml/EncryptionIndicator.qml +++ b/resources/qml/EncryptionIndicator.qml
@@ -1,4 +1,4 @@ -import QtQuick 2.5 +import QtQuick 2.12 import QtQuick.Controls 2.1 import im.nheko 1.0 @@ -24,14 +24,11 @@ Rectangle { color: "transparent" width: 16 height: 16 - ToolTip.visible: ma.containsMouse && indicator.visible + ToolTip.visible: ma.hovered && indicator.visible ToolTip.text: getEncryptionTooltip() - MouseArea { + HoverHandler { id: ma - - anchors.fill: parent - hoverEnabled: true } Image { diff --git a/resources/qml/ImageButton.qml b/resources/qml/ImageButton.qml
index 9c0faef3..159c750f 100644 --- a/resources/qml/ImageButton.qml +++ b/resources/qml/ImageButton.qml
@@ -1,6 +1,7 @@ import "./ui" import QtQuick 2.3 import QtQuick.Controls 2.3 +import im.nheko 1.0 // for cursor shape AbstractButton { id: button @@ -23,11 +24,10 @@ AbstractButton { source: image != "" ? ("image://colorimage/" + image + "?" + ((button.hovered && changeColorOnHover) ? highlightColor : buttonTextColor)) : "" } - MouseArea { + CursorShape { id: mouseArea anchors.fill: parent - onPressed: mouse.accepted = false cursorShape: Qt.PointingHandCursor } diff --git a/resources/qml/MatrixText.qml b/resources/qml/MatrixText.qml
index bb3b4296..4ea15518 100644 --- a/resources/qml/MatrixText.qml +++ b/resources/qml/MatrixText.qml
@@ -8,6 +8,7 @@ TextEdit { focus: false wrapMode: Text.Wrap selectByMouse: !Settings.mobileMode + enabled: selectByMouse color: colors.text onLinkActivated: { if (/^https:\/\/matrix.to\/#\/(@.*)$/.test(link)) { @@ -25,12 +26,9 @@ TextEdit { ToolTip.visible: hoveredLink ToolTip.text: hoveredLink - MouseArea { - id: ma - + CursorShape { anchors.fill: parent - acceptedButtons: Qt.NoButton - cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + cursorShape: hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor } } diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index 5d335872..b5c96660 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml
@@ -139,6 +139,7 @@ Rectangle { if (TimelineManager.timeline) TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text); + forceActiveFocus(); } onCursorRectangleChanged: textInput.ensureVisible(cursorRectangle) onCursorPositionChanged: { @@ -163,6 +164,10 @@ Rectangle { TimelineManager.timeline.input.paste(false); event.accepted = true; } else if (event.key == Qt.Key_Space) { + // close popup if user enters space after colon + if (cursorPosition == completerTriggeredAt + 1) + popup.close(); + if (popup.opened && popup.count <= 0) popup.close(); @@ -256,16 +261,28 @@ Rectangle { Connections { ignoreUnknownSignals: true - onInsertText: messageInput.insert(messageInput.cursorPosition, text) + onInsertText: { + messageInput.insert(messageInput.cursorPosition, text); + } + onTextChanged: { + messageInput.text = newText; + messageInput.cursorPosition = newText.length; + } target: TimelineManager.timeline ? TimelineManager.timeline.input : null } Connections { ignoreUnknownSignals: true onReplyChanged: messageInput.forceActiveFocus() + onEditChanged: messageInput.forceActiveFocus() target: TimelineManager.timeline } + Connections { + target: TimelineManager + onFocusInput: messageInput.forceActiveFocus() + } + MouseArea { // workaround for wrong cursor shape on some platforms anchors.fill: parent @@ -293,6 +310,7 @@ Rectangle { ToolTip.text: qsTr("Emoji") onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(emojiButton, function(emoji) { messageInput.insert(messageInput.cursorPosition, emoji); + TimelineManager.focusMessageInput(); }) } diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index 29115b00..e1641a36 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml
@@ -1,200 +1,230 @@ import "./delegates" import QtGraphicalEffects 1.0 -import QtQuick 2.9 +import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 import im.nheko 1.0 -ListView { - id: chat +ScrollView { + contentWidth: availableWidth + clip: false + palette: colors + padding: 8 - property int delegateMaxWidth: (Settings.timelineMaxWidth > 100 && (parent.width - Settings.timelineMaxWidth) > scrollbar.width * 2) ? Settings.timelineMaxWidth : (parent.width - scrollbar.width * 2 - 8) + ListView { + id: chat - Layout.fillWidth: true - Layout.fillHeight: true - cacheBuffer: 400 - model: TimelineManager.timeline - boundsBehavior: Flickable.StopAtBounds - pixelAligned: true - spacing: 4 - verticalLayoutDirection: ListView.BottomToTop - onCountChanged: { - // Mark timeline as read - if (atYEnd) - model.currentIndex = 0; + property int delegateMaxWidth: ((Settings.timelineMaxWidth > 100 && Settings.timelineMaxWidth < parent.availableWidth) ? Settings.timelineMaxWidth : parent.availableWidth) - parent.padding - } + model: TimelineManager.timeline + boundsBehavior: Flickable.StopAtBounds + pixelAligned: true + spacing: 4 + verticalLayoutDirection: ListView.BottomToTop + onCountChanged: { + // Mark timeline as read + if (atYEnd) + model.currentIndex = 0; - ScrollHelper { - flickable: parent - anchors.fill: parent - enabled: !Settings.mobileMode - } + } - Shortcut { - sequence: StandardKey.MoveToPreviousPage - onActivated: { - chat.contentY = chat.contentY - chat.height / 2; - chat.returnToBounds(); + ScrollHelper { + flickable: parent + anchors.fill: parent + enabled: !Settings.mobileMode } - } - Shortcut { - sequence: StandardKey.MoveToNextPage - onActivated: { - chat.contentY = chat.contentY + chat.height / 2; - chat.returnToBounds(); + Shortcut { + sequence: StandardKey.MoveToPreviousPage + onActivated: { + chat.contentY = chat.contentY - chat.height / 2; + chat.returnToBounds(); + } } - } - Shortcut { - sequence: StandardKey.Cancel - onActivated: chat.model.reply = undefined - } + Shortcut { + sequence: StandardKey.MoveToNextPage + onActivated: { + chat.contentY = chat.contentY + chat.height / 2; + chat.returnToBounds(); + } + } - Shortcut { - sequence: "Alt+Up" - onActivated: chat.model.reply = chat.model.indexToId(chat.model.reply ? chat.model.idToIndex(chat.model.reply) + 1 : 0) - } + Shortcut { + sequence: StandardKey.Cancel + onActivated: { + if (chat.model.reply) + chat.model.reply = undefined; + else + chat.model.edit = undefined; + } + } - Shortcut { - sequence: "Alt+Down" - onActivated: { - var idx = chat.model.reply ? chat.model.idToIndex(chat.model.reply) - 1 : -1; - chat.model.reply = idx >= 0 ? chat.model.indexToId(idx) : undefined; + Shortcut { + sequence: "Alt+Up" + onActivated: chat.model.reply = chat.model.indexToId(chat.model.reply ? chat.model.idToIndex(chat.model.reply) + 1 : 0) } - } - Component { - id: sectionHeader - - Column { - topPadding: 4 - bottomPadding: 4 - spacing: 8 - visible: modelData && (modelData.previousMessageUserId !== modelData.userId || modelData.previousMessageDay !== modelData.day) - width: parentWidth - height: ((modelData && modelData.previousMessageDay !== modelData.day) ? dateBubble.height + 8 + userName.height : userName.height) + 8 - - Label { - id: dateBubble - - anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined - visible: modelData && modelData.previousMessageDay !== modelData.day - text: modelData ? chat.model.formatDateSeparator(modelData.timestamp) : "" - color: colors.text - height: Math.round(fontMetrics.height * 1.4) - width: contentWidth * 1.2 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - background: Rectangle { - radius: parent.height / 2 - color: colors.window - } + Shortcut { + sequence: "Alt+Down" + onActivated: { + var idx = chat.model.reply ? chat.model.idToIndex(chat.model.reply) - 1 : -1; + chat.model.reply = idx >= 0 ? chat.model.indexToId(idx) : undefined; + } + } + Shortcut { + sequence: "Ctrl+E" + onActivated: { + chat.model.edit = chat.model.reply; } + } - Row { - height: userName.height - spacing: 8 + Connections { + target: TimelineManager + onFocusChanged: readTimer.running = TimelineManager.isWindowFocused + } - Avatar { - id: messageUserAvatar - width: avatarSize - height: avatarSize - url: modelData ? chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/") : "" - displayName: modelData ? modelData.userName : "" - userid: modelData ? modelData.userId : "" - onClicked: chat.model.openUserProfile(modelData.userId) - } + Timer { + id: readTimer - Connections { - target: chat.model - onRoomAvatarUrlChanged: { - messageUserAvatar.url = modelData ? chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/") : "" + // force current read index to update + onTriggered: chat.model.setCurrentIndex(chat.model.currentIndex) + interval: 1000 + } + + Component { + id: sectionHeader + + Column { + topPadding: 4 + bottomPadding: 4 + spacing: 8 + visible: modelData && (modelData.previousMessageUserId !== modelData.userId || modelData.previousMessageDay !== modelData.day) + width: parentWidth + height: ((modelData && modelData.previousMessageDay !== modelData.day) ? dateBubble.height + 8 + userName.height : userName.height) + 8 + + Label { + id: dateBubble + + anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined + visible: modelData && modelData.previousMessageDay !== modelData.day + text: modelData ? chat.model.formatDateSeparator(modelData.timestamp) : "" + color: colors.text + height: Math.round(fontMetrics.height * 1.4) + width: contentWidth * 1.2 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + background: Rectangle { + radius: parent.height / 2 + color: colors.window } + } - Label { - id: userName + Row { + height: userName.height + spacing: 8 - text: modelData ? TimelineManager.escapeEmoji(modelData.userName) : "" - color: TimelineManager.userColor(modelData ? modelData.userId : "", colors.window) - textFormat: Text.RichText + Avatar { + id: messageUserAvatar - MouseArea { - anchors.fill: parent - Layout.alignment: Qt.AlignHCenter + width: avatarSize + height: avatarSize + url: modelData ? chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/") : "" + displayName: modelData ? modelData.userName : "" + userid: modelData ? modelData.userId : "" onClicked: chat.model.openUserProfile(modelData.userId) - cursorShape: Qt.PointingHandCursor - propagateComposedEvents: true } - } + Connections { + target: chat.model + onRoomAvatarUrlChanged: { + messageUserAvatar.url = modelData ? chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/") : ""; + } + } - Label { - color: colors.buttonText - text: modelData ? TimelineManager.userStatus(modelData.userId) : "" - textFormat: Text.PlainText - elide: Text.ElideRight - width: chat.delegateMaxWidth - parent.spacing * 2 - userName.implicitWidth - avatarSize - font.italic: true - } + Label { + id: userName - } + text: modelData ? TimelineManager.escapeEmoji(modelData.userName) : "" + color: TimelineManager.userColor(modelData ? modelData.userId : "", colors.window) + textFormat: Text.RichText - } + TapHandler { + //cursorShape: Qt.PointingHandCursor - } + onSingleTapped: chat.model.openUserProfile(modelData.userId) + } - ScrollBar.vertical: ScrollBar { - id: scrollbar - } + CursorShape { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + } - delegate: Item { - id: wrapper + } - anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined - width: chat.delegateMaxWidth - height: section ? section.height + timelinerow.height : timelinerow.height + Label { + color: colors.buttonText + text: modelData ? TimelineManager.userStatus(modelData.userId) : "" + textFormat: Text.PlainText + elide: Text.ElideRight + width: chat.delegateMaxWidth - parent.spacing * 2 - userName.implicitWidth - avatarSize + font.italic: true + } - Loader { - id: section + } - property var modelData: model - property int parentWidth: parent.width + } - active: model.previousMessageUserId !== undefined && model.previousMessageUserId !== model.userId || model.previousMessageDay !== model.day - //asynchronous: true - sourceComponent: sectionHeader - visible: status == Loader.Ready } - TimelineRow { - id: timelinerow + delegate: Item { + id: wrapper - y: section.active && section.visible ? section.y + section.height : 0 - } + anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined + width: chat.delegateMaxWidth + height: section ? section.height + timelinerow.height : timelinerow.height - Connections { - target: chat - onMovementEnded: { - if (y + height + 2 * chat.spacing > chat.contentY + chat.height && y < chat.contentY + chat.height) - chat.model.currentIndex = index; + Loader { + id: section + property var modelData: model + property int parentWidth: parent.width + + active: model.previousMessageUserId !== undefined && model.previousMessageUserId !== model.userId || model.previousMessageDay !== model.day + //asynchronous: true + sourceComponent: sectionHeader + visible: status == Loader.Ready } + + TimelineRow { + id: timelinerow + + y: section.active && section.visible ? section.y + section.height : 0 + } + + Connections { + target: chat + onMovementEnded: { + if (y + height + 2 * chat.spacing > chat.contentY + chat.height && y < chat.contentY + chat.height) + chat.model.currentIndex = index; + + } + } + } - } + footer: BusyIndicator { + anchors.horizontalCenter: parent.horizontalCenter + running: chat.model && chat.model.paginationInProgress + height: 50 + width: 50 + z: 3 + } - footer: BusyIndicator { - anchors.horizontalCenter: parent.horizontalCenter - running: chat.model && chat.model.paginationInProgress - height: 50 - width: 50 - z: 3 } } diff --git a/resources/qml/ReplyPopup.qml b/resources/qml/ReplyPopup.qml
index 4659e075..c07c2c44 100644 --- a/resources/qml/ReplyPopup.qml +++ b/resources/qml/ReplyPopup.qml
@@ -10,15 +10,16 @@ Rectangle { property var room: TimelineManager.timeline Layout.fillWidth: true - visible: room && room.reply + visible: room && (room.reply || room.edit) // Height of child, plus margins, plus border - implicitHeight: replyPreview.height + 10 + implicitHeight: (room && room.reply ? replyPreview.height : closeEditButton.height) + 10 color: colors.window z: 3 Reply { id: replyPreview + visible: room && room.reply anchors.left: parent.left anchors.leftMargin: 2 * 22 + 3 * 16 anchors.right: closeReplyButton.left @@ -32,8 +33,9 @@ Rectangle { ImageButton { id: closeReplyButton + visible: room && room.reply anchors.right: parent.right - anchors.rightMargin: 15 + anchors.rightMargin: 16 anchors.top: replyPreview.top hoverEnabled: true width: 16 @@ -44,4 +46,17 @@ Rectangle { onClicked: room.reply = undefined } + Button { + id: closeEditButton + + visible: room && room.edit + anchors.left: parent.left + anchors.rightMargin: 16 + anchors.topMargin: 10 + anchors.top: parent.top + //height: 16 + text: qsTr("Cancel edit") + onClicked: room.edit = undefined + } + } diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml
index 95a025cf..b731d29d 100644 --- a/resources/qml/TimelineRow.qml +++ b/resources/qml/TimelineRow.qml
@@ -1,6 +1,6 @@ import "./delegates" import "./emoji" -import QtQuick 2.6 +import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 @@ -12,27 +12,24 @@ Item { height: row.height Rectangle { - color: (Settings.messageHoverHighlight && hoverHandler.containsMouse) ? colors.alternateBase : "transparent" + color: (Settings.messageHoverHighlight && hoverHandler.hovered) ? colors.alternateBase : "transparent" anchors.fill: row } - MouseArea { + HoverHandler { id: hoverHandler - anchors.fill: parent - propagateComposedEvents: true - preventStealing: false - hoverEnabled: true - acceptedButtons: Qt.AllButtons - onClicked: { - if (mouse.button === Qt.RightButton) - messageContextMenu.show(model.id, model.type, model.isEncrypted, row); - else - mouse.accepted = false; - } - onPressAndHold: { - messageContextMenu.show(model.id, model.type, model.isEncrypted, row, mapToItem(timelineRoot, mouse.x, mouse.y)); - } + acceptedDevices: PointerDevice.GenericPointer + } + + TapHandler { + acceptedButtons: Qt.RightButton + onSingleTapped: messageContextMenu.show(model.id, model.type, model.isEncrypted, model.isEditable, row, mapToItem(timelineRoot, eventPoint.position.x, eventPoint.position.y)) + } + + TapHandler { + onLongPressed: messageContextMenu.show(model.id, model.type, model.isEncrypted, model.isEditable, row, mapToItem(timelineRoot, point.position.x, point.position.y)) + onDoubleTapped: chat.model.reply = model.id } RowLayout { @@ -85,6 +82,25 @@ Item { width: 16 } + ImageButton { + id: editButton + + visible: (Settings.buttonsInTimeline && model.isEditable) || model.isEdited + buttonTextColor: chat.model.edit == model.id ? colors.highlight : colors.buttonText + Layout.alignment: Qt.AlignRight | Qt.AlignTop + Layout.preferredHeight: 16 + width: 16 + hoverEnabled: true + image: ":/icons/icons/ui/edit.png" + ToolTip.visible: hovered + ToolTip.text: model.isEditable ? qsTr("Edit") : qsTr("Edited") + onClicked: { + if (model.isEditable) + chat.model.editAction(model.id); + + } + } + EmojiButton { id: reactButton @@ -124,7 +140,7 @@ Item { image: ":/icons/icons/ui/vertical-ellipsis.png" ToolTip.visible: hovered ToolTip.text: qsTr("Options") - onClicked: messageContextMenu.show(model.id, model.type, model.isEncrypted, optionsButton) + onClicked: messageContextMenu.show(model.id, model.type, model.isEncrypted, model.isEditable, optionsButton) } Label { @@ -132,15 +148,11 @@ Item { text: model.timestamp.toLocaleTimeString("HH:mm") width: Math.max(implicitWidth, text.length * fontMetrics.maximumCharacterWidth) color: inactiveColors.text - ToolTip.visible: ma.containsMouse + ToolTip.visible: ma.hovered ToolTip.text: Qt.formatDateTime(model.timestamp, Qt.DefaultLocaleLongDate) - MouseArea { + HoverHandler { id: ma - - anchors.fill: parent - hoverEnabled: true - propagateComposedEvents: true } } diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index 7a33f25f..7db9d041 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml
@@ -74,11 +74,13 @@ Page { property string eventId property int eventType property bool isEncrypted + property bool isEditable - function show(eventId_, eventType_, isEncrypted_, showAt_, position) { + function show(eventId_, eventType_, isEncrypted_, isEditable_, showAt_, position) { eventId = eventId_; eventType = eventType_; isEncrypted = isEncrypted_; + isEditable = isEditable_; if (position) popup(position, showAt_); else @@ -100,6 +102,13 @@ Page { } MenuItem { + visible: messageContextMenu.isEditable + height: visible ? implicitHeight : 0 + text: qsTr("Edit") + onClicked: TimelineManager.timeline.editAction(messageContextMenu.eventId) + } + + MenuItem { text: qsTr("Read receipts") onTriggered: TimelineManager.timeline.readReceiptsAction(messageContextMenu.eventId) } diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml
index e8d41073..003f6b3a 100644 --- a/resources/qml/UserProfile.qml +++ b/resources/qml/UserProfile.qml
@@ -49,6 +49,7 @@ ApplicationWindow { Text { id: errorText + text: "Error Text" color: "red" visible: opacity > 0 @@ -58,24 +59,28 @@ ApplicationWindow { SequentialAnimation { id: hideErrorAnimation + running: false + PauseAnimation { duration: 4000 } + NumberAnimation { target: errorText property: 'opacity' to: 0 duration: 1000 } + } - Connections{ + Connections { target: profile onDisplayError: { - errorText.text = errorMessage - errorText.opacity = 1 - hideErrorAnimation.restart() + errorText.text = errorMessage; + errorText.opacity = 1; + hideErrorAnimation.restart(); } } diff --git a/resources/qml/delegates/FileMessage.qml b/resources/qml/delegates/FileMessage.qml
index ffd1e82b..4bc202eb 100644 --- a/resources/qml/delegates/FileMessage.qml +++ b/resources/qml/delegates/FileMessage.qml
@@ -1,4 +1,4 @@ -import QtQuick 2.6 +import QtQuick 2.12 import QtQuick.Layouts 1.2 import im.nheko 1.0 @@ -31,7 +31,15 @@ Item { MouseArea { anchors.fill: parent - onClicked: TimelineManager.timeline.saveMedia(model.data.id) + cursorShape: Qt.PointingHandCursor + } + + TapHandler { + onSingleTapped: TimelineManager.timeline.saveMedia(model.data.id) + } + + CursorShape { + anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/resources/qml/delegates/ImageMessage.qml b/resources/qml/delegates/ImageMessage.qml
index e8e325f0..3bb9eb05 100644 --- a/resources/qml/delegates/ImageMessage.qml +++ b/resources/qml/delegates/ImageMessage.qml
@@ -1,4 +1,4 @@ -import QtQuick 2.6 +import QtQuick 2.12 import im.nheko 1.0 Item { @@ -32,20 +32,20 @@ Item { smooth: true mipmap: true - MouseArea { - id: mouseArea - + TapHandler { enabled: model.data.type == MtxEvent.ImageMessage && img.status == Image.Ready - hoverEnabled: true - anchors.fill: parent - onClicked: TimelineManager.openImageOverlay(model.data.url, model.data.id) + onSingleTapped: TimelineManager.openImageOverlay(model.data.url, model.data.id) + } + + HoverHandler { + id: mouseArea } Item { id: overlay anchors.fill: parent - visible: mouseArea.containsMouse + visible: mouseArea.hovered Rectangle { id: container diff --git a/resources/qml/delegates/NoticeMessage.qml b/resources/qml/delegates/NoticeMessage.qml
index 67a69055..c38cb555 100644 --- a/resources/qml/delegates/NoticeMessage.qml +++ b/resources/qml/delegates/NoticeMessage.qml
@@ -1,6 +1,6 @@ TextMessage { font.italic: true color: colors.buttonText - height: isReply ? Math.min(chat.height / 8, implicitHeight) : undefined + height: isReply ? Math.min(timelineRoot.height / 8, implicitHeight) : undefined clip: isReply } diff --git a/resources/qml/delegates/PlayableMediaMessage.qml b/resources/qml/delegates/PlayableMediaMessage.qml
index 1534da2e..70f39e43 100644 --- a/resources/qml/delegates/PlayableMediaMessage.qml +++ b/resources/qml/delegates/PlayableMediaMessage.qml
@@ -1,5 +1,5 @@ import QtMultimedia 5.6 -import QtQuick 2.6 +import QtQuick 2.12 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.2 import im.nheko 1.0 @@ -140,9 +140,8 @@ Rectangle { fillMode: Image.Pad } - MouseArea { - anchors.fill: parent - onClicked: { + TapHandler { + onSingleTapped: { switch (button.state) { case "": TimelineManager.timeline.cacheMedia(model.data.id); @@ -159,6 +158,10 @@ Rectangle { break; } } + } + + CursorShape { + anchors.fill: parent cursorShape: Qt.PointingHandCursor } diff --git a/resources/qml/delegates/Reply.qml b/resources/qml/delegates/Reply.qml
index ff1fa657..28c4bf6e 100644 --- a/resources/qml/delegates/Reply.qml +++ b/resources/qml/delegates/Reply.qml
@@ -1,4 +1,4 @@ -import QtQuick 2.6 +import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 @@ -13,10 +13,12 @@ Item { width: parent.width height: replyContainer.height - MouseArea { + TapHandler { + onSingleTapped: chat.positionViewAtIndex(chat.model.idToIndex(modelData.id), ListView.Contain) + } + + CursorShape { anchors.fill: parent - preventStealing: false - onClicked: chat.positionViewAtIndex(chat.model.idToIndex(modelData.id), ListView.Contain) cursorShape: Qt.PointingHandCursor } @@ -43,10 +45,8 @@ Item { color: replyComponent.userColor textFormat: Text.RichText - MouseArea { - anchors.fill: parent - onClicked: chat.model.openUserProfile(reply.modelData.userId) - cursorShape: Qt.PointingHandCursor + TapHandler { + onSingleTapped: chat.model.openUserProfile(reply.modelData.userId) } } diff --git a/resources/qml/delegates/TextMessage.qml b/resources/qml/delegates/TextMessage.qml
index 3ff771dc..82d0d0e4 100644 --- a/resources/qml/delegates/TextMessage.qml +++ b/resources/qml/delegates/TextMessage.qml
@@ -4,9 +4,10 @@ import im.nheko 1.0 MatrixText { property string formatted: model.data.formattedBody - text: "<span style='white-space: pre-wrap'><style type=\"text/css\">a { color:" + colors.link + ";}\ncode { background-color: " + colors.alternateBase + ";}</style>" + formatted.replace("<pre>", "<pre style='white-space: pre-wrap; background-color: " + colors.alternateBase + "'>") + "</span>" + text: "<style type=\"text/css\">a { color:" + colors.link + ";}\ncode { background-color: " + colors.alternateBase + ";}</style>" + formatted.replace("<pre>", "<pre style='white-space: pre-wrap; background-color: " + colors.alternateBase + "'>") width: parent ? parent.width : undefined height: isReply ? Math.round(Math.min(timelineRoot.height / 8, implicitHeight)) : undefined clip: isReply + selectByMouse: !Settings.mobileMode && !isReply font.pointSize: (Settings.enlargeEmojiOnlyMessages && model.data.isOnlyEmoji > 0 && model.data.isOnlyEmoji < 4) ? Settings.fontSize * 3 : Settings.fontSize } diff --git a/resources/qml/emoji/EmojiButton.qml b/resources/qml/emoji/EmojiButton.qml
index 928d6226..dd7530a6 100644 --- a/resources/qml/emoji/EmojiButton.qml +++ b/resources/qml/emoji/EmojiButton.qml
@@ -14,5 +14,6 @@ ImageButton { image: ":/icons/icons/ui/smile.png" onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.show(emojiButton, function(emoji) { TimelineManager.queueReactionMessage(event_id, emoji); + TimelineManager.focusMessageInput(); }) }