tdesktop/Telegram/SourceFiles/stickers/stickers.cpp

231 lines
6.8 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop 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.
It 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.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "stickers.h"
#include "boxes/stickers_box.h"
#include "boxes/confirmbox.h"
#include "lang.h"
#include "apiwrap.h"
#include "localstorage.h"
#include "mainwidget.h"
namespace Stickers {
namespace {
constexpr int kReadFeaturedSetsTimeoutMs = 1000;
internal::FeaturedReader *FeaturedReaderInstance = nullptr;
} // namespace
void applyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
auto &v = d.vsets.c_vector().v;
auto &order = Global::RefStickerSetsOrder();
Stickers::Order archived;
archived.reserve(v.size());
QMap<uint64, uint64> setsToRequest;
for_const (auto &stickerSet, v) {
const MTPDstickerSet *setData = nullptr;
switch (stickerSet.type()) {
case mtpc_stickerSetCovered: {
auto &d = stickerSet.c_stickerSetCovered();
if (d.vset.type() == mtpc_stickerSet) {
setData = &d.vset.c_stickerSet();
}
} break;
case mtpc_stickerSetMultiCovered: {
auto &d = stickerSet.c_stickerSetMultiCovered();
if (d.vset.type() == mtpc_stickerSet) {
setData = &d.vset.c_stickerSet();
}
} break;
}
if (setData) {
auto set = Stickers::feedSet(*setData);
if (set->stickers.isEmpty()) {
setsToRequest.insert(set->id, set->access);
}
auto index = order.indexOf(set->id);
if (index >= 0) {
order.removeAt(index);
}
archived.push_back(set->id);
}
}
if (!setsToRequest.isEmpty()) {
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
App::api()->scheduleStickerSetRequest(i.key(), i.value());
}
App::api()->requestStickerSets();
}
Local::writeInstalledStickers();
Local::writeArchivedStickers();
Ui::show(Box<StickersBox>(archived), KeepOtherLayers);
emit App::main()->stickersUpdated();
}
// For testing: Just apply random subset or your sticker sets as archived.
bool applyArchivedResultFake() {
if (rand_value<uint32>() % 128 < 64) {
return false;
}
auto sets = QVector<MTPStickerSetCovered>();
for (auto &set : Global::RefStickerSets()) {
if ((set.flags & MTPDstickerSet::Flag::f_installed) && !(set.flags & MTPDstickerSet_ClientFlag::f_special)) {
if (rand_value<uint32>() % 128 < 64) {
auto data = MTP_stickerSet(MTP_flags(set.flags | MTPDstickerSet::Flag::f_archived), MTP_long(set.id), MTP_long(set.access), MTP_string(set.title), MTP_string(set.shortName), MTP_int(set.count), MTP_int(set.hash));
sets.push_back(MTP_stickerSetCovered(data, MTP_documentEmpty(MTP_long(0))));
}
}
}
if (sets.size() > 3) sets = sets.mid(0, 3);
auto fakeResult = MTP_messages_stickerSetInstallResultArchive(MTP_vector<MTPStickerSetCovered>(sets));
applyArchivedResult(fakeResult.c_messages_stickerSetInstallResultArchive());
return true;
}
void installLocally(uint64 setId) {
auto &sets = Global::RefStickerSets();
auto it = sets.find(setId);
if (it == sets.end()) {
return;
}
auto flags = it->flags;
it->flags &= ~(MTPDstickerSet::Flag::f_archived | MTPDstickerSet_ClientFlag::f_unread);
it->flags |= MTPDstickerSet::Flag::f_installed;
auto changedFlags = flags ^ it->flags;
auto &order = Global::RefStickerSetsOrder();
int insertAtIndex = 0, currentIndex = order.indexOf(setId);
if (currentIndex != insertAtIndex) {
if (currentIndex > 0) {
order.removeAt(currentIndex);
}
order.insert(insertAtIndex, setId);
}
auto custom = sets.find(Stickers::CustomSetId);
if (custom != sets.cend()) {
for_const (auto sticker, it->stickers) {
int removeIndex = custom->stickers.indexOf(sticker);
if (removeIndex >= 0) custom->stickers.removeAt(removeIndex);
}
if (custom->stickers.isEmpty()) {
sets.erase(custom);
}
}
Local::writeInstalledStickers();
if (changedFlags & MTPDstickerSet_ClientFlag::f_unread) Local::writeFeaturedStickers();
if (changedFlags & MTPDstickerSet::Flag::f_archived) {
auto index = Global::RefArchivedStickerSetsOrder().indexOf(setId);
if (index >= 0) {
Global::RefArchivedStickerSetsOrder().removeAt(index);
Local::writeArchivedStickers();
}
}
emit App::main()->stickersUpdated();
}
void undoInstallLocally(uint64 setId) {
auto &sets = Global::RefStickerSets();
auto it = sets.find(setId);
if (it == sets.end()) {
return;
}
it->flags &= ~MTPDstickerSet::Flag::f_installed;
auto &order = Global::RefStickerSetsOrder();
int currentIndex = order.indexOf(setId);
if (currentIndex >= 0) {
order.removeAt(currentIndex);
}
Local::writeInstalledStickers();
emit App::main()->stickersUpdated();
Ui::show(Box<InformBox>(lang(lng_stickers_not_found)), KeepOtherLayers);
}
void markFeaturedAsRead(uint64 setId) {
if (!FeaturedReaderInstance) {
if (auto main = App::main()) {
FeaturedReaderInstance = new internal::FeaturedReader(main);
} else {
return;
}
}
FeaturedReaderInstance->scheduleRead(setId);
}
namespace internal {
void readFeaturedDone() {
Local::writeFeaturedStickers();
if (App::main()) {
emit App::main()->stickersUpdated();
}
}
FeaturedReader::FeaturedReader(QObject *parent) : QObject(parent)
, _timer(new QTimer(this)) {
_timer->setSingleShot(true);
connect(_timer, SIGNAL(timeout()), this, SLOT(onReadSets()));
}
void FeaturedReader::scheduleRead(uint64 setId) {
if (!_setIds.contains(setId)) {
_setIds.insert(setId);
_timer->start(kReadFeaturedSetsTimeoutMs);
}
}
void FeaturedReader::onReadSets() {
auto &sets = Global::RefStickerSets();
auto count = Global::FeaturedStickerSetsUnreadCount();
QVector<MTPlong> wrappedIds;
wrappedIds.reserve(_setIds.size());
for_const (auto setId, _setIds) {
auto it = sets.find(setId);
if (it != sets.cend()) {
it->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
wrappedIds.append(MTP_long(setId));
if (count) {
--count;
}
}
}
_setIds.clear();
if (!wrappedIds.empty()) {
MTP::send(MTPmessages_ReadFeaturedStickers(MTP_vector<MTPlong>(wrappedIds)), rpcDone(&readFeaturedDone));
if (Global::FeaturedStickerSetsUnreadCount() != count) {
Global::SetFeaturedStickerSetsUnreadCount(count);
Global::RefFeaturedStickerSetsUnreadCountChanged().notify();
}
}
}
} // namespace internal
} // namespace Stickers