diff options
author | Joseph Donofry <joedonofry@gmail.com> | 2021-07-19 14:12:28 -0400 |
---|---|---|
committer | Joseph Donofry <joedonofry@gmail.com> | 2021-07-19 14:12:28 -0400 |
commit | a4754e79d2e5d8c3a490cd01989abd25dd360646 (patch) | |
tree | 44114ff7e7527346792931e69908f02109a366ec /resources/qml | |
parent | Import and update lurkki's branch (diff) | |
parent | Fix reaction button again (diff) | |
download | nheko-a4754e79d2e5d8c3a490cd01989abd25dd360646.tar.xz |
Merge remote-tracking branch 'nheko-im/master' into video_player_enhancements
Diffstat (limited to 'resources/qml')
-rw-r--r-- | resources/qml/MatrixText.qml | 8 | ||||
-rw-r--r-- | resources/qml/MessageInput.qml | 29 | ||||
-rw-r--r-- | resources/qml/MessageView.qml | 10 | ||||
-rw-r--r-- | resources/qml/TimelineRow.qml | 38 | ||||
-rw-r--r-- | resources/qml/emoji/EmojiButton.qml | 23 | ||||
-rw-r--r-- | resources/qml/emoji/EmojiPicker.qml | 1 | ||||
-rw-r--r-- | resources/qml/emoji/StickerPicker.qml | 181 |
7 files changed, 239 insertions, 51 deletions
diff --git a/resources/qml/MatrixText.qml b/resources/qml/MatrixText.qml index 9129b154..35e5f7e7 100644 --- a/resources/qml/MatrixText.qml +++ b/resources/qml/MatrixText.qml @@ -8,6 +8,7 @@ import im.nheko 1.0 TextEdit { id: r + textFormat: TextEdit.RichText readOnly: true focus: false @@ -19,14 +20,13 @@ TextEdit { onLinkActivated: Nheko.openLink(link) ToolTip.visible: hoveredLink ToolTip.text: hoveredLink + Component.onCompleted: { + TimelineManager.fixImageRendering(r.textDocument, r); + } CursorShape { anchors.fill: parent cursorShape: hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor } - Component.onCompleted: { - TimelineManager.fixImageRendering(r.textDocument, r) - } - } diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 24f9b0e8..415d67a7 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -2,6 +2,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +import "./emoji" import "./voip" import QtQuick 2.12 import QtQuick.Controls 2.3 @@ -87,7 +88,7 @@ Rectangle { Layout.alignment: Qt.AlignBottom // | Qt.AlignHCenter Layout.maximumHeight: Window.height / 4 Layout.minimumHeight: Settings.fontSize - implicitWidth: inputBar.width - 4 * (22 + 16) - 24 + implicitWidth: inputBar.width - 5 * (22 + 16) - 24 TextArea { id: messageInput @@ -320,6 +321,30 @@ Rectangle { } ImageButton { + id: stickerButton + + Layout.alignment: Qt.AlignRight | Qt.AlignBottom + Layout.margins: 8 + hoverEnabled: true + width: 22 + height: 22 + image: ":/icons/icons/ui/sticky-note-solid.svg" + ToolTip.visible: hovered + ToolTip.text: qsTr("Stickers") + onClicked: stickerPopup.visible ? stickerPopup.close() : stickerPopup.show(stickerButton, room.roomId(), function(row) { + room.input.sticker(stickerPopup.model.sourceModel, row); + TimelineManager.focusMessageInput(); + }) + + StickerPicker { + id: stickerPopup + + colors: Nheko.colors + } + + } + + ImageButton { id: emojiButton Layout.alignment: Qt.AlignRight | Qt.AlignBottom @@ -330,7 +355,7 @@ Rectangle { image: ":/icons/icons/ui/smile.png" ToolTip.visible: hovered ToolTip.text: qsTr("Emoji") - onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(emojiButton, function(emoji) { + onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(function(emoji) { messageInput.insert(messageInput.cursorPosition, emoji); TimelineManager.focusMessageInput(); }) diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index 33dff122..f56af237 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -92,16 +92,20 @@ ScrollView { } } - EmojiButton { + ImageButton { id: reactButton visible: chat.model ? chat.model.permissions.canSend(MtxEvent.Reaction) : false width: 16 hoverEnabled: true + image: ":/icons/icons/ui/smile.png" ToolTip.visible: hovered ToolTip.text: qsTr("React") - emojiPicker: emojiPopup - event_id: row.model ? row.model.eventId : "" + onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(reactButton, function(emoji) { + var event_id = row.model ? row.model.eventId : ""; + room.input.reaction(event_id, emoji); + TimelineManager.focusMessageInput(); + }) } ImageButton { diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml index 58e367a0..70db08e7 100644 --- a/resources/qml/TimelineRow.qml +++ b/resources/qml/TimelineRow.qml @@ -86,29 +86,29 @@ Item { // fancy reply, if this is a reply Reply { function fromModel(role) { - return replyTo != "" ? room.dataById(replyTo, role) : null; + return replyTo != "" ? room.dataById(replyTo, role, r.eventId) : null; } visible: replyTo - userColor: TimelineManager.userColor(userId, Nheko.colors.base) - blurhash: fromModel(Room.Blurhash) ?? "" - body: fromModel(Room.Body) ?? "" - formattedBody: fromModel(Room.FormattedBody) ?? "" + userColor: replyTo, TimelineManager.userColor(userId, Nheko.colors.base) + blurhash: replyTo, fromModel(Room.Blurhash) ?? "" + body: replyTo, fromModel(Room.Body) ?? "" + formattedBody: replyTo, fromModel(Room.FormattedBody) ?? "" eventId: fromModel(Room.EventId) ?? "" - filename: fromModel(Room.Filename) ?? "" - filesize: fromModel(Room.Filesize) ?? "" - proportionalHeight: fromModel(Room.ProportionalHeight) ?? 1 - type: fromModel(Room.Type) ?? MtxEvent.UnknownMessage - typeString: fromModel(Room.TypeString) ?? "" - url: fromModel(Room.Url) ?? "" - originalWidth: fromModel(Room.OriginalWidth) ?? 0 - isOnlyEmoji: fromModel(Room.IsOnlyEmoji) ?? false - userId: fromModel(Room.UserId) ?? "" - userName: fromModel(Room.UserName) ?? "" - thumbnailUrl: fromModel(Room.ThumbnailUrl) ?? "" - roomTopic: fromModel(Room.RoomTopic) ?? "" - roomName: fromModel(Room.RoomName) ?? "" - callType: fromModel(Room.CallType) ?? "" + filename: replyTo, fromModel(Room.Filename) ?? "" + filesize: replyTo, fromModel(Room.Filesize) ?? "" + proportionalHeight: replyTo, fromModel(Room.ProportionalHeight) ?? 1 + type: replyTo, fromModel(Room.Type) ?? MtxEvent.UnknownMessage + typeString: replyTo, fromModel(Room.TypeString) ?? "" + url: replyTo, fromModel(Room.Url) ?? "" + originalWidth: replyTo, fromModel(Room.OriginalWidth) ?? 0 + isOnlyEmoji: replyTo, fromModel(Room.IsOnlyEmoji) ?? false + userId: replyTo, fromModel(Room.UserId) ?? "" + userName: replyTo, fromModel(Room.UserName) ?? "" + thumbnailUrl: replyTo, fromModel(Room.ThumbnailUrl) ?? "" + roomTopic: replyTo, fromModel(Room.RoomTopic) ?? "" + roomName: replyTo, fromModel(Room.RoomName) ?? "" + callType: replyTo, fromModel(Room.CallType) ?? "" } // actual message content diff --git a/resources/qml/emoji/EmojiButton.qml b/resources/qml/emoji/EmojiButton.qml deleted file mode 100644 index 5f4d23d3..00000000 --- a/resources/qml/emoji/EmojiButton.qml +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -import "../" -import QtQuick 2.10 -import QtQuick.Controls 2.1 -import im.nheko 1.0 -import im.nheko.EmojiModel 1.0 - -ImageButton { - id: emojiButton - - property var colors: currentActivePalette - property var emojiPicker - property string event_id - - image: ":/icons/icons/ui/smile.png" - onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.show(emojiButton, function(emoji) { - room.input.reaction(event_id, emoji); - TimelineManager.focusMessageInput(); - }) -} diff --git a/resources/qml/emoji/EmojiPicker.qml b/resources/qml/emoji/EmojiPicker.qml index 6f10a230..354e340c 100644 --- a/resources/qml/emoji/EmojiPicker.qml +++ b/resources/qml/emoji/EmojiPicker.qml @@ -130,6 +130,7 @@ Menu { boundsBehavior: Flickable.StopAtBounds clip: true currentIndex: -1 // prevent sorting from stealing focus + cacheBuffer: 500 // Individual emoji delegate: AbstractButton { diff --git a/resources/qml/emoji/StickerPicker.qml b/resources/qml/emoji/StickerPicker.qml new file mode 100644 index 00000000..813c0b12 --- /dev/null +++ b/resources/qml/emoji/StickerPicker.qml @@ -0,0 +1,181 @@ +// SPDX-FileCopyrightText: 2021 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import "../" +import QtGraphicalEffects 1.0 +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.3 +import im.nheko 1.0 +import im.nheko.EmojiModel 1.0 + +Menu { + id: stickerPopup + + property var callback + property var colors + property string roomid + property alias model: gridView.model + property var textArea + property real highlightHue: Nheko.colors.highlight.hslHue + property real highlightSat: Nheko.colors.highlight.hslSaturation + property real highlightLight: Nheko.colors.highlight.hslLightness + readonly property int stickerDim: 128 + readonly property int stickerDimPad: 128 + Nheko.paddingSmall + readonly property int stickersPerRow: 3 + + function show(showAt, roomid_, callback) { + console.debug("Showing sticker picker"); + roomid = roomid_; + stickerPopup.callback = callback; + popup(showAt ? showAt : null); + } + + margins: 0 + bottomPadding: 1 + leftPadding: 1 + rightPadding: 1 + modal: true + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + width: stickersPerRow * stickerDimPad + 20 + + Rectangle { + color: Nheko.colors.window + height: columnView.implicitHeight + 4 + width: stickersPerRow * stickerDimPad + 20 + + ColumnLayout { + id: columnView + + spacing: 0 + anchors.leftMargin: 3 + anchors.rightMargin: 3 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.topMargin: 2 + + // Search field + TextField { + id: emojiSearch + + Layout.topMargin: 3 + Layout.preferredWidth: stickersPerRow * stickerDimPad + 20 - 6 + palette: Nheko.colors + background: null + placeholderTextColor: Nheko.colors.buttonText + color: Nheko.colors.text + placeholderText: qsTr("Search") + selectByMouse: true + rightPadding: clearSearch.width + onTextChanged: searchTimer.restart() + onVisibleChanged: { + if (visible) + forceActiveFocus(); + + } + + Timer { + id: searchTimer + + interval: 350 // tweak as needed? + onTriggered: stickerPopup.model.searchString = emojiSearch.text + } + + ToolButton { + id: clearSearch + + visible: emojiSearch.text !== '' + icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText) + focusPolicy: Qt.NoFocus + onClicked: emojiSearch.clear() + hoverEnabled: true + background: null + + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + } + // clear the default hover effects. + + Image { + height: parent.height - 2 * Nheko.paddingSmall + width: height + source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText) + + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + margins: Nheko.paddingSmall + } + + } + + } + + } + + // emoji grid + GridView { + id: gridView + + model: roomid ? TimelineManager.completerFor("stickers", roomid) : null + + Layout.preferredHeight: cellHeight * 3.5 + Layout.preferredWidth: stickersPerRow * stickerDimPad + 20 + Layout.leftMargin: 4 + cellWidth: stickerDimPad + cellHeight: stickerDimPad + boundsBehavior: Flickable.StopAtBounds + clip: true + currentIndex: -1 // prevent sorting from stealing focus + cacheBuffer: 500 + + ScrollHelper { + flickable: parent + anchors.fill: parent + enabled: !Settings.mobileMode + } + + // Individual emoji + delegate: AbstractButton { + width: stickerDim + height: stickerDim + hoverEnabled: true + ToolTip.text: ":" + model.shortcode + ": - " + model.body + ToolTip.visible: hovered + // TODO: maybe add favorites at some point? + onClicked: { + console.debug("Picked " + model.shortcode); + stickerPopup.close(); + callback(model.originalRow); + } + + contentItem: Image { + height: stickerDim + width: stickerDim + source: model.url.replace("mxc://", "image://MxcImage/") + fillMode: Image.PreserveAspectFit + } + + background: Rectangle { + anchors.fill: parent + color: hovered ? Nheko.colors.highlight : 'transparent' + radius: 5 + } + + } + + ScrollBar.vertical: ScrollBar { + id: emojiScroll + } + + } + + } + + } + +} |