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..d4f7ca62 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, TimelineManager.completerFor("stickers", 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..4e605ad7 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(emojiButton, function(emoji) {
+ var event_id = row.model ? row.model.eventId : "";
+ room.input.reaction(event_id, emoji);
+ TimelineManager.focusMessageInput();
+ })
}
ImageButton {
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/StickerPicker.qml b/resources/qml/emoji/StickerPicker.qml
new file mode 100644
index 00000000..eca302eb
--- /dev/null
+++ b/resources/qml/emoji/StickerPicker.qml
@@ -0,0 +1,178 @@
+// 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 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, model_, callback) {
+ console.debug("Showing sticker picker");
+ model = model_;
+ 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
+
+ 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
+ }
+
+ }
+
+ }
+
+ }
+
+}
|