summary refs log tree commit diff
path: root/resources/qml
diff options
context:
space:
mode:
authorJoseph Donofry <joedonofry@gmail.com>2021-07-19 14:12:28 -0400
committerJoseph Donofry <joedonofry@gmail.com>2021-07-19 14:12:28 -0400
commita4754e79d2e5d8c3a490cd01989abd25dd360646 (patch)
tree44114ff7e7527346792931e69908f02109a366ec /resources/qml
parentImport and update lurkki's branch (diff)
parentFix reaction button again (diff)
downloadnheko-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.qml8
-rw-r--r--resources/qml/MessageInput.qml29
-rw-r--r--resources/qml/MessageView.qml10
-rw-r--r--resources/qml/TimelineRow.qml38
-rw-r--r--resources/qml/emoji/EmojiButton.qml23
-rw-r--r--resources/qml/emoji/EmojiPicker.qml1
-rw-r--r--resources/qml/emoji/StickerPicker.qml181
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
+                }
+
+            }
+
+        }
+
+    }
+
+}