Merge pull request #376 from Wunderfitz/newStickerSets

Redesign sticker picker, show sticker sets, install/remove sticker sets
This commit is contained in:
Sebastian Wolf 2021-02-15 21:19:13 +01:00 committed by GitHub
commit 41e9efb8e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 615 additions and 129 deletions

View file

@ -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 \

View file

@ -25,22 +25,28 @@ Item {
id: stickerPickerOverlayItem
anchors.fill: parent
property var recentStickers: stickerManager.getRecentStickers()
property var installedStickerSets: stickerManager.getInstalledStickerSets()
property bool pickerLoaded: false
property var recentStickers: stickerManager.getRecentStickers();
property var installedStickerSets: stickerManager.getInstalledStickerSets();
signal stickerPicked(var stickerId)
Timer {
id: stickerPickerLoadedTimer
interval: 100
running: true
repeat: false
onTriggered: {
stickerPickerOverlayItem.pickerLoaded = true;
Connections {
target: tdLibWrapper
onOkReceived: {
if (request === "removeStickerSet") {
appNotification.show(qsTr("Sticker set successfully removed!"));
tdLibWrapper.getInstalledStickerSets();
}
}
}
Connections {
target: stickerManager
onStickerSetsReceived: {
installedStickerSets = stickerManager.getInstalledStickerSets();
}
}
signal stickerPicked(var stickerId)
Rectangle {
id: stickerPickerOverlayBackground
anchors.fill: parent
@ -54,10 +60,6 @@ Item {
anchors.fill: parent
anchors.margins: Theme.paddingMedium
opacity: stickerPickerOverlayItem.pickerLoaded ? 1 : 0
Behavior on opacity { NumberAnimation {} }
visible: stickerPickerOverlayItem.pickerLoaded
contentHeight: stickerPickerColumn.height
clip: true
@ -66,7 +68,7 @@ Item {
spacing: Theme.paddingMedium
width: stickerPickerFlickable.width
Label {
font.pixelSize: Theme.fontSizeMedium
font.pixelSize: Theme.fontSizeLarge
font.bold: true
width: parent.width
maximumLineCount: 1
@ -90,15 +92,16 @@ Item {
width: recentStickersGridView.cellWidth
height: recentStickersGridView.cellHeight
Image {
source: modelData.thumbnail.file.local.path
TDLibThumbnail {
thumbnail: modelData.thumbnail
anchors.fill: parent
asynchronous: true
onStatusChanged: {
if (status === Image.Ready) {
stickerPickerLoadedTimer.restart();
}
}
}
Label {
font.pixelSize: Theme.fontSizeSmall
anchors.right: parent.right
anchors.bottom: parent.bottom
text: Emoji.emojify(modelData.emoji, font.pixelSize)
}
MouseArea {
@ -116,60 +119,126 @@ Item {
model: stickerPickerOverlayItem.installedStickerSets
width: stickerPickerFlickable.width
Column {
spacing: Theme.paddingMedium
width: parent.width
Label {
font.pixelSize: Theme.fontSizeMedium
font.bold: true
width: parent.width
maximumLineCount: 1
truncationMode: TruncationMode.Fade
text: modelData.title
id: stickerSetColumn
property bool isExpanded: false
function toggleDisplaySet() {
stickerSetColumn.isExpanded = !stickerSetColumn.isExpanded;
stickerSetLoader.active = stickerSetColumn.isExpanded;
if (stickerSetLoader.active) {
stickerSetLoader.myStickerSet = modelData.stickers;
} else {
stickerSetLoader.myStickerSet = ({});
}
}
SilicaGridView {
id: installedStickerSetGridView
spacing: Theme.paddingMedium
width: parent.width
Row {
id: stickerSetTitleRow
width: parent.width
height: Theme.itemSizeExtraLarge
cellWidth: Theme.itemSizeExtraLarge;
cellHeight: Theme.itemSizeExtraLarge;
visible: count > 0
clip: true
flow: GridView.FlowTopToBottom
model: modelData.stickers
delegate: Item {
width: installedStickerSetGridView.cellWidth
height: installedStickerSetGridView.cellHeight
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) {
stickerPickerLoadedTimer.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
}
height: stickerSetThumbnail.height + ( 2 * Theme.paddingSmall )
spacing: Theme.paddingMedium
TDLibThumbnail {
id: stickerSetThumbnail
thumbnail: modelData.thumbnail ? modelData.thumbnail : modelData.stickers[0].thumbnail
anchors.verticalCenter: parent.verticalCenter
width: Theme.itemSizeMedium
height: Theme.itemSizeMedium
MouseArea {
anchors.fill: parent
onClicked: stickerPickerOverlayItem.stickerPicked(modelData.sticker.remote.id)
onClicked: {
toggleDisplaySet();
}
}
}
HorizontalScrollDecorator {}
Label {
id: setTitleText
font.pixelSize: Theme.fontSizeLarge
font.bold: true
width: parent.width - removeSetButton.width - expandSetButton.width - stickerSetThumbnail.width - ( 3 * Theme.paddingMedium )
anchors.verticalCenter: parent.verticalCenter
maximumLineCount: 1
truncationMode: TruncationMode.Fade
text: modelData.title
MouseArea {
anchors.fill: parent
onClicked: {
toggleDisplaySet();
}
}
}
IconButton {
id: expandSetButton
icon.source: stickerSetColumn.isExpanded ? "image://theme/icon-m-up" : "image://theme/icon-m-down"
anchors.verticalCenter: parent.verticalCenter
onClicked: {
toggleDisplaySet();
}
}
IconButton {
id: removeSetButton
icon.source: "image://theme/icon-m-remove"
anchors.verticalCenter: parent.verticalCenter
onClicked: {
var stickerSetId = modelData.id;
Remorse.popupAction(chatPage, qsTr("Removing sticker set"), function() {
tdLibWrapper.changeStickerSet(stickerSetId, false);
});
}
}
}
Loader {
id: stickerSetLoader
width: parent.width
active: false
height: active ? Theme.itemSizeExtraLarge : 0
property var myStickerSet
sourceComponent: Component {
SilicaGridView {
id: installedStickerSetGridView
width: parent.width
height: parent.height
cellWidth: Theme.itemSizeExtraLarge;
cellHeight: Theme.itemSizeExtraLarge;
visible: count > 0
clip: true
flow: GridView.FlowTopToBottom
model: stickerSetLoader.myStickerSet
delegate: Item {
width: installedStickerSetGridView.cellWidth
height: installedStickerSetGridView.cellHeight
TDLibThumbnail {
thumbnail: modelData.thumbnail
anchors.fill: parent
}
Label {
font.pixelSize: Theme.fontSizeSmall
anchors.right: parent.right
anchors.bottom: parent.bottom
text: Emoji.emojify(modelData.emoji, font.pixelSize)
}
MouseArea {
anchors.fill: parent
onClicked: stickerPickerOverlayItem.stickerPicked(modelData.sticker.remote.id)
}
}
HorizontalScrollDecorator {}
}
}
}
}
@ -177,27 +246,5 @@ Item {
}
}
Column {
anchors.centerIn: parent
width: parent.width
spacing: Theme.paddingMedium
opacity: stickerPickerOverlayItem.pickerLoaded ? 0 : 1
Behavior on opacity { NumberAnimation {} }
visible: !stickerPickerOverlayItem.pickerLoaded
InfoLabel {
id: loadingLabel
text: qsTr("Loading stickers...")
}
BusyIndicator {
id: loadingBusyIndicator
anchors.horizontalCenter: parent.horizontalCenter
running: !stickerPickerOverlayItem.pickerLoaded
size: BusyIndicatorSize.Large
}
}
}

View file

@ -0,0 +1,173 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
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;
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;
}
}
onOkReceived: {
if (request === "installStickerSet") {
appNotification.show(qsTr("Sticker set successfully installed!"));
installSetButton.visible = false;
tdLibWrapper.getInstalledStickerSets();
}
if (request === "removeStickerSet") {
appNotification.show(qsTr("Sticker set successfully removed!"));
installSetButton.visible = true;
tdLibWrapper.getInstalledStickerSets();
}
}
}
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.width - 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: !stickerManager.isStickerSetInstalled(stickerSet.id)
onClicked: {
tdLibWrapper.changeStickerSet(stickerSet.id, true);
}
}
IconButton {
id: removeSetButton
icon.source: "image://theme/icon-m-remove"
anchors.verticalCenter: parent.verticalCenter
visible: !installSetButton.visible
onClicked: {
tdLibWrapper.changeStickerSet(stickerSet.id, false);
}
}
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
TDLibThumbnail {
id: singleStickerThumbnail
thumbnail: modelData.thumbnail
anchors.fill: parent
}
Label {
font.pixelSize: Theme.fontSizeSmall
anchors.right: parent.right
anchors.bottom: parent.bottom
text: Emoji.emojify(modelData.emoji, font.pixelSize)
}
}
VerticalScrollDecorator {}
}
}
}

View file

@ -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 {

View file

@ -699,7 +699,7 @@ Page {
contentWidth: width
PullDownMenu {
visible: chatInformation.id !== chatPage.myUserId && !stickerPickerLoader.active && !voiceNoteOverlayLoader.active && !messageOverlayLoader.active
visible: chatInformation.id !== chatPage.myUserId && !stickerPickerLoader.active && !voiceNoteOverlayLoader.active && !messageOverlayLoader.active && !stickerSetOverlayLoader.active
MenuItem {
id: closeSecretChatMenuItem
visible: chatPage.isSecretChat && chatPage.secretChatDetails.state["@type"] !== "secretChatStateClosed"
@ -958,7 +958,7 @@ Page {
id: chatView
visible: !blurred
property bool blurred: messageOverlayLoader.item || stickerPickerLoader.item || voiceNoteOverlayLoader.item || inlineQuery.hasOverlay
property bool blurred: messageOverlayLoader.item || stickerPickerLoader.item || voiceNoteOverlayLoader.item || inlineQuery.hasOverlay || stickerSetOverlayLoader.item
anchors.fill: parent
opacity: chatPage.loading ? 0 : 1
@ -1245,9 +1245,11 @@ Page {
target: stickerPickerLoader.item
onStickerPicked: {
Debug.log("Sticker picked: " + stickerId);
tdLibWrapper.sendStickerMessage(chatInformation.id, stickerId);
tdLibWrapper.sendStickerMessage(chatInformation.id, stickerId, newMessageColumn.replyToMessageId);
stickerPickerLoader.active = false;
attachmentOptionsFlickable.isNeeded = false;
newMessageInReplyToRow.inReplyToMessage = null;
newMessageColumn.editMessageId = "0";
}
}
@ -1285,6 +1287,31 @@ 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: {
if (active) {
attachmentOptionsFlickable.isNeeded = false;
}
}
}
InlineQuery {
id: inlineQuery
textField: newMessageTextField
@ -1751,7 +1778,7 @@ Page {
icon.source: "image://theme/icon-m-attach?" + (attachmentOptionsFlickable.isNeeded ? Theme.highlightColor : Theme.primaryColor)
anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.paddingSmall
enabled: !attachmentPreviewRow.visible
enabled: !attachmentPreviewRow.visible && !stickerSetOverlayLoader.item
visible: !inlineQuery.userNameIsValid
onClicked: {
if (attachmentOptionsFlickable.isNeeded) {

View file

@ -12,7 +12,7 @@ Name: harbour-fernschreiber
Summary: Fernschreiber is a Telegram client for Sailfish OS
Version: 0.7.1
Release: 1
Release: 2
Group: Qt/Qt
License: LICENSE
URL: http://werkwolf.eu/

View file

@ -1,7 +1,7 @@
Name: harbour-fernschreiber
Summary: Fernschreiber is a Telegram client for Sailfish OS
Version: 0.7.1
Release: 1
Release: 2
# The contents of the Group field should be one of the groups listed here:
# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
Group: Qt/Qt

View file

@ -50,6 +50,21 @@ 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::isStickerSetInstalled(const QString &stickerSetId)
{
return this->installedStickerSetIds.contains(stickerSetId);
}
bool StickerManager::needsReload()
{
return this->reloadNeeded;
@ -95,7 +110,17 @@ void StickerManager::handleStickerSetsReceived(const QVariantList &stickerSets)
QListIterator<QVariant> stickerSetsIterator(stickerSets);
while (stickerSetsIterator.hasNext()) {
QVariantMap newStickerSet = stickerSetsIterator.next().toMap();
this->stickerSets.insert(newStickerSet.value("id").toString(), newStickerSet);
QString newSetId = newStickerSet.value("id").toString();
bool isInstalled = newStickerSet.value("is_installed").toBool();
if (isInstalled && !this->installedStickerSetIds.contains(newSetId)) {
this->installedStickerSetIds.append(newSetId);
}
if (!isInstalled && this->installedStickerSetIds.contains(newSetId)) {
this->installedStickerSetIds.removeAll(newSetId);
}
if (!this->stickerSets.contains(newSetId)) {
this->stickerSets.insert(newSetId, newStickerSet);
}
}
this->installedStickerSets.clear();
@ -104,19 +129,26 @@ 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->stickerSets.contains(stickerSetId)) {
this->installedStickerSets.append(this->stickerSets.value(stickerSetId));
this->stickerSetMap.insert(stickerSetId, i);
i++;
}
}
emit stickerSetsReceived();
}
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<QVariant> stickerIterator(stickerList);
while (stickerIterator.hasNext()) {

View file

@ -35,10 +35,14 @@ 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 isStickerSetInstalled(const QString &stickerSetId);
Q_INVOKABLE bool needsReload();
Q_INVOKABLE void setNeedsReload(const bool &reloadNeeded);
signals:
void stickerSetsReceived();
private slots:

View file

@ -1326,6 +1326,19 @@ 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(_EXTRA, isInstalled ? "installStickerSet" : "removeStickerSet");
requestObject.insert("set_id", stickerSetId);
requestObject.insert("is_installed", isInstalled);
this->sendRequest(requestObject);
}
void TDLibWrapper::searchEmoji(const QString &queryString)
{
LOG("Searching emoji" << queryString);

View file

@ -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);

View file

@ -1666,8 +1666,23 @@
<translation>Kürzlich verwendet</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Lade Sticker...</translation>
<source>Removing sticker set</source>
<translation>Entferne Sticker-Set</translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation>Sticker-Set erfolgreich entfernt!</translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation>Sticker-Set erfolgreich installiert!</translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation>Sticker-Set erfolgreich entfernt!</translation>
</message>
</context>
<context>

View file

@ -1668,8 +1668,23 @@ messages</numerusform>
<translation>Recently used</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Loading stickers...</translation>
<source>Removing sticker set</source>
<translation>Removing sticker set</translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation>Sticker set successfully removed!</translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation>Sticker set successfully installed!</translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation>Sticker set successfully removed!</translation>
</message>
</context>
<context>

View file

@ -1666,8 +1666,23 @@
<translation>Usado recientemente</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Cargando pegatinas...</translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -1667,8 +1667,23 @@
<translation>Viimeksi käytetty</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Ladataan tarroja...</translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -1639,7 +1639,22 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Loading stickers...</source>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>

View file

@ -1666,8 +1666,23 @@
<translation>Usati di recente</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Carica sticker...</translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -1693,8 +1693,23 @@
<translation>Ostatnio użyty</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Ładowanie naklejek...</translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -1696,8 +1696,23 @@
<translation>Недавно использованные</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Загрузка стикеров...</translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -1693,8 +1693,23 @@
<translation>Nedávno použité</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Načítanie nálepiek...</translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -1666,8 +1666,23 @@
<translation>Nyligen använt</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Läser in dekaler...</translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -1640,8 +1640,23 @@
<translation>使</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation></translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -1666,8 +1666,23 @@
<translation>Recently used</translation>
</message>
<message>
<source>Loading stickers...</source>
<translation>Loading stickers...</translation>
<source>Removing sticker set</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StickerSetOverlay</name>
<message>
<source>Sticker set successfully installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sticker set successfully removed!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>