From 537725566bcfc9de27a25e0536a9d8279c8c6e16 Mon Sep 17 00:00:00 2001 From: "Sebastian J. Wolf" Date: Wed, 14 Oct 2020 23:25:56 +0200 Subject: [PATCH] Supporting stickers is quite some work... :/ --- harbour-fernschreiber.pro | 1 + qml/components/StickerPicker.qml | 186 ++++++++++++++++++++ qml/pages/ChatPage.qml | 31 ++-- src/stickermanager.cpp | 14 ++ src/stickermanager.h | 2 + src/tdlibreceiver.cpp | 7 + src/tdlibreceiver.h | 2 + src/tdlibwrapper.cpp | 31 +++- src/tdlibwrapper.h | 5 +- translations/harbour-fernschreiber-es.ts | 7 + translations/harbour-fernschreiber-fi.ts | 7 + translations/harbour-fernschreiber-hu.ts | 7 + translations/harbour-fernschreiber-pl.ts | 7 + translations/harbour-fernschreiber-ru.ts | 7 + translations/harbour-fernschreiber-zh_CN.ts | 7 + translations/harbour-fernschreiber.ts | 7 + 16 files changed, 304 insertions(+), 24 deletions(-) create mode 100644 qml/components/StickerPicker.qml diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index 9d5300f..359923b 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -37,6 +37,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/components/ImagePreview.qml \ qml/components/InReplyToRow.qml \ qml/components/LocationPreview.qml \ + qml/components/StickerPicker.qml \ qml/components/WebPagePreview.qml \ qml/js/functions.js \ qml/pages/ChatPage.qml \ diff --git a/qml/components/StickerPicker.qml b/qml/components/StickerPicker.qml new file mode 100644 index 0000000..3d95806 --- /dev/null +++ b/qml/components/StickerPicker.qml @@ -0,0 +1,186 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ +import QtQuick 2.5 +import QtGraphicalEffects 1.0 +import QtMultimedia 5.0 +import Sailfish.Silica 1.0 +import "../components" +import "../js/twemoji.js" as Emoji + +Item { + id: stickerPickerOverlayItem + anchors.fill: parent + + property variant recentStickers: stickerManager.getRecentStickers() + property variant installedStickerSets: stickerManager.getInstalledStickerSets() + + Rectangle { + id: stickerPickerOverlayBackground + anchors.fill: parent + + color: Theme.overlayBackgroundColor + opacity: 0.7 + } + Flickable { + id: stickerPickerFlickable + anchors.fill: parent + anchors.margins: Theme.paddingMedium + contentHeight: stickerPickerColumn.height + clip: true + + Column { + id: stickerPickerColumn + spacing: Theme.paddingMedium + width: stickerPickerFlickable.width + Text { + font.pixelSize: Theme.fontSizeMedium + font.bold: true + color: Theme.primaryColor + width: parent.width + maximumLineCount: 1 + elide: Text.ElideRight + text: qsTr("Recently used") + } + Flickable { + width: parent.width + height: recentStickersRow.height + Theme.paddingSmall + anchors.horizontalCenter: parent.horizontalCenter + contentWidth: recentStickersRow.width + clip: true + + Row { + id: recentStickersRow + spacing: Theme.paddingMedium + Repeater { + model: stickerPickerOverlayItem.recentStickers + + Item { + height: singleRecentStickerRow.height + width: singleRecentStickerRow.width + + Row { + id: singleRecentStickerRow + spacing: Theme.paddingSmall + Image { + source: modelData.sticker.local.path + width: Theme.itemSizeMedium + height: Theme.itemSizeMedium + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + tdLibWrapper.sendStickerMessage(chatInformation.id, modelData.sticker.local.path); + stickerPickerOverlayItem.visible = false; + attachmentOptionsRow.visible = false; + } + } + } + + } + } + } + Repeater { + model: stickerPickerOverlayItem.installedStickerSets + width: stickerPickerFlickable.width + Column { + spacing: Theme.paddingMedium + width: parent.width + Text { + font.pixelSize: Theme.fontSizeMedium + font.bold: true + color: Theme.primaryColor + width: parent.width + maximumLineCount: 1 + elide: Text.ElideRight + text: modelData.title + } + Flickable { + width: parent.width + height: installedStickerSetRow.height + Theme.paddingSmall + anchors.horizontalCenter: parent.horizontalCenter + contentWidth: installedStickerSetRow.width + clip: true + Row { + id: installedStickerSetRow + spacing: Theme.paddingMedium + + Repeater { + model: modelData.stickers + + Item { + width: Theme.itemSizeMedium + height: Theme.itemSizeMedium + + Component.onCompleted: { + if (!modelData.sticker.local.is_downloading_completed) { + tdLibWrapper.downloadFile(modelData.sticker.id); + } + } + + Connections { + target: tdLibWrapper + onFileUpdated : { + if (fileInformation.local.is_downloading_completed) { + if (fileId === modelData.sticker.id) { + singleStickerImage.source = fileInformation.local.path; + } + } + } + } + + Image { + id: singleStickerImage + source: modelData.sticker.local.is_downloading_completed ? modelData.sticker.local.path : "" + anchors.fill: parent + visible: modelData.sticker.local.is_downloading_completed + } + Text { + font.pixelSize: Theme.fontSizeLarge + color: Theme.primaryColor + anchors.fill: parent + maximumLineCount: 1 + elide: Text.ElideRight + text: Emoji.emojify(modelData.emoji, font.pixelSize) + visible: !modelData.sticker.local.is_downloading_completed + } + + MouseArea { + anchors.fill: parent + onClicked: { + tdLibWrapper.sendStickerMessage(chatInformation.id, modelData.sticker.local.path); + stickerPickerOverlayItem.visible = false; + attachmentOptionsRow.visible = false; + } + } + } + + } + } + } + + + } + } + + } + } +} + diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 2891151..68264d7 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -635,14 +635,14 @@ Page { if (display.forward_info.origin["@type"] === "messageForwardOriginChannel") { var otherChatInformation = tdLibWrapper.getChat(display.forward_info.origin.chat_id); forwardedThumbnail.photoData = (typeof otherChatInformation.photo !== "undefined") ? otherChatInformation.photo.small : ""; - forwardedChannelText.text = otherChatInformation.title; + forwardedChannelText.text = Emoji.emojify(otherChatInformation.title, Theme.fontSizeExtraSmall); } else if (display.forward_info.origin["@type"] === "messageForwardOriginUser") { var otherUserInformation = tdLibWrapper.getUserInformation(display.forward_info.origin.sender_user_id); forwardedThumbnail.photoData = (typeof otherUserInformation.profile_photo !== "undefined") ? otherUserInformation.profile_photo.small : ""; - forwardedChannelText.text = Functions.getUserName(otherUserInformation); + forwardedChannelText.text = Emoji.emojify(Functions.getUserName(otherUserInformation), Theme.fontSizeExtraSmall); } else { forwardedThumbnail.photoData = ""; - forwardedChannelText.text = display.forward_info.origin.sender_user_name; + forwardedChannelText.text = Emoji.emojify(display.forward_info.origin.sender_user_name, Theme.fontSizeExtraSmall); } } @@ -680,7 +680,7 @@ Page { font.bold: true elide: Text.ElideRight textFormat: Text.StyledText - text: forwardedMessageInformationRow.otherChatInformation.title + text: Emoji.emojify(forwardedMessageInformationRow.otherChatInformation.title, font.pixelSize) onTruncatedChanged: { // There is obviously a bug in QML in truncating text with images. // We simply remove Emojis then... @@ -945,19 +945,10 @@ Page { } } - Item { - id: stickerPickerOverlayItem - anchors.fill: parent - visible: false - Rectangle { - id: stickerPickerOverlayBackground - anchors.fill: parent - - color: Theme.overlayBackgroundColor - opacity: 0.7 - } - } - +// StickerPicker { +// id: stickerPicker +// visible: false +// } } Column { @@ -1063,13 +1054,13 @@ Page { height: documentAttachmentButton.height color: Theme.primaryColor highlightColor: Theme.highlightColor - highlighted: stickerPickerOverlayItem.visible + highlighted: stickerPicker.visible MouseArea { anchors.fill: parent onClicked: { //console.log("RECENT STICKERS: " + JSON.stringify(stickerManager.getRecentStickers())); //console.log("INSTALLED SETS: " + JSON.stringify(stickerManager.getInstalledStickerSets())); - stickerPickerOverlayItem.visible = !stickerPickerOverlayItem.visible; + stickerPicker.visible = !stickerPicker.visible; } } } @@ -1207,7 +1198,7 @@ Page { anchors.bottom: parent.bottom anchors.bottomMargin: Theme.paddingSmall - enabled: !attachmentPreviewRow.visible + enabled: !(attachmentPreviewRow.visible || stickerPicker.visible) onClicked: { if (attachmentOptionsRow.visible) { attachmentOptionsRow.visible = false; diff --git a/src/stickermanager.cpp b/src/stickermanager.cpp index 28487aa..eb0aecd 100644 --- a/src/stickermanager.cpp +++ b/src/stickermanager.cpp @@ -32,6 +32,7 @@ StickerManager::StickerManager(TDLibWrapper *tdLibWrapper, QObject *parent) : QO connect(this->tdLibWrapper, SIGNAL(stickersReceived(QVariantList)), this, SLOT(handleStickersReceived(QVariantList))); connect(this->tdLibWrapper, SIGNAL(installedStickerSetsUpdated(QVariantList)), this, SLOT(handleInstalledStickerSetsUpdated(QVariantList))); connect(this->tdLibWrapper, SIGNAL(stickerSetsReceived(QVariantList)), this, SLOT(handleStickerSetsReceived(QVariantList))); + connect(this->tdLibWrapper, SIGNAL(stickerSetReceived(QVariantMap)), this, SLOT(handleStickerSetReceived(QVariantMap))); } StickerManager::~StickerManager() @@ -89,8 +90,21 @@ void StickerManager::handleStickerSetsReceived(const QVariantList &stickerSets) this->installedStickerSets.clear(); QListIterator stickerSetIdIterator(this->installedStickerSetIds); + int i = 0; + this->stickerSetMap.clear(); while (stickerSetIdIterator.hasNext()) { QString stickerSetId = stickerSetIdIterator.next().toString(); this->installedStickerSets.append(this->stickerSets.value(stickerSetId)); + this->stickerSetMap.insert(stickerSetId, i); + i++; } } + +void StickerManager::handleStickerSetReceived(const QVariantMap &stickerSet) +{ + LOG("Receiving complete sticker set...." << stickerSet); + QString stickerSetId = stickerSet.value("id").toString(); + this->stickerSets.insert(stickerSetId, stickerSet); + int setIndex = this->stickerSetMap.value(stickerSetId).toInt(); + this->installedStickerSets.replace(setIndex, stickerSet); +} diff --git a/src/stickermanager.h b/src/stickermanager.h index 2ccdf54..326796d 100644 --- a/src/stickermanager.h +++ b/src/stickermanager.h @@ -44,6 +44,7 @@ private slots: void handleStickersReceived(const QVariantList &stickers); void handleInstalledStickerSetsUpdated(const QVariantList &stickerSetIds); void handleStickerSetsReceived(const QVariantList &stickerSets); + void handleStickerSetReceived(const QVariantMap &stickerSet); private: @@ -55,6 +56,7 @@ private: QVariantList installedStickerSetIds; QVariantMap stickers; QVariantMap stickerSets; + QVariantMap stickerSetMap; }; diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index dd63f6a..407e633 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -103,6 +103,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren handlers.insert("stickers", &TDLibReceiver::processStickers); handlers.insert("updateInstalledStickerSets", &TDLibReceiver::processUpdateInstalledStickerSets); handlers.insert("stickerSets", &TDLibReceiver::processStickerSets); + handlers.insert("stickerSet", &TDLibReceiver::processStickerSet); } void TDLibReceiver::setActive(const bool &active) @@ -397,3 +398,9 @@ void TDLibReceiver::processStickerSets(const QVariantMap &receivedInformation) LOG("Received some sticker sets..."); emit stickerSets(receivedInformation.value("sets").toList()); } + +void TDLibReceiver::processStickerSet(const QVariantMap &receivedInformation) +{ + LOG("Received a sticker set..."); + emit stickerSet(receivedInformation); +} diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index 7ed6ef7..8aac1ba 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -68,6 +68,7 @@ signals: void stickers(const QVariantList &stickers); void installedStickerSetsUpdated(const QVariantList &stickerSetIds); void stickerSets(const QVariantList &stickerSets); + void stickerSet(const QVariantMap &stickerSet); private: typedef void (TDLibReceiver::*Handler)(const QVariantMap &); @@ -111,6 +112,7 @@ private: void processStickers(const QVariantMap &receivedInformation); void processUpdateInstalledStickerSets(const QVariantMap &receivedInformation); void processStickerSets(const QVariantMap &receivedInformation); + void processStickerSet(const QVariantMap &receivedInformation); }; #endif // TDLIBRECEIVER_H diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 533c908..94994ca 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -91,6 +91,7 @@ TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent) connect(this->tdLibReceiver, SIGNAL(stickers(QVariantList)), this, SLOT(handleStickers(QVariantList))); connect(this->tdLibReceiver, SIGNAL(installedStickerSetsUpdated(QVariantList)), this, SLOT(handleInstalledStickerSetsUpdated(QVariantList))); connect(this->tdLibReceiver, SIGNAL(stickerSets(QVariantList)), this, SLOT(handleStickerSets(QVariantList))); + connect(this->tdLibReceiver, SIGNAL(stickerSet(QVariantMap)), this, SLOT(handleStickerSet(QVariantMap))); this->tdLibReceiver->start(); @@ -336,9 +337,9 @@ void TDLibWrapper::sendDocumentMessage(const QString &chatId, const QString &fil this->sendRequest(requestObject); } -void TDLibWrapper::sendStickerMessage(const QString &chatId, const QVariantMap &stickerInformation, const QString &replyToMessageId) +void TDLibWrapper::sendStickerMessage(const QString &chatId, const QString &filePath, const QString &replyToMessageId) { - LOG("Sending sticker message" << chatId << stickerInformation << replyToMessageId); + LOG("Sending sticker message" << chatId << filePath << replyToMessageId); QVariantMap requestObject; requestObject.insert(_TYPE, "sendMessage"); requestObject.insert("chat_id", chatId); @@ -347,7 +348,12 @@ void TDLibWrapper::sendStickerMessage(const QString &chatId, const QVariantMap & } QVariantMap inputMessageContent; inputMessageContent.insert(_TYPE, "inputMessageSticker"); - inputMessageContent.insert("sticker", stickerInformation); + + QVariantMap stickerInputFile; + stickerInputFile.insert(_TYPE, "inputFileLocal"); + stickerInputFile.insert("path", filePath); + + inputMessageContent.insert("sticker", stickerInputFile); requestObject.insert("input_message_content", inputMessageContent); this->sendRequest(requestObject); @@ -452,6 +458,15 @@ void TDLibWrapper::getInstalledStickerSets() this->sendRequest(requestObject); } +void TDLibWrapper::getStickerSet(const QString &setId) +{ + LOG("Retrieving sticker set" << setId); + QVariantMap requestObject; + requestObject.insert(_TYPE, "getStickerSet"); + requestObject.insert("set_id", setId); + this->sendRequest(requestObject); +} + QVariantMap TDLibWrapper::getUserInformation() { return this->userInformation; @@ -800,9 +815,19 @@ void TDLibWrapper::handleInstalledStickerSetsUpdated(const QVariantList &sticker void TDLibWrapper::handleStickerSets(const QVariantList &stickerSets) { + QListIterator stickerSetIterator(stickerSets); + while (stickerSetIterator.hasNext()) { + QVariantMap stickerSet = stickerSetIterator.next().toMap(); + this->getStickerSet(stickerSet.value("id").toString()); + } emit this->stickerSetsReceived(stickerSets); } +void TDLibWrapper::handleStickerSet(const QVariantMap &stickerSet) +{ + emit stickerSetReceived(stickerSet); +} + void TDLibWrapper::setInitialParameters() { LOG("Sending initial parameters to TD Lib"); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index cb710f5..40b4ba6 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -118,7 +118,7 @@ public: Q_INVOKABLE void sendPhotoMessage(const QString &chatId, const QString &filePath, const QString &message, const QString &replyToMessageId = "0"); Q_INVOKABLE void sendVideoMessage(const QString &chatId, const QString &filePath, const QString &message, const QString &replyToMessageId = "0"); Q_INVOKABLE void sendDocumentMessage(const QString &chatId, const QString &filePath, const QString &message, const QString &replyToMessageId = "0"); - Q_INVOKABLE void sendStickerMessage(const QString &chatId, const QVariantMap &stickerInformation, const QString &replyToMessageId = "0"); + Q_INVOKABLE void sendStickerMessage(const QString &chatId, const QString &filePath, const QString &replyToMessageId = "0"); Q_INVOKABLE void getMessage(const QString &chatId, const QString &messageId); Q_INVOKABLE void setOptionInteger(const QString &optionName, const int &optionValue); Q_INVOKABLE void setChatNotificationSettings(const QString &chatId, const QVariantMap ¬ificationSettings); @@ -127,6 +127,7 @@ public: Q_INVOKABLE void getMapThumbnailFile(const QString &chatId, const double &latitude, const double &longitude, const int &width, const int &height); Q_INVOKABLE void getRecentStickers(); Q_INVOKABLE void getInstalledStickerSets(); + Q_INVOKABLE void getStickerSet(const QString &setId); public: const Group* getGroup(qlonglong groupId) const; @@ -167,6 +168,7 @@ signals: void stickersReceived(const QVariantList &stickers); void installedStickerSetsUpdated(const QVariantList &stickerSetIds); void stickerSetsReceived(const QVariantList &stickerSets); + void stickerSetReceived(const QVariantMap &stickerSet); public slots: void handleVersionDetected(const QString &version); @@ -201,6 +203,7 @@ public slots: void handleStickers(const QVariantList &stickers); void handleInstalledStickerSetsUpdated(const QVariantList &stickerSetIds); void handleStickerSets(const QVariantList &stickerSets); + void handleStickerSet(const QVariantMap &stickerSet); private: void setInitialParameters(); diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 98ee718..a9e5343 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -523,6 +523,13 @@ Mostrar fondo para pegatinas y alinearlas centralmente como imágenes + + StickerPicker + + Recently used + + + VideoPage diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index b5ff7d4..ea21750 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -523,6 +523,13 @@ + + StickerPicker + + Recently used + + + VideoPage diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index f12bb76..02c873b 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -523,6 +523,13 @@ + + StickerPicker + + Recently used + + + VideoPage diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 650ee23..19c7fe0 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -523,6 +523,13 @@ + + StickerPicker + + Recently used + + + VideoPage diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 4baf2f4..b025095 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -523,6 +523,13 @@ То есть рисовать под ними фон и позиционировать по центру. + + StickerPicker + + Recently used + + + VideoPage diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index b7e9295..d6a7995 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -523,6 +523,13 @@ + + StickerPicker + + Recently used + + + VideoPage diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 659c9a4..5e7f494 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -523,6 +523,13 @@ + + StickerPicker + + Recently used + + + VideoPage