diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro
index 83a998d..c56af5b 100644
--- a/harbour-fernschreiber.pro
+++ b/harbour-fernschreiber.pro
@@ -64,6 +64,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \
qml/components/ReplyMarkupButtons.qml \
qml/components/StickerPicker.qml \
qml/components/PhotoTextsListItem.qml \
+ qml/components/StickerSetOverlay.qml \
qml/components/TDLibImage.qml \
qml/components/TDLibMinithumbnail.qml \
qml/components/TDLibPhoto.qml \
diff --git a/qml/components/StickerSetOverlay.qml b/qml/components/StickerSetOverlay.qml
new file mode 100644
index 0000000..0cf65e3
--- /dev/null
+++ b/qml/components/StickerSetOverlay.qml
@@ -0,0 +1,170 @@
+/*
+ Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
+
+ 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.6
+import Sailfish.Silica 1.0
+import "./messageContent"
+import "../js/functions.js" as Functions
+import "../js/twemoji.js" as Emoji
+import "../js/debug.js" as Debug
+
+Flickable {
+ id: stickerSetOverlayFlickable
+ anchors.fill: parent
+ boundsBehavior: Flickable.StopAtBounds
+ contentHeight: stickerSetContentColumn.height
+ clip: true
+
+ property string stickerSetId;
+ property var stickerSet;
+ property bool setLoaded: false;
+ signal requestClose;
+
+ Component.onCompleted: {
+ if (!stickerManager.hasStickerSet(stickerSetId)) {
+ tdLibWrapper.getStickerSet(stickerSetId);
+ } else {
+ stickerSet = stickerManager.getStickerSet(stickerSetId);
+ }
+ }
+
+ Connections {
+ target: tdLibWrapper
+ onStickerSetReceived: {
+ if (stickerSet.id === stickerSetOverlayFlickable.stickerSetId) {
+ stickerSetOverlayFlickable.stickerSet = stickerSet;
+ }
+ }
+ }
+
+ Timer {
+ id: stickerSetLoadedTimer
+ interval: 100
+ running: true
+ repeat: false
+ onTriggered: {
+ stickerSetOverlayFlickable.setLoaded = true;
+ }
+ }
+
+ Rectangle {
+ id: stickerSetContentBackground
+ color: Theme.overlayBackgroundColor
+ opacity: 0.7
+ anchors.fill: parent
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ stickerSetOverlayFlickable.requestClose();
+ }
+ }
+ }
+
+ Column {
+ id: stickerSetContentColumn
+ spacing: Theme.paddingMedium
+ width: parent.width
+ height: parent.height
+
+ Row {
+ id: stickerSetTitleRow
+ width: parent.width - ( 2 * Theme.horizontalPageMargin )
+ height: overlayStickerTitleText.height + ( 2 * Theme.paddingMedium )
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ Label {
+ id: overlayStickerTitleText
+
+ width: parent.width - ( installSetButton.visible ? installSetButton.width : 0 ) - closeSetButton.width
+ text: stickerSet.title
+ font.pixelSize: Theme.fontSizeExtraLarge
+ font.weight: Font.ExtraBold
+ maximumLineCount: 1
+ truncationMode: TruncationMode.Fade
+ textFormat: Text.StyledText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ IconButton {
+ id: installSetButton
+ icon.source: "image://theme/icon-m-add"
+ anchors.verticalCenter: parent.verticalCenter
+ visible: !stickerSet.is_installed
+ onClicked: {
+ tdLibWrapper.changeStickerSet(stickerSet.id, true);
+ }
+ }
+
+ IconButton {
+ id: closeSetButton
+ icon.source: "image://theme/icon-m-clear"
+ anchors.verticalCenter: parent.verticalCenter
+ onClicked: {
+ stickerSetOverlayFlickable.requestClose();
+ }
+ }
+ }
+
+ SilicaGridView {
+ id: stickerSetGridView
+
+ width: parent.width - ( 2 * Theme.horizontalPageMargin )
+ height: parent.height - stickerSetTitleRow.height - Theme.paddingMedium
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ cellWidth: chatPage.isLandscape ? (width / 5) : (width / 3);
+ cellHeight: cellWidth
+
+ visible: count > 0
+
+ clip: true
+
+ model: stickerSet.stickers
+ delegate: Item {
+ width: stickerSetGridView.cellWidth - Theme.paddingSmall
+ height: stickerSetGridView.cellHeight - Theme.paddingSmall
+
+ Image {
+ id: singleStickerImage
+ source: modelData.thumbnail.file.local.is_downloading_completed ? modelData.thumbnail.file.local.path : ""
+ anchors.fill: parent
+ visible: modelData.thumbnail.file.local.is_downloading_completed
+ asynchronous: true
+ onStatusChanged: {
+ if (status === Image.Ready) {
+ stickerSetLoadedTimer.restart();
+ }
+ }
+ }
+ Label {
+ font.pixelSize: Theme.fontSizeHuge
+ anchors.fill: parent
+ maximumLineCount: 1
+ truncationMode: TruncationMode.Fade
+ text: Emoji.emojify(modelData.emoji, font.pixelSize)
+ visible: !modelData.thumbnail.file.local.is_downloading_completed
+ }
+
+ }
+
+ VerticalScrollDecorator {}
+ }
+
+ }
+
+}
diff --git a/qml/components/messageContent/MessageSticker.qml b/qml/components/messageContent/MessageSticker.qml
index 4b698c2..5216e57 100644
--- a/qml/components/messageContent/MessageSticker.qml
+++ b/qml/components/messageContent/MessageSticker.qml
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2020 Sebastian J. Wolf and other contributors
+ Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
This file is part of Fernschreiber.
@@ -96,6 +96,14 @@ MessageContentBase {
opacity: !stickerVisible && !placeHolderDelayTimer.running ? 0.15 : 0
Behavior on opacity { FadeAnimation {} }
}
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ stickerSetOverlayLoader.stickerSetId = stickerData.set_id;
+ stickerSetOverlayLoader.active = true;
+ }
+ }
}
Timer {
diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml
index d2346bb..1740822 100644
--- a/qml/pages/ChatPage.qml
+++ b/qml/pages/ChatPage.qml
@@ -1285,6 +1285,28 @@ Page {
}
}
+ Loader {
+ id: stickerSetOverlayLoader
+
+ property string stickerSetId;
+
+ active: false
+ asynchronous: true
+ width: parent.width
+ height: active ? parent.height : 0
+ sourceComponent: Component {
+ StickerSetOverlay {
+ stickerSetId: stickerSetOverlayLoader.stickerSetId
+ onRequestClose: {
+ stickerSetOverlayLoader.active = false;
+ }
+ }
+ }
+
+ onActiveChanged: {
+ }
+ }
+
InlineQuery {
id: inlineQuery
textField: newMessageTextField
diff --git a/src/stickermanager.cpp b/src/stickermanager.cpp
index e0ab6bf..479c672 100644
--- a/src/stickermanager.cpp
+++ b/src/stickermanager.cpp
@@ -50,6 +50,16 @@ QVariantList StickerManager::getInstalledStickerSets()
return this->installedStickerSets;
}
+QVariantMap StickerManager::getStickerSet(const QString &stickerSetId)
+{
+ return this->stickerSets.value(stickerSetId).toMap();
+}
+
+bool StickerManager::hasStickerSet(const QString &stickerSetId)
+{
+ return this->stickerSets.contains(stickerSetId);
+}
+
bool StickerManager::needsReload()
{
return this->reloadNeeded;
@@ -104,19 +114,25 @@ void StickerManager::handleStickerSetsReceived(const QVariantList &stickerSets)
this->stickerSetMap.clear();
while (stickerSetIdIterator.hasNext()) {
QString stickerSetId = stickerSetIdIterator.next().toString();
- this->installedStickerSets.append(this->stickerSets.value(stickerSetId));
- this->stickerSetMap.insert(stickerSetId, i);
- i++;
+ if (this->installedStickerSetIds.contains(stickerSetId)) {
+ this->installedStickerSets.append(this->stickerSets.value(stickerSetId));
+ this->stickerSetMap.insert(stickerSetId, i);
+ i++;
+ }
}
}
void StickerManager::handleStickerSetReceived(const QVariantMap &stickerSet)
{
QString stickerSetId = stickerSet.value("id").toString();
- LOG("Receiving complete sticker set...." << stickerSetId);
this->stickerSets.insert(stickerSetId, stickerSet);
- int setIndex = this->stickerSetMap.value(stickerSetId).toInt();
- this->installedStickerSets.replace(setIndex, stickerSet);
+ if (this->installedStickerSetIds.contains(stickerSetId)) {
+ LOG("Receiving installed sticker set...." << stickerSetId);
+ int setIndex = this->stickerSetMap.value(stickerSetId).toInt();
+ this->installedStickerSets.replace(setIndex, stickerSet);
+ } else {
+ LOG("Receiving new sticker set...." << stickerSetId);
+ }
QVariantList stickerList = stickerSet.value("stickers").toList();
QListIterator stickerIterator(stickerList);
while (stickerIterator.hasNext()) {
diff --git a/src/stickermanager.h b/src/stickermanager.h
index 3aae40f..e952055 100644
--- a/src/stickermanager.h
+++ b/src/stickermanager.h
@@ -35,6 +35,8 @@ public:
Q_INVOKABLE QVariantList getRecentStickers();
Q_INVOKABLE QVariantList getInstalledStickerSets();
+ Q_INVOKABLE QVariantMap getStickerSet(const QString &stickerSetId);
+ Q_INVOKABLE bool hasStickerSet(const QString &stickerSetId);
Q_INVOKABLE bool needsReload();
Q_INVOKABLE void setNeedsReload(const bool &reloadNeeded);
diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp
index 8f42add..f1b06ff 100644
--- a/src/tdlibwrapper.cpp
+++ b/src/tdlibwrapper.cpp
@@ -1326,6 +1326,18 @@ void TDLibWrapper::deleteProfilePhoto(const QString &profilePhotoId)
this->sendRequest(requestObject);
}
+void TDLibWrapper::changeStickerSet(const QString &stickerSetId, bool isInstalled)
+{
+ LOG("Change sticker set" << stickerSetId << isInstalled);
+
+ QVariantMap requestObject;
+ requestObject.insert(_TYPE, "changeStickerSet");
+ requestObject.insert("set_id", stickerSetId);
+ requestObject.insert("is_installed", isInstalled);
+
+ this->sendRequest(requestObject);
+}
+
void TDLibWrapper::searchEmoji(const QString &queryString)
{
LOG("Searching emoji" << queryString);
diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h
index 207ce56..7cd4664 100644
--- a/src/tdlibwrapper.h
+++ b/src/tdlibwrapper.h
@@ -221,6 +221,7 @@ public:
Q_INVOKABLE void getUserPrivacySettingRules(UserPrivacySetting setting);
Q_INVOKABLE void setProfilePhoto(const QString &filePath);
Q_INVOKABLE void deleteProfilePhoto(const QString &profilePhotoId);
+ Q_INVOKABLE void changeStickerSet(const QString &stickerSetId, bool isInstalled);
// Others (candidates for extraction ;))
Q_INVOKABLE void searchEmoji(const QString &queryString);