Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stickers! #648

Merged
merged 5 commits into from
Jul 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ set(SRC_FILES
src/Olm.cpp
src/RegisterPage.cpp
src/SSOHandler.cpp
src/ImagePackModel.cpp
src/TrayIcon.cpp
src/UserSettingsPage.cpp
src/UsersModel.cpp
Expand Down Expand Up @@ -559,6 +560,7 @@ qt5_wrap_cpp(MOC_HEADERS
src/MxcImageProvider.h
src/RegisterPage.h
src/SSOHandler.h
src/ImagePackModel.h
src/TrayIcon.h
src/UserSettingsPage.h
src/UsersModel.h
Expand Down
1 change: 1 addition & 0 deletions resources/icons/ui/sticky-note-solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions resources/qml/MatrixText.qml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import im.nheko 1.0

TextEdit {
id: r

textFormat: TextEdit.RichText
readOnly: true
focus: false
Expand All @@ -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)
}

}
29 changes: 27 additions & 2 deletions resources/qml/MessageInput.qml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -319,6 +320,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

Expand All @@ -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();
})
Expand Down
10 changes: 7 additions & 3 deletions resources/qml/MessageView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
23 changes: 0 additions & 23 deletions resources/qml/emoji/EmojiButton.qml

This file was deleted.

178 changes: 178 additions & 0 deletions resources/qml/emoji/StickerPicker.qml
Original file line number Diff line number Diff line change
@@ -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
}

}

}

}

}
3 changes: 2 additions & 1 deletion resources/res.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<file>icons/ui/search@2x.png</file>
<file>icons/ui/settings.png</file>
<file>icons/ui/settings@2x.png</file>
<file>icons/ui/sticky-note-solid.svg</file>
<file>icons/ui/smile.png</file>
<file>icons/ui/smile@2x.png</file>
<file>icons/ui/speech-bubbles-comment-option.png</file>
Expand Down Expand Up @@ -150,8 +151,8 @@
<file>qml/ForwardCompleter.qml</file>
<file>qml/TypingIndicator.qml</file>
<file>qml/RoomSettings.qml</file>
<file>qml/emoji/EmojiButton.qml</file>
<file>qml/emoji/EmojiPicker.qml</file>
<file>qml/emoji/StickerPicker.qml</file>
<file>qml/UserProfile.qml</file>
<file>qml/delegates/MessageDelegate.qml</file>
<file>qml/delegates/TextMessage.qml</file>
Expand Down
Loading