mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-02 12:42:16 +00:00
Change Stickers::Set from value to object type.
This commit is contained in:
parent
897e432f40
commit
803593cd8d
@ -301,6 +301,8 @@ PRIVATE
|
||||
chat_helpers/stickers_dice_pack.h
|
||||
chat_helpers/stickers_list_widget.cpp
|
||||
chat_helpers/stickers_list_widget.h
|
||||
chat_helpers/stickers_set.cpp
|
||||
chat_helpers/stickers_set.h
|
||||
chat_helpers/tabbed_panel.cpp
|
||||
chat_helpers/tabbed_panel.h
|
||||
chat_helpers/tabbed_section.cpp
|
||||
|
@ -1890,16 +1890,17 @@ void ApiWrap::saveStickerSets(
|
||||
|
||||
auto it = sets.find(removedSetId);
|
||||
if (it != sets.cend()) {
|
||||
const auto set = it->second.get();
|
||||
for (auto i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
if (set->stickers.indexOf(i->first) >= 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (!(it->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName));
|
||||
if (!(set->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
const auto setId = set->mtpInput();
|
||||
|
||||
auto requestId = request(MTPmessages_UninstallStickerSet(setId)).done([this](const MTPBool &result, mtpRequestId requestId) {
|
||||
stickerSetDisenabled(requestId);
|
||||
@ -1909,60 +1910,69 @@ void ApiWrap::saveStickerSets(
|
||||
|
||||
_stickerSetDisenableRequests.insert(requestId);
|
||||
|
||||
int removeIndex = _session->data().stickerSetsOrder().indexOf(it->id);
|
||||
int removeIndex = _session->data().stickerSetsOrder().indexOf(set->id);
|
||||
if (removeIndex >= 0) _session->data().stickerSetsOrderRef().removeAt(removeIndex);
|
||||
if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured)
|
||||
&& !(it->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
if (!(set->flags & MTPDstickerSet_ClientFlag::f_featured)
|
||||
&& !(set->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
sets.erase(it);
|
||||
} else {
|
||||
if (it->flags & MTPDstickerSet::Flag::f_archived) {
|
||||
if (set->flags & MTPDstickerSet::Flag::f_archived) {
|
||||
writeArchived = true;
|
||||
}
|
||||
it->flags &= ~(MTPDstickerSet::Flag::f_installed_date | MTPDstickerSet::Flag::f_archived);
|
||||
it->installDate = TimeId(0);
|
||||
set->flags &= ~(MTPDstickerSet::Flag::f_installed_date | MTPDstickerSet::Flag::f_archived);
|
||||
set->installDate = TimeId(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all installed flags, set only for sets from order.
|
||||
for (auto &set : sets) {
|
||||
if (!(set.flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
set.flags &= ~MTPDstickerSet::Flag::f_installed_date;
|
||||
for (auto &[id, set] : sets) {
|
||||
if (!(set->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
|
||||
}
|
||||
}
|
||||
|
||||
auto &order = _session->data().stickerSetsOrderRef();
|
||||
order.clear();
|
||||
for_const (auto setId, _stickersOrder) {
|
||||
for (const auto setId : std::as_const(_stickersOrder)) {
|
||||
auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
if ((it->flags & MTPDstickerSet::Flag::f_archived) && !localRemoved.contains(it->id)) {
|
||||
MTPInputStickerSet mtpSetId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName));
|
||||
const auto set = it->second.get();
|
||||
if ((set->flags & MTPDstickerSet::Flag::f_archived) && !localRemoved.contains(set->id)) {
|
||||
const auto mtpSetId = set->mtpInput();
|
||||
|
||||
auto requestId = request(MTPmessages_InstallStickerSet(mtpSetId, MTP_boolFalse())).done([this](const MTPmessages_StickerSetInstallResult &result, mtpRequestId requestId) {
|
||||
const auto requestId = request(MTPmessages_InstallStickerSet(
|
||||
mtpSetId,
|
||||
MTP_boolFalse()
|
||||
)).done([=](
|
||||
const MTPmessages_StickerSetInstallResult &result,
|
||||
mtpRequestId requestId) {
|
||||
stickerSetDisenabled(requestId);
|
||||
}).fail([this](const RPCError &error, mtpRequestId requestId) {
|
||||
}).fail([=](
|
||||
const RPCError &error,
|
||||
mtpRequestId requestId) {
|
||||
stickerSetDisenabled(requestId);
|
||||
}).afterDelay(kSmallDelayMs).send();
|
||||
|
||||
_stickerSetDisenableRequests.insert(requestId);
|
||||
|
||||
it->flags &= ~MTPDstickerSet::Flag::f_archived;
|
||||
set->flags &= ~MTPDstickerSet::Flag::f_archived;
|
||||
writeArchived = true;
|
||||
}
|
||||
order.push_back(setId);
|
||||
it->flags |= MTPDstickerSet::Flag::f_installed_date;
|
||||
if (!it->installDate) {
|
||||
it->installDate = base::unixtime::now();
|
||||
set->flags |= MTPDstickerSet::Flag::f_installed_date;
|
||||
if (!set->installDate) {
|
||||
set->installDate = base::unixtime::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = sets.begin(); it != sets.cend();) {
|
||||
if ((it->flags & MTPDstickerSet_ClientFlag::f_featured)
|
||||
|| (it->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
|| (it->flags & MTPDstickerSet::Flag::f_archived)
|
||||
|| (it->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
const auto set = it->second.get();
|
||||
if ((set->flags & MTPDstickerSet_ClientFlag::f_featured)
|
||||
|| (set->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
|| (set->flags & MTPDstickerSet::Flag::f_archived)
|
||||
|| (set->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
++it;
|
||||
} else {
|
||||
it = sets.erase(it);
|
||||
@ -3341,7 +3351,7 @@ void ApiWrap::readFeaturedSets() {
|
||||
for (auto setId : _featuredSetsRead) {
|
||||
auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
it->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
|
||||
it->second->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
|
||||
wrappedIds.append(MTP_long(setId));
|
||||
if (count) {
|
||||
--count;
|
||||
|
@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/flat_map.h"
|
||||
#include "base/flat_set.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "chat_helpers/stickers_set.h"
|
||||
#include "data/data_messages.h"
|
||||
|
||||
class TaskQueue;
|
||||
|
@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "mtproto/facade.h"
|
||||
#include "app.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/image/image_location_factory.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "lottie/lottie_multi_player.h"
|
||||
@ -115,7 +116,7 @@ private:
|
||||
int32 _setHash = 0;
|
||||
MTPDstickerSet::Flags _setFlags = 0;
|
||||
TimeId _setInstallDate = TimeId(0);
|
||||
ImagePtr _setThumbnail;
|
||||
ImageWithLocation _setThumbnail;
|
||||
|
||||
MTPInputStickerSet _input;
|
||||
|
||||
@ -299,25 +300,29 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
||||
_setFlags = set.vflags().v;
|
||||
_setInstallDate = set.vinstalled_date().value_or(0);
|
||||
if (const auto thumb = set.vthumb()) {
|
||||
_setThumbnail = Images::Create(set, *thumb);
|
||||
_setThumbnail = Images::FromPhotoSize(
|
||||
&_controller->session(),
|
||||
set,
|
||||
*thumb);
|
||||
} else {
|
||||
_setThumbnail = ImagePtr();
|
||||
_setThumbnail = ImageWithLocation();
|
||||
}
|
||||
auto &sets = _controller->session().data().stickerSetsRef();
|
||||
const auto it = sets.find(_setId);
|
||||
if (it != sets.cend()) {
|
||||
const auto set = it->second.get();
|
||||
using ClientFlag = MTPDstickerSet_ClientFlag;
|
||||
const auto clientFlags = it->flags
|
||||
const auto clientFlags = set->flags
|
||||
& (ClientFlag::f_featured
|
||||
| ClientFlag::f_not_loaded
|
||||
| ClientFlag::f_unread
|
||||
| ClientFlag::f_special);
|
||||
_setFlags |= clientFlags;
|
||||
it->flags = _setFlags;
|
||||
it->installDate = _setInstallDate;
|
||||
it->stickers = _pack;
|
||||
it->emoji = _emoji;
|
||||
it->thumbnail = _setThumbnail;
|
||||
set->flags = _setFlags;
|
||||
set->installDate = _setInstallDate;
|
||||
set->stickers = _pack;
|
||||
set->emoji = _emoji;
|
||||
set->setThumbnail(_setThumbnail);
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -359,9 +364,10 @@ void StickerSetBox::Inner::installDone(
|
||||
_setFlags |= MTPDstickerSet::Flag::f_installed_date;
|
||||
auto it = sets.find(_setId);
|
||||
if (it == sets.cend()) {
|
||||
it = sets.insert(
|
||||
it = sets.emplace(
|
||||
_setId,
|
||||
Stickers::Set(
|
||||
std::make_unique<Stickers::Set>(
|
||||
&_controller->session().data(),
|
||||
_setId,
|
||||
_setAccess,
|
||||
_setTitle,
|
||||
@ -369,14 +375,15 @@ void StickerSetBox::Inner::installDone(
|
||||
_setCount,
|
||||
_setHash,
|
||||
_setFlags,
|
||||
_setInstallDate,
|
||||
_setThumbnail));
|
||||
_setInstallDate)).first;
|
||||
} else {
|
||||
it->flags = _setFlags;
|
||||
it->installDate = _setInstallDate;
|
||||
it->second->flags = _setFlags;
|
||||
it->second->installDate = _setInstallDate;
|
||||
}
|
||||
it->stickers = _pack;
|
||||
it->emoji = _emoji;
|
||||
const auto set = it->second.get();
|
||||
set->setThumbnail(_setThumbnail);
|
||||
set->stickers = _pack;
|
||||
set->emoji = _emoji;
|
||||
|
||||
auto &order = _controller->session().data().stickerSetsOrderRef();
|
||||
int insertAtIndex = 0, currentIndex = order.indexOf(_setId);
|
||||
@ -387,14 +394,15 @@ void StickerSetBox::Inner::installDone(
|
||||
order.insert(insertAtIndex, _setId);
|
||||
}
|
||||
|
||||
auto custom = sets.find(Stickers::CustomSetId);
|
||||
if (custom != sets.cend()) {
|
||||
for_const (auto sticker, _pack) {
|
||||
const auto customIt = sets.find(Stickers::CustomSetId);
|
||||
if (customIt != sets.cend()) {
|
||||
const auto custom = customIt->second.get();
|
||||
for (const auto sticker : std::as_const(_pack)) {
|
||||
int removeIndex = custom->stickers.indexOf(sticker);
|
||||
if (removeIndex >= 0) custom->stickers.removeAt(removeIndex);
|
||||
}
|
||||
if (custom->stickers.isEmpty()) {
|
||||
sets.erase(custom);
|
||||
sets.erase(customIt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -669,10 +677,11 @@ bool StickerSetBox::Inner::notInstalled() const {
|
||||
if (!_loaded) {
|
||||
return false;
|
||||
}
|
||||
const auto it = _controller->session().data().stickerSets().constFind(_setId);
|
||||
if ((it == _controller->session().data().stickerSets().cend())
|
||||
|| !(it->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
|| (it->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
const auto &sets = _controller->session().data().stickerSets();
|
||||
const auto it = sets.find(_setId);
|
||||
if ((it == sets.cend())
|
||||
|| !(it->second->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
|| (it->second->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
return !_pack.empty();
|
||||
}
|
||||
return false;
|
||||
|
@ -374,17 +374,24 @@ void StickersBox::loadMoreArchived() {
|
||||
}
|
||||
|
||||
uint64 lastId = 0;
|
||||
for (auto setIt = _session->data().archivedStickerSetsOrder().cend(), e = _session->data().archivedStickerSetsOrder().cbegin(); setIt != e;) {
|
||||
const auto &order = _session->data().archivedStickerSetsOrder();
|
||||
const auto &sets = _session->data().stickerSets();
|
||||
for (auto setIt = order.cend(), e = order.cbegin(); setIt != e;) {
|
||||
--setIt;
|
||||
auto it = _session->data().stickerSets().constFind(*setIt);
|
||||
if (it != _session->data().stickerSets().cend()) {
|
||||
if (it->flags & MTPDstickerSet::Flag::f_archived) {
|
||||
lastId = it->id;
|
||||
auto it = sets.find(*setIt);
|
||||
if (it != sets.cend()) {
|
||||
if (it->second->flags & MTPDstickerSet::Flag::f_archived) {
|
||||
lastId = it->second->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(0), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId));
|
||||
_archivedRequestId = MTP::send(
|
||||
MTPmessages_GetArchivedStickers(
|
||||
MTP_flags(0),
|
||||
MTP_long(lastId),
|
||||
MTP_int(kArchivedLimitPerPage)),
|
||||
rpcDone(&StickersBox::getArchivedDone, lastId));
|
||||
}
|
||||
|
||||
void StickersBox::paintEvent(QPaintEvent *e) {
|
||||
@ -497,6 +504,7 @@ void StickersBox::installSet(uint64 setId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto set = it->second.get();
|
||||
if (_localRemoved.contains(setId)) {
|
||||
_localRemoved.removeOne(setId);
|
||||
if (_installed.widget()) _installed.widget()->setRemovedSets(_localRemoved);
|
||||
@ -504,11 +512,11 @@ void StickersBox::installSet(uint64 setId) {
|
||||
if (_archived.widget()) _archived.widget()->setRemovedSets(_localRemoved);
|
||||
if (_attached.widget()) _attached.widget()->setRemovedSets(_localRemoved);
|
||||
}
|
||||
if (!(it->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
|| (it->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
if (!(set->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
|| (set->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
MTP::send(
|
||||
MTPmessages_InstallStickerSet(
|
||||
Stickers::inputSetId(*it),
|
||||
set->mtpInput(),
|
||||
MTP_boolFalse()),
|
||||
rpcDone(&StickersBox::installDone),
|
||||
rpcFail(&StickersBox::installFail, setId));
|
||||
@ -551,12 +559,14 @@ void StickersBox::requestArchivedSets() {
|
||||
preloadArchivedSets();
|
||||
}
|
||||
|
||||
auto &sets = _session->data().stickerSets();
|
||||
for_const (auto setId, _session->data().archivedStickerSetsOrder()) {
|
||||
auto it = sets.constFind(setId);
|
||||
const auto &sets = _session->data().stickerSets();
|
||||
const auto &order = _session->data().archivedStickerSetsOrder();
|
||||
for (const auto setId : order) {
|
||||
auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
if (it->stickers.isEmpty() && (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
_session->api().scheduleStickerSetRequest(setId, it->access);
|
||||
const auto set = it->second.get();
|
||||
if (set->stickers.isEmpty() && (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
_session->api().scheduleStickerSetRequest(setId, set->access);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -658,6 +668,10 @@ StickersBox::Inner::Row::Row(
|
||||
|
||||
StickersBox::Inner::Row::~Row() = default;
|
||||
|
||||
bool StickersBox::Inner::Row::isRecentSet() const {
|
||||
return (id == Stickers::CloudRecentSetId);
|
||||
}
|
||||
|
||||
StickersBox::Inner::Inner(
|
||||
QWidget *parent,
|
||||
not_null<Main::Session*> session,
|
||||
@ -1298,7 +1312,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (!row.isRecentSet()) {
|
||||
auto it = sets.find(row.id);
|
||||
if (it != sets.cend()) {
|
||||
return &*it;
|
||||
return it->second.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
@ -1309,7 +1323,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
Ui::show(
|
||||
Box<StickerSetBox>(
|
||||
App::wnd()->sessionController(),
|
||||
Stickers::inputSetId(*set)),
|
||||
set->mtpInput()),
|
||||
Ui::LayerOption::KeepOther);
|
||||
}
|
||||
};
|
||||
@ -1470,8 +1484,9 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
|
||||
auto text = _megagroupSetField->getLastText().trimmed();
|
||||
if (text.isEmpty()) {
|
||||
if (_megagroupSelectedSet) {
|
||||
auto it = _session->data().stickerSets().constFind(_megagroupSelectedSet->id);
|
||||
if (it != _session->data().stickerSets().cend() && !it->shortName.isEmpty()) {
|
||||
const auto &sets = _session->data().stickerSets();
|
||||
const auto it = sets.find(_megagroupSelectedSet->id);
|
||||
if (it != sets.cend() && !it->second->shortName.isEmpty()) {
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
|
||||
}
|
||||
}
|
||||
@ -1481,7 +1496,9 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
|
||||
)).done([=](const MTPmessages_StickerSet &result) {
|
||||
_megagroupSetRequestId = 0;
|
||||
auto set = Stickers::FeedSetFull(result);
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetID(MTP_long(set->id), MTP_long(set->access)));
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetID(
|
||||
MTP_long(set->id),
|
||||
MTP_long(set->access)));
|
||||
}).fail([=](const RPCError &error) {
|
||||
_megagroupSetRequestId = 0;
|
||||
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
|
||||
@ -1503,31 +1520,35 @@ void StickersBox::Inner::rebuildMegagroupSet() {
|
||||
_megagroupSelectedShadow.destroy();
|
||||
return;
|
||||
}
|
||||
auto &set = _megagroupSetInput.c_inputStickerSetID();
|
||||
auto setId = set.vid().v;
|
||||
auto &inputId = _megagroupSetInput.c_inputStickerSetID();
|
||||
auto setId = inputId.vid().v;
|
||||
auto &sets = _session->data().stickerSets();
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
_session->api().scheduleStickerSetRequest(set.vid().v, set.vaccess_hash().v);
|
||||
if (it == sets.cend()
|
||||
|| (it->second->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
_session->api().scheduleStickerSetRequest(
|
||||
inputId.vid().v,
|
||||
inputId.vaccess_hash().v);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto set = it->second.get();
|
||||
auto maxNameWidth = countMaxNameWidth();
|
||||
auto titleWidth = 0;
|
||||
auto title = fillSetTitle(*it, maxNameWidth, &titleWidth);
|
||||
auto count = fillSetCount(*it);
|
||||
auto title = fillSetTitle(*set, maxNameWidth, &titleWidth);
|
||||
auto count = fillSetCount(*set);
|
||||
auto thumbnail = ImagePtr();
|
||||
auto sticker = (DocumentData*)nullptr;
|
||||
auto pixw = 0, pixh = 0;
|
||||
fillSetCover(*it, &thumbnail, &sticker, &pixw, &pixh);
|
||||
fillSetCover(*set, &thumbnail, &sticker, &pixw, &pixh);
|
||||
auto installed = true, official = false, unread = false, archived = false, removed = false;
|
||||
if (!_megagroupSelectedSet || _megagroupSelectedSet->id != it->id) {
|
||||
_megagroupSetField->setText(it->shortName);
|
||||
if (!_megagroupSelectedSet || _megagroupSelectedSet->id != set->id) {
|
||||
_megagroupSetField->setText(set->shortName);
|
||||
_megagroupSetField->finishAnimating();
|
||||
}
|
||||
_megagroupSelectedSet = std::make_unique<Row>(
|
||||
it->id,
|
||||
it->access,
|
||||
set->id,
|
||||
set->access,
|
||||
thumbnail,
|
||||
sticker,
|
||||
count,
|
||||
@ -1565,7 +1586,7 @@ void StickersBox::Inner::rebuild() {
|
||||
auto maxNameWidth = countMaxNameWidth();
|
||||
|
||||
clear();
|
||||
auto &order = ([&]() -> const Stickers::Order & {
|
||||
const auto &order = ([&]() -> const Stickers::Order & {
|
||||
if (_section == Section::Installed) {
|
||||
auto &result = _session->data().stickerSetsOrder();
|
||||
if (_megagroupSet && result.empty()) {
|
||||
@ -1588,21 +1609,23 @@ void StickersBox::Inner::rebuild() {
|
||||
: tr::lng_stickers_group_from_your(tr::now));
|
||||
updateControlsGeometry();
|
||||
} else if (_section == Section::Installed) {
|
||||
auto cloudIt = sets.constFind(Stickers::CloudRecentSetId);
|
||||
if (cloudIt != sets.cend() && !cloudIt->stickers.isEmpty()) {
|
||||
rebuildAppendSet(cloudIt.value(), maxNameWidth);
|
||||
auto cloudIt = sets.find(Stickers::CloudRecentSetId);
|
||||
if (cloudIt != sets.cend() && !cloudIt->second->stickers.isEmpty()) {
|
||||
rebuildAppendSet(*cloudIt->second, maxNameWidth);
|
||||
}
|
||||
}
|
||||
for_const (auto setId, order) {
|
||||
auto it = sets.constFind(setId);
|
||||
for (const auto setId : order) {
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rebuildAppendSet(it.value(), maxNameWidth);
|
||||
const auto set = it->second.get();
|
||||
rebuildAppendSet(*set, maxNameWidth);
|
||||
|
||||
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
_session->api().scheduleStickerSetRequest(it->id, it->access);
|
||||
if (set->stickers.isEmpty()
|
||||
|| (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
_session->api().scheduleStickerSetRequest(set->id, set->access);
|
||||
}
|
||||
}
|
||||
_session->api().requestStickerSets();
|
||||
@ -1632,16 +1655,16 @@ void StickersBox::Inner::updateRows() {
|
||||
int maxNameWidth = countMaxNameWidth();
|
||||
auto &sets = _session->data().stickerSets();
|
||||
for (const auto &row : _rows) {
|
||||
const auto it = sets.constFind(row->id);
|
||||
const auto it = sets.find(row->id);
|
||||
if (it == sets.cend()) {
|
||||
continue;
|
||||
}
|
||||
const auto &set = it.value();
|
||||
const auto set = it->second.get();
|
||||
if (!row->sticker) {
|
||||
auto thumbnail = ImagePtr();
|
||||
auto sticker = (DocumentData*)nullptr;
|
||||
auto pixw = 0, pixh = 0;
|
||||
fillSetCover(set, &thumbnail, &sticker, &pixw, &pixh);
|
||||
fillSetCover(*set, &thumbnail, &sticker, &pixw, &pixh);
|
||||
if (sticker) {
|
||||
if ((row->thumbnail.get() != thumbnail.get())
|
||||
|| (!thumbnail && row->sticker != sticker)) {
|
||||
@ -1659,7 +1682,7 @@ void StickersBox::Inner::updateRows() {
|
||||
if (!row->isRecentSet()) {
|
||||
auto wasInstalled = row->installed;
|
||||
auto wasArchived = row->archived;
|
||||
fillSetFlags(set, &row->installed, &row->official, &row->unread, &row->archived);
|
||||
fillSetFlags(*set, &row->installed, &row->official, &row->unread, &row->archived);
|
||||
if (_section == Section::Installed) {
|
||||
row->archived = false;
|
||||
}
|
||||
@ -1667,8 +1690,8 @@ void StickersBox::Inner::updateRows() {
|
||||
row->ripple.reset();
|
||||
}
|
||||
}
|
||||
row->title = fillSetTitle(set, maxNameWidth, &row->titleWidth);
|
||||
row->count = fillSetCount(set);
|
||||
row->title = fillSetTitle(*set, maxNameWidth, &row->titleWidth);
|
||||
row->count = fillSetCount(*set);
|
||||
}
|
||||
update();
|
||||
}
|
||||
@ -1739,7 +1762,7 @@ void StickersBox::Inner::rebuildAppendSet(const Stickers::Set &set, int maxNameW
|
||||
}
|
||||
|
||||
void StickersBox::Inner::fillSetCover(const Stickers::Set &set, ImagePtr *thumbnail, DocumentData **outSticker, int *outWidth, int *outHeight) const {
|
||||
*thumbnail = set.thumbnail;
|
||||
//*thumbnail = set.thumbnail; // #TODO optimize stickers
|
||||
if (set.stickers.isEmpty()) {
|
||||
*outSticker = nullptr;
|
||||
*outWidth = *outHeight = 0;
|
||||
@ -1747,8 +1770,10 @@ void StickersBox::Inner::fillSetCover(const Stickers::Set &set, ImagePtr *thumbn
|
||||
}
|
||||
auto sticker = *outSticker = set.stickers.front();
|
||||
|
||||
const auto size = set.thumbnail
|
||||
? set.thumbnail->size()
|
||||
const auto size = set.hasThumbnail()
|
||||
? QSize(
|
||||
set.thumbnailLocation().width(),
|
||||
set.thumbnailLocation().height())
|
||||
: sticker->hasThumbnail()
|
||||
? QSize(
|
||||
sticker->thumbnailLocation().width(),
|
||||
@ -1775,11 +1800,13 @@ void StickersBox::Inner::fillSetCover(const Stickers::Set &set, ImagePtr *thumbn
|
||||
int StickersBox::Inner::fillSetCount(const Stickers::Set &set) const {
|
||||
int result = set.stickers.isEmpty() ? set.count : set.stickers.size(), added = 0;
|
||||
if (set.id == Stickers::CloudRecentSetId) {
|
||||
auto customIt = _session->data().stickerSets().constFind(Stickers::CustomSetId);
|
||||
if (customIt != _session->data().stickerSets().cend()) {
|
||||
added = customIt->stickers.size();
|
||||
for_const (auto &sticker, Stickers::GetRecentPack()) {
|
||||
if (customIt->stickers.indexOf(sticker.first) < 0) {
|
||||
const auto &sets = _session->data().stickerSets();
|
||||
auto customIt = sets.find(Stickers::CustomSetId);
|
||||
if (customIt != sets.cend()) {
|
||||
added = customIt->second->stickers.size();
|
||||
const auto &recent = Stickers::GetRecentPack();
|
||||
for (const auto &sticker : recent) {
|
||||
if (customIt->second->stickers.indexOf(sticker.first) < 0) {
|
||||
++added;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "base/timer.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "chat_helpers/stickers_set.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/special_fields.h"
|
||||
|
||||
@ -33,6 +33,14 @@ namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Data {
|
||||
class DocumentMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Lottie {
|
||||
class SinglePlayer;
|
||||
} // namespace Lottie
|
||||
|
||||
class StickersBox final
|
||||
: public Ui::BoxContent
|
||||
, public RPCSender
|
||||
@ -235,9 +243,7 @@ private:
|
||||
int32 pixh);
|
||||
~Row();
|
||||
|
||||
bool isRecentSet() const {
|
||||
return (id == Stickers::CloudRecentSetId);
|
||||
}
|
||||
bool isRecentSet() const;
|
||||
|
||||
uint64 id = 0;
|
||||
uint64 accessHash = 0;
|
||||
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "mtproto/facade.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
|
||||
|
@ -5,12 +5,13 @@ the official desktop application for the Telegram messaging service.
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "stickers.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "chat_helpers/stickers_set.h"
|
||||
#include "boxes/stickers_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
@ -21,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "mainwindow.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "ui/image/image_location_factory.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "lottie/lottie_single_player.h"
|
||||
#include "lottie/lottie_multi_player.h"
|
||||
@ -41,7 +43,7 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
|
||||
Order archived;
|
||||
archived.reserve(v.size());
|
||||
QMap<uint64, uint64> setsToRequest;
|
||||
for_const (auto &stickerSet, v) {
|
||||
for (const auto &stickerSet : v) {
|
||||
const MTPDstickerSet *setData = nullptr;
|
||||
switch (stickerSet.type()) {
|
||||
case mtpc_stickerSetCovered: {
|
||||
@ -91,21 +93,22 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
|
||||
// For testing: Just apply random subset or your sticker sets as archived.
|
||||
bool ApplyArchivedResultFake() {
|
||||
auto sets = QVector<MTPStickerSetCovered>();
|
||||
for (auto &set : Auth().data().stickerSetsRef()) {
|
||||
if ((set.flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !(set.flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
for (const auto &[id, set] : Auth().data().stickerSetsRef()) {
|
||||
const auto raw = set.get();
|
||||
if ((raw->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !(raw->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
if (rand_value<uint32>() % 128 < 64) {
|
||||
const auto data = MTP_stickerSet(
|
||||
MTP_flags(set.flags | MTPDstickerSet::Flag::f_archived),
|
||||
MTP_int(set.installDate),
|
||||
MTP_long(set.id),
|
||||
MTP_long(set.access),
|
||||
MTP_string(set.title),
|
||||
MTP_string(set.shortName),
|
||||
MTP_flags(raw->flags | MTPDstickerSet::Flag::f_archived),
|
||||
MTP_int(raw->installDate),
|
||||
MTP_long(raw->id),
|
||||
MTP_long(raw->access),
|
||||
MTP_string(raw->title),
|
||||
MTP_string(raw->shortName),
|
||||
MTP_photoSizeEmpty(MTP_string()),
|
||||
MTP_int(0),
|
||||
MTP_int(set.count),
|
||||
MTP_int(set.hash));
|
||||
MTP_int(raw->count),
|
||||
MTP_int(raw->hash));
|
||||
sets.push_back(MTP_stickerSetCovered(
|
||||
data,
|
||||
MTP_documentEmpty(MTP_long(0))));
|
||||
@ -128,11 +131,12 @@ void InstallLocally(uint64 setId) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto flags = it->flags;
|
||||
it->flags &= ~(MTPDstickerSet::Flag::f_archived | MTPDstickerSet_ClientFlag::f_unread);
|
||||
it->flags |= MTPDstickerSet::Flag::f_installed_date;
|
||||
it->installDate = base::unixtime::now();
|
||||
auto changedFlags = flags ^ it->flags;
|
||||
const auto set = it->second.get();
|
||||
auto flags = set->flags;
|
||||
set->flags &= ~(MTPDstickerSet::Flag::f_archived | MTPDstickerSet_ClientFlag::f_unread);
|
||||
set->flags |= MTPDstickerSet::Flag::f_installed_date;
|
||||
set->installDate = base::unixtime::now();
|
||||
auto changedFlags = flags ^ set->flags;
|
||||
|
||||
auto &order = Auth().data().stickerSetsOrderRef();
|
||||
int insertAtIndex = 0, currentIndex = order.indexOf(setId);
|
||||
@ -143,14 +147,15 @@ void InstallLocally(uint64 setId) {
|
||||
order.insert(insertAtIndex, setId);
|
||||
}
|
||||
|
||||
auto custom = sets.find(CustomSetId);
|
||||
if (custom != sets.cend()) {
|
||||
for_const (auto sticker, it->stickers) {
|
||||
auto customIt = sets.find(CustomSetId);
|
||||
if (customIt != sets.cend()) {
|
||||
const auto custom = customIt->second.get();
|
||||
for (const auto sticker : std::as_const(set->stickers)) {
|
||||
int removeIndex = custom->stickers.indexOf(sticker);
|
||||
if (removeIndex >= 0) custom->stickers.removeAt(removeIndex);
|
||||
}
|
||||
if (custom->stickers.isEmpty()) {
|
||||
sets.erase(custom);
|
||||
sets.erase(customIt);
|
||||
}
|
||||
}
|
||||
Local::writeInstalledStickers();
|
||||
@ -174,8 +179,9 @@ void UndoInstallLocally(uint64 setId) {
|
||||
return;
|
||||
}
|
||||
|
||||
it->flags &= ~MTPDstickerSet::Flag::f_installed_date;
|
||||
it->installDate = TimeId(0);
|
||||
const auto set = it->second.get();
|
||||
set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
|
||||
set->installDate = TimeId(0);
|
||||
|
||||
auto &order = Auth().data().stickerSetsOrderRef();
|
||||
int currentIndex = order.indexOf(setId);
|
||||
@ -192,11 +198,12 @@ void UndoInstallLocally(uint64 setId) {
|
||||
}
|
||||
|
||||
bool IsFaved(not_null<const DocumentData*> document) {
|
||||
const auto it = Auth().data().stickerSets().constFind(FavedSetId);
|
||||
if (it == Auth().data().stickerSets().cend()) {
|
||||
const auto &sets = Auth().data().stickerSets();
|
||||
const auto it = sets.find(FavedSetId);
|
||||
if (it == sets.cend()) {
|
||||
return false;
|
||||
}
|
||||
for (const auto sticker : it->stickers) {
|
||||
for (const auto sticker : it->second->stickers) {
|
||||
if (sticker == document) {
|
||||
return true;
|
||||
}
|
||||
@ -254,11 +261,14 @@ void MoveFavedToFront(Set &set, int index) {
|
||||
|
||||
void RequestSetToPushFaved(not_null<DocumentData*> document);
|
||||
|
||||
void SetIsFaved(not_null<DocumentData*> document, std::optional<std::vector<not_null<EmojiPtr>>> emojiList = std::nullopt) {
|
||||
auto &sets = Auth().data().stickerSetsRef();
|
||||
void SetIsFaved(
|
||||
not_null<DocumentData*> document,
|
||||
std::optional<std::vector<not_null<EmojiPtr>>> emojiList = std::nullopt) {
|
||||
auto &sets = document->owner().stickerSetsRef();
|
||||
auto it = sets.find(FavedSetId);
|
||||
if (it == sets.end()) {
|
||||
it = sets.insert(FavedSetId, Set(
|
||||
it = sets.emplace(FavedSetId, std::make_unique<Set>(
|
||||
&document->owner(),
|
||||
FavedSetId,
|
||||
uint64(0),
|
||||
Lang::Hard::FavedSetTitle(),
|
||||
@ -266,19 +276,19 @@ void SetIsFaved(not_null<DocumentData*> document, std::optional<std::vector<not_
|
||||
0, // count
|
||||
0, // hash
|
||||
MTPDstickerSet_ClientFlag::f_special | 0,
|
||||
TimeId(0),
|
||||
ImagePtr()));
|
||||
TimeId(0))).first;
|
||||
}
|
||||
auto index = it->stickers.indexOf(document);
|
||||
const auto set = it->second.get();
|
||||
auto index = set->stickers.indexOf(document);
|
||||
if (index == 0) {
|
||||
return;
|
||||
}
|
||||
if (index > 0) {
|
||||
MoveFavedToFront(*it, index);
|
||||
MoveFavedToFront(*set, index);
|
||||
} else if (emojiList) {
|
||||
PushFavedToFront(*it, document, *emojiList);
|
||||
PushFavedToFront(*set, document, *emojiList);
|
||||
} else if (auto list = GetEmojiListFromSet(document)) {
|
||||
PushFavedToFront(*it, document, *list);
|
||||
PushFavedToFront(*set, document, *list);
|
||||
} else {
|
||||
RequestSetToPushFaved(document);
|
||||
return;
|
||||
@ -304,9 +314,9 @@ void RequestSetToPushFaved(not_null<DocumentData*> document) {
|
||||
auto list = std::vector<not_null<EmojiPtr>>();
|
||||
auto &d = result.c_messages_stickerSet();
|
||||
list.reserve(d.vpacks().v.size());
|
||||
for_const (auto &mtpPack, d.vpacks().v) {
|
||||
for (const auto &mtpPack : d.vpacks().v) {
|
||||
auto &pack = mtpPack.c_stickerPack();
|
||||
for_const (auto &documentId, pack.vdocuments().v) {
|
||||
for (const auto &documentId : pack.vdocuments().v) {
|
||||
if (documentId.v == document->id) {
|
||||
if (const auto emoji = Ui::Emoji::Find(qs(mtpPack.c_stickerPack().vemoticon()))) {
|
||||
list.emplace_back(emoji);
|
||||
@ -332,23 +342,24 @@ void SetIsNotFaved(not_null<DocumentData*> document) {
|
||||
if (it == sets.end()) {
|
||||
return;
|
||||
}
|
||||
auto index = it->stickers.indexOf(document);
|
||||
const auto set = it->second.get();
|
||||
auto index = set->stickers.indexOf(document);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
it->stickers.removeAt(index);
|
||||
for (auto i = it->emoji.begin(); i != it->emoji.end();) {
|
||||
set->stickers.removeAt(index);
|
||||
for (auto i = set->emoji.begin(); i != set->emoji.end();) {
|
||||
auto index = i->indexOf(document);
|
||||
if (index >= 0) {
|
||||
i->removeAt(index);
|
||||
if (i->empty()) {
|
||||
i = it->emoji.erase(i);
|
||||
i = set->emoji.erase(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (it->stickers.empty()) {
|
||||
if (set->stickers.empty()) {
|
||||
sets.erase(it);
|
||||
}
|
||||
Local::writeFavedStickers();
|
||||
@ -369,14 +380,14 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
|
||||
|
||||
auto &sets = Auth().data().stickerSetsRef();
|
||||
QMap<uint64, uint64> setsToRequest;
|
||||
for (auto &set : sets) {
|
||||
if (!(set.flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
for (auto &[id, set] : sets) {
|
||||
if (!(set->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
// Mark for removing.
|
||||
set.flags &= ~MTPDstickerSet::Flag::f_installed_date;
|
||||
set.installDate = 0;
|
||||
set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
|
||||
set->installDate = 0;
|
||||
}
|
||||
}
|
||||
for_const (auto &setData, data) {
|
||||
for (const auto &setData : data) {
|
||||
if (setData.type() == mtpc_stickerSet) {
|
||||
auto set = FeedSet(setData.c_stickerSet());
|
||||
if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) {
|
||||
@ -390,13 +401,14 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
|
||||
auto writeRecent = false;
|
||||
auto &recent = GetRecentPack();
|
||||
for (auto it = sets.begin(), e = sets.end(); it != e;) {
|
||||
bool installed = (it->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
|
||||
bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special);
|
||||
bool archived = (it->flags & MTPDstickerSet::Flag::f_archived);
|
||||
const auto set = it->second.get();
|
||||
bool installed = (set->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
bool featured = (set->flags & MTPDstickerSet_ClientFlag::f_featured);
|
||||
bool special = (set->flags & MTPDstickerSet_ClientFlag::f_special);
|
||||
bool archived = (set->flags & MTPDstickerSet::Flag::f_archived);
|
||||
if (!installed) { // remove not mine sets from recent stickers
|
||||
for (auto i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
if (set->stickers.indexOf(i->first) >= 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
@ -437,7 +449,7 @@ void SetPackAndEmoji(
|
||||
set.stickers = std::move(pack);
|
||||
set.dates = std::move(dates);
|
||||
set.emoji.clear();
|
||||
for_const (auto &mtpPack, packs) {
|
||||
for (const auto &mtpPack : packs) {
|
||||
Assert(mtpPack.type() == mtpc_stickerPack);
|
||||
auto &pack = mtpPack.c_stickerPack();
|
||||
if (auto emoji = Ui::Emoji::Find(qs(pack.vemoticon()))) {
|
||||
@ -473,7 +485,8 @@ void SpecialSetReceived(
|
||||
}
|
||||
} else {
|
||||
if (it == sets.cend()) {
|
||||
it = sets.insert(setId, Set(
|
||||
it = sets.emplace(setId, std::make_unique<Set>(
|
||||
&Auth().data(),
|
||||
setId,
|
||||
uint64(0),
|
||||
setTitle,
|
||||
@ -481,19 +494,19 @@ void SpecialSetReceived(
|
||||
0, // count
|
||||
0, // hash
|
||||
MTPDstickerSet_ClientFlag::f_special | 0,
|
||||
TimeId(0),
|
||||
ImagePtr()));
|
||||
TimeId(0))).first;
|
||||
} else {
|
||||
it->title = setTitle;
|
||||
it->second->title = setTitle;
|
||||
}
|
||||
it->hash = hash;
|
||||
const auto set = it->second.get();
|
||||
set->hash = hash;
|
||||
|
||||
auto dates = std::vector<TimeId>();
|
||||
auto dateIndex = 0;
|
||||
auto datesAvailable = (items.size() == usageDates.size())
|
||||
&& (setId == CloudRecentSetId);
|
||||
|
||||
auto custom = sets.find(CustomSetId);
|
||||
auto customIt = sets.find(CustomSetId);
|
||||
auto pack = Pack();
|
||||
pack.reserve(items.size());
|
||||
for (const auto &item : items) {
|
||||
@ -507,22 +520,24 @@ void SpecialSetReceived(
|
||||
if (datesAvailable) {
|
||||
dates.push_back(TimeId(usageDates[dateIndex - 1].v));
|
||||
}
|
||||
if (custom != sets.cend()) {
|
||||
if (customIt != sets.cend()) {
|
||||
const auto custom = customIt->second.get();
|
||||
auto index = custom->stickers.indexOf(document);
|
||||
if (index >= 0) {
|
||||
custom->stickers.removeAt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (custom != sets.cend() && custom->stickers.isEmpty()) {
|
||||
sets.erase(custom);
|
||||
custom = sets.end();
|
||||
if (customIt != sets.cend()
|
||||
&& customIt->second->stickers.isEmpty()) {
|
||||
sets.erase(customIt);
|
||||
customIt = sets.end();
|
||||
}
|
||||
|
||||
auto writeRecent = false;
|
||||
auto &recent = GetRecentPack();
|
||||
for (auto i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
|
||||
if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
@ -533,7 +548,7 @@ void SpecialSetReceived(
|
||||
if (pack.isEmpty()) {
|
||||
sets.erase(it);
|
||||
} else {
|
||||
SetPackAndEmoji(*it, std::move(pack), std::move(dates), packs);
|
||||
SetPackAndEmoji(*set, std::move(pack), std::move(dates), packs);
|
||||
}
|
||||
|
||||
if (writeRecent) {
|
||||
@ -561,7 +576,7 @@ void SpecialSetReceived(
|
||||
}
|
||||
|
||||
void FeaturedSetsReceived(
|
||||
const QVector<MTPStickerSetCovered> &data,
|
||||
const QVector<MTPStickerSetCovered> &list,
|
||||
const QVector<MTPlong> &unread,
|
||||
int32 hash) {
|
||||
auto &&unreadIds = ranges::view::all(
|
||||
@ -579,87 +594,76 @@ void FeaturedSetsReceived(
|
||||
|
||||
auto &sets = Auth().data().stickerSetsRef();
|
||||
auto setsToRequest = base::flat_map<uint64, uint64>();
|
||||
for (auto &set : sets) {
|
||||
for (auto &[id, set] : sets) {
|
||||
// Mark for removing.
|
||||
set.flags &= ~MTPDstickerSet_ClientFlag::f_featured;
|
||||
set->flags &= ~MTPDstickerSet_ClientFlag::f_featured;
|
||||
}
|
||||
for (int i = 0, l = data.size(); i != l; ++i) {
|
||||
auto &setData = data[i];
|
||||
const MTPDstickerSet *set = nullptr;
|
||||
switch (setData.type()) {
|
||||
case mtpc_stickerSetCovered: {
|
||||
auto &d = setData.c_stickerSetCovered();
|
||||
if (d.vset().type() == mtpc_stickerSet) {
|
||||
set = &d.vset().c_stickerSet();
|
||||
for (const auto &entry : list) {
|
||||
const auto data = entry.match([&](const auto &data) {
|
||||
return data.vset().match([&](const MTPDstickerSet &data) {
|
||||
return &data;
|
||||
});
|
||||
});
|
||||
auto it = sets.find(data->vid().v);
|
||||
const auto title = GetSetTitle(*data);
|
||||
const auto installDate = data->vinstalled_date().value_or_empty();
|
||||
const auto thumb = data->vthumb();
|
||||
if (it == sets.cend()) {
|
||||
auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured
|
||||
| MTPDstickerSet_ClientFlag::f_not_loaded;
|
||||
if (unreadMap.contains(data->vid().v)) {
|
||||
setClientFlags |= MTPDstickerSet_ClientFlag::f_unread;
|
||||
}
|
||||
} break;
|
||||
case mtpc_stickerSetMultiCovered: {
|
||||
auto &d = setData.c_stickerSetMultiCovered();
|
||||
if (d.vset().type() == mtpc_stickerSet) {
|
||||
set = &d.vset().c_stickerSet();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
auto it = sets.find(set->vid().v);
|
||||
const auto title = GetSetTitle(*set);
|
||||
const auto installDate = set->vinstalled_date().value_or_empty();
|
||||
const auto thumb = set->vthumb();
|
||||
const auto thumbnail = thumb
|
||||
? Images::Create(*set, *thumb)
|
||||
: ImagePtr();
|
||||
if (it == sets.cend()) {
|
||||
auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured
|
||||
| MTPDstickerSet_ClientFlag::f_not_loaded;
|
||||
if (unreadMap.contains(set->vid().v)) {
|
||||
setClientFlags |= MTPDstickerSet_ClientFlag::f_unread;
|
||||
}
|
||||
it = sets.insert(set->vid().v, Set(
|
||||
set->vid().v,
|
||||
set->vaccess_hash().v,
|
||||
title,
|
||||
qs(set->vshort_name()),
|
||||
set->vcount().v,
|
||||
set->vhash().v,
|
||||
set->vflags().v | setClientFlags,
|
||||
installDate,
|
||||
thumbnail));
|
||||
it = sets.emplace(data->vid().v, std::make_unique<Set>(
|
||||
&Auth().data(),
|
||||
data->vid().v,
|
||||
data->vaccess_hash().v,
|
||||
title,
|
||||
qs(data->vshort_name()),
|
||||
data->vcount().v,
|
||||
data->vhash().v,
|
||||
data->vflags().v | setClientFlags,
|
||||
installDate)).first;
|
||||
it->second->setThumbnail(
|
||||
Images::FromPhotoSize(&Auth(), *data, *thumb));
|
||||
} else {
|
||||
const auto set = it->second.get();
|
||||
set->access = data->vaccess_hash().v;
|
||||
set->title = title;
|
||||
set->shortName = qs(data->vshort_name());
|
||||
auto clientFlags = set->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_special);
|
||||
set->flags = data->vflags().v | clientFlags;
|
||||
set->flags |= MTPDstickerSet_ClientFlag::f_featured;
|
||||
set->installDate = installDate;
|
||||
set->setThumbnail(
|
||||
Images::FromPhotoSize(&Auth(), *data, *thumb));
|
||||
if (unreadMap.contains(set->id)) {
|
||||
set->flags |= MTPDstickerSet_ClientFlag::f_unread;
|
||||
} else {
|
||||
it->access = set->vaccess_hash().v;
|
||||
it->title = title;
|
||||
it->shortName = qs(set->vshort_name());
|
||||
auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_special);
|
||||
it->flags = set->vflags().v | clientFlags;
|
||||
it->flags |= MTPDstickerSet_ClientFlag::f_featured;
|
||||
it->installDate = installDate;
|
||||
it->thumbnail = thumbnail;
|
||||
if (unreadMap.contains(it->id)) {
|
||||
it->flags |= MTPDstickerSet_ClientFlag::f_unread;
|
||||
} else {
|
||||
it->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
|
||||
}
|
||||
if (it->count != set->vcount().v || it->hash != set->vhash().v || it->emoji.isEmpty()) {
|
||||
it->count = set->vcount().v;
|
||||
it->hash = set->vhash().v;
|
||||
it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; // need to request this set
|
||||
}
|
||||
set->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
|
||||
}
|
||||
setsOrder.push_back(set->vid().v);
|
||||
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
setsToRequest.emplace(set->vid().v, set->vaccess_hash().v);
|
||||
if (set->count != data->vcount().v || set->hash != data->vhash().v || set->emoji.isEmpty()) {
|
||||
set->count = data->vcount().v;
|
||||
set->hash = data->vhash().v;
|
||||
set->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; // need to request this set
|
||||
}
|
||||
}
|
||||
setsOrder.push_back(data->vid().v);
|
||||
if (it->second->stickers.isEmpty()
|
||||
|| (it->second->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
|
||||
setsToRequest.emplace(data->vid().v, data->vaccess_hash().v);
|
||||
}
|
||||
}
|
||||
|
||||
auto unreadCount = 0;
|
||||
for (auto it = sets.begin(), e = sets.end(); it != e;) {
|
||||
bool installed = (it->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
|
||||
bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special);
|
||||
bool archived = (it->flags & MTPDstickerSet::Flag::f_archived);
|
||||
const auto set = it->second.get();
|
||||
bool installed = (set->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
bool featured = (set->flags & MTPDstickerSet_ClientFlag::f_featured);
|
||||
bool special = (set->flags & MTPDstickerSet_ClientFlag::f_special);
|
||||
bool archived = (set->flags & MTPDstickerSet::Flag::f_archived);
|
||||
if (installed || featured || special || archived) {
|
||||
if (featured && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
if (featured && (set->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
++unreadCount;
|
||||
}
|
||||
++it;
|
||||
@ -773,7 +777,7 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
|
||||
const auto setId = sticker->set.c_inputStickerSetID().vid().v;
|
||||
const auto setIt = sets.find(setId);
|
||||
if (setIt != sets.end()) {
|
||||
return InstallDateAdjusted(setIt->installDate, document);
|
||||
return InstallDateAdjusted(setIt->second->installDate, document);
|
||||
}
|
||||
}
|
||||
return TimeId(0);
|
||||
@ -781,20 +785,21 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
|
||||
|
||||
auto recentIt = sets.find(Stickers::CloudRecentSetId);
|
||||
if (recentIt != sets.cend()) {
|
||||
auto i = recentIt->emoji.constFind(original);
|
||||
if (i != recentIt->emoji.cend()) {
|
||||
const auto recent = recentIt->second.get();
|
||||
auto i = recent->emoji.constFind(original);
|
||||
if (i != recent->emoji.cend()) {
|
||||
result.reserve(i->size());
|
||||
for (const auto document : *i) {
|
||||
const auto usageDate = [&] {
|
||||
if (recentIt->dates.empty()) {
|
||||
if (recent->dates.empty()) {
|
||||
return TimeId(0);
|
||||
}
|
||||
const auto index = recentIt->stickers.indexOf(document);
|
||||
const auto index = recent->stickers.indexOf(document);
|
||||
if (index < 0) {
|
||||
return TimeId(0);
|
||||
}
|
||||
Assert(index < recentIt->dates.size());
|
||||
return recentIt->dates[index];
|
||||
Assert(index < recent->dates.size());
|
||||
return recent->dates[index];
|
||||
}();
|
||||
const auto date = usageDate
|
||||
? usageDate
|
||||
@ -808,22 +813,23 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
|
||||
const auto addList = [&](const Order &order, MTPDstickerSet::Flag skip) {
|
||||
for (const auto setId : order) {
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend() || (it->flags & skip)) {
|
||||
if (it == sets.cend() || (it->second->flags & skip)) {
|
||||
continue;
|
||||
}
|
||||
if (it->emoji.isEmpty()) {
|
||||
setsToRequest.emplace(it->id, it->access);
|
||||
it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded;
|
||||
const auto set = it->second.get();
|
||||
if (set->emoji.isEmpty()) {
|
||||
setsToRequest.emplace(set->id, set->access);
|
||||
set->flags |= MTPDstickerSet_ClientFlag::f_not_loaded;
|
||||
continue;
|
||||
}
|
||||
auto i = it->emoji.constFind(original);
|
||||
if (i == it->emoji.cend()) {
|
||||
auto i = set->emoji.constFind(original);
|
||||
if (i == set->emoji.cend()) {
|
||||
continue;
|
||||
}
|
||||
const auto my = (it->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
const auto my = (set->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
result.reserve(result.size() + i->size());
|
||||
for (const auto document : *i) {
|
||||
const auto installDate = my ? it->installDate : TimeId(0);
|
||||
const auto installDate = my ? set->installDate : TimeId(0);
|
||||
const auto date = (installDate > 1)
|
||||
? InstallDateAdjusted(installDate, document)
|
||||
: my
|
||||
@ -879,12 +885,13 @@ std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
|
||||
return std::nullopt;
|
||||
}
|
||||
auto &sets = Auth().data().stickerSets();
|
||||
auto it = sets.constFind(inputSet.c_inputStickerSetID().vid().v);
|
||||
auto it = sets.find(inputSet.c_inputStickerSetID().vid().v);
|
||||
if (it == sets.cend()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const auto set = it->second.get();
|
||||
auto result = std::vector<not_null<EmojiPtr>>();
|
||||
for (auto i = it->emoji.cbegin(), e = it->emoji.cend(); i != e; ++i) {
|
||||
for (auto i = set->emoji.cbegin(), e = set->emoji.cend(); i != e; ++i) {
|
||||
if (i->contains(document)) {
|
||||
result.emplace_back(i.key());
|
||||
}
|
||||
@ -897,61 +904,65 @@ std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Set *FeedSet(const MTPDstickerSet &set) {
|
||||
Set *FeedSet(const MTPDstickerSet &data) {
|
||||
auto &sets = Auth().data().stickerSetsRef();
|
||||
auto it = sets.find(set.vid().v);
|
||||
auto title = GetSetTitle(set);
|
||||
auto it = sets.find(data.vid().v);
|
||||
auto title = GetSetTitle(data);
|
||||
auto flags = MTPDstickerSet::Flags(0);
|
||||
const auto thumb = set.vthumb();
|
||||
const auto thumbnail = thumb ? Images::Create(set, *thumb) : ImagePtr();
|
||||
const auto thumb = data.vthumb();
|
||||
if (it == sets.cend()) {
|
||||
it = sets.insert(set.vid().v, Stickers::Set(
|
||||
set.vid().v,
|
||||
set.vaccess_hash().v,
|
||||
it = sets.emplace(data.vid().v, std::make_unique<Set>(
|
||||
&Auth().data(),
|
||||
data.vid().v,
|
||||
data.vaccess_hash().v,
|
||||
title,
|
||||
qs(set.vshort_name()),
|
||||
set.vcount().v,
|
||||
set.vhash().v,
|
||||
set.vflags().v | MTPDstickerSet_ClientFlag::f_not_loaded,
|
||||
set.vinstalled_date().value_or_empty(),
|
||||
thumbnail));
|
||||
qs(data.vshort_name()),
|
||||
data.vcount().v,
|
||||
data.vhash().v,
|
||||
data.vflags().v | MTPDstickerSet_ClientFlag::f_not_loaded,
|
||||
data.vinstalled_date().value_or_empty())).first;
|
||||
it->second->setThumbnail(
|
||||
Images::FromPhotoSize(&Auth(), data, *thumb));
|
||||
} else {
|
||||
it->access = set.vaccess_hash().v;
|
||||
it->title = title;
|
||||
it->shortName = qs(set.vshort_name());
|
||||
flags = it->flags;
|
||||
auto clientFlags = it->flags
|
||||
const auto set = it->second.get();
|
||||
set->access = data.vaccess_hash().v;
|
||||
set->title = title;
|
||||
set->shortName = qs(data.vshort_name());
|
||||
flags = set->flags;
|
||||
auto clientFlags = set->flags
|
||||
& (MTPDstickerSet_ClientFlag::f_featured
|
||||
| MTPDstickerSet_ClientFlag::f_unread
|
||||
| MTPDstickerSet_ClientFlag::f_not_loaded
|
||||
| MTPDstickerSet_ClientFlag::f_special);
|
||||
it->flags = set.vflags().v | clientFlags;
|
||||
const auto installDate = set.vinstalled_date();
|
||||
it->installDate = installDate
|
||||
set->flags = data.vflags().v | clientFlags;
|
||||
const auto installDate = data.vinstalled_date();
|
||||
set->installDate = installDate
|
||||
? (installDate->v ? installDate->v : base::unixtime::now())
|
||||
: TimeId(0);
|
||||
it->thumbnail = thumbnail;
|
||||
if (it->count != set.vcount().v
|
||||
|| it->hash != set.vhash().v
|
||||
|| it->emoji.isEmpty()) {
|
||||
// Need to request this set.
|
||||
it->count = set.vcount().v;
|
||||
it->hash = set.vhash().v;
|
||||
it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded;
|
||||
it->second->setThumbnail(
|
||||
Images::FromPhotoSize(&Auth(), data, *thumb));
|
||||
if (set->count != data.vcount().v
|
||||
|| set->hash != data.vhash().v
|
||||
|| set->emoji.isEmpty()) {
|
||||
// Need to request this data.
|
||||
set->count = data.vcount().v;
|
||||
set->hash = data.vhash().v;
|
||||
set->flags |= MTPDstickerSet_ClientFlag::f_not_loaded;
|
||||
}
|
||||
}
|
||||
auto changedFlags = (flags ^ it->flags);
|
||||
const auto set = it->second.get();
|
||||
auto changedFlags = (flags ^ set->flags);
|
||||
if (changedFlags & MTPDstickerSet::Flag::f_archived) {
|
||||
auto index = Auth().data().archivedStickerSetsOrder().indexOf(it->id);
|
||||
if (it->flags & MTPDstickerSet::Flag::f_archived) {
|
||||
auto index = Auth().data().archivedStickerSetsOrder().indexOf(set->id);
|
||||
if (set->flags & MTPDstickerSet::Flag::f_archived) {
|
||||
if (index < 0) {
|
||||
Auth().data().archivedStickerSetsOrderRef().push_front(it->id);
|
||||
Auth().data().archivedStickerSetsOrderRef().push_front(set->id);
|
||||
}
|
||||
} else if (index >= 0) {
|
||||
Auth().data().archivedStickerSetsOrderRef().removeAt(index);
|
||||
}
|
||||
}
|
||||
return &it.value();
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
Set *FeedSetFull(const MTPmessages_StickerSet &data) {
|
||||
@ -963,14 +974,14 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
|
||||
|
||||
auto &sets = Auth().data().stickerSetsRef();
|
||||
auto it = sets.find(s.vid().v);
|
||||
const auto wasArchived = (it->flags & MTPDstickerSet::Flag::f_archived);
|
||||
const auto wasArchived = (it->second->flags & MTPDstickerSet::Flag::f_archived);
|
||||
|
||||
auto set = FeedSet(s);
|
||||
|
||||
set->flags &= ~MTPDstickerSet_ClientFlag::f_not_loaded;
|
||||
|
||||
auto &d_docs = d.vdocuments().v;
|
||||
auto custom = sets.find(Stickers::CustomSetId);
|
||||
auto customIt = sets.find(Stickers::CustomSetId);
|
||||
auto inputSet = MTP_inputStickerSetID(
|
||||
MTP_long(set->id),
|
||||
MTP_long(set->access));
|
||||
@ -985,16 +996,17 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
|
||||
if (document->sticker()->set.type() != mtpc_inputStickerSetID) {
|
||||
document->sticker()->set = inputSet;
|
||||
}
|
||||
if (custom != sets.cend()) {
|
||||
if (customIt != sets.cend()) {
|
||||
const auto custom = customIt->second.get();
|
||||
const auto index = custom->stickers.indexOf(document);
|
||||
if (index >= 0) {
|
||||
custom->stickers.removeAt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (custom != sets.cend() && custom->stickers.isEmpty()) {
|
||||
sets.erase(custom);
|
||||
custom = sets.end();
|
||||
if (customIt != sets.cend() && customIt->second->stickers.isEmpty()) {
|
||||
sets.erase(customIt);
|
||||
customIt = sets.end();
|
||||
}
|
||||
|
||||
auto writeRecent = false;
|
||||
@ -1276,31 +1288,4 @@ std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
|
||||
box);
|
||||
}
|
||||
|
||||
ThumbnailSource::ThumbnailSource(
|
||||
const StorageImageLocation &location,
|
||||
int size)
|
||||
: StorageSource(location, size) {
|
||||
}
|
||||
|
||||
QImage ThumbnailSource::takeLoaded() {
|
||||
const auto loader = currentLoader();
|
||||
if (_bytesForAnimated.isEmpty()
|
||||
&& loader
|
||||
&& loader->finished()
|
||||
&& !loader->cancelled()) {
|
||||
_bytesForAnimated = loader->bytes();
|
||||
}
|
||||
auto result = StorageSource::takeLoaded();
|
||||
if (!_bytesForAnimated.isEmpty()
|
||||
&& !result.isNull()
|
||||
&& result.size() != Image::Empty()->original().size()) {
|
||||
_bytesForAnimated = QByteArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray ThumbnailSource::bytesForCache() {
|
||||
return _bytesForAnimated;
|
||||
}
|
||||
|
||||
} // namespace Stickers
|
||||
|
@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#pragma once
|
||||
|
||||
#include "mtproto/sender.h"
|
||||
#include "ui/image/image_source.h"
|
||||
|
||||
class DocumentData;
|
||||
|
||||
@ -46,53 +45,7 @@ constexpr auto FeaturedSetId = 0xFFFFFFFFFFFFFFFBULL; // for emoji/stickers pane
|
||||
constexpr auto FavedSetId = 0xFFFFFFFFFFFFFFFAULL; // for cloud-stored faved stickers
|
||||
constexpr auto MegagroupSetId = 0xFFFFFFFFFFFFFFEFULL; // for setting up megagroup sticker set
|
||||
|
||||
using Order = QList<uint64>;
|
||||
using SavedGifs = QVector<DocumentData*>;
|
||||
using Pack = QVector<DocumentData*>;
|
||||
using ByEmojiMap = QMap<EmojiPtr, Pack>;
|
||||
|
||||
struct Set {
|
||||
Set(
|
||||
uint64 id,
|
||||
uint64 access,
|
||||
const QString &title,
|
||||
const QString &shortName,
|
||||
int count,
|
||||
int32 hash,
|
||||
MTPDstickerSet::Flags flags,
|
||||
TimeId installDate,
|
||||
ImagePtr thumbnail)
|
||||
: id(id)
|
||||
, access(access)
|
||||
, title(title)
|
||||
, shortName(shortName)
|
||||
, count(count)
|
||||
, hash(hash)
|
||||
, flags(flags)
|
||||
, installDate(installDate)
|
||||
, thumbnail(thumbnail) {
|
||||
}
|
||||
uint64 id = 0;
|
||||
uint64 access = 0;
|
||||
QString title, shortName;
|
||||
int count = 0;
|
||||
int32 hash = 0;
|
||||
MTPDstickerSet::Flags flags;
|
||||
TimeId installDate = 0;
|
||||
ImagePtr thumbnail;
|
||||
Pack stickers;
|
||||
std::vector<TimeId> dates;
|
||||
Pack covers;
|
||||
ByEmojiMap emoji;
|
||||
};
|
||||
using Sets = QMap<uint64, Set>;
|
||||
|
||||
inline MTPInputStickerSet inputSetId(const Set &set) {
|
||||
if (set.id && set.access) {
|
||||
return MTP_inputStickerSetID(MTP_long(set.id), MTP_long(set.access));
|
||||
}
|
||||
return MTP_inputStickerSetShortName(MTP_string(set.shortName));
|
||||
}
|
||||
class Set;
|
||||
|
||||
void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d);
|
||||
bool ApplyArchivedResultFake(); // For testing.
|
||||
@ -110,7 +63,7 @@ void SpecialSetReceived(
|
||||
const QVector<MTPStickerPack> &packs = QVector<MTPStickerPack>(),
|
||||
const QVector<MTPint> &usageDates = QVector<MTPint>());
|
||||
void FeaturedSetsReceived(
|
||||
const QVector<MTPStickerSetCovered> &data,
|
||||
const QVector<MTPStickerSetCovered> &list,
|
||||
const QVector<MTPlong> &unread,
|
||||
int32 hash);
|
||||
void GifsReceived(const QVector<MTPDocument> &items, int32 hash);
|
||||
@ -168,19 +121,4 @@ enum class LottieSize : uchar {
|
||||
QSize box,
|
||||
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
|
||||
|
||||
class ThumbnailSource : public Images::StorageSource {
|
||||
public:
|
||||
ThumbnailSource(
|
||||
const StorageImageLocation &location,
|
||||
int size);
|
||||
|
||||
QImage takeLoaded() override;
|
||||
|
||||
QByteArray bytesForCache() override;
|
||||
|
||||
private:
|
||||
QByteArray _bytesForAnimated;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Stickers
|
||||
|
@ -184,7 +184,8 @@ private:
|
||||
|
||||
};
|
||||
|
||||
auto StickersListWidget::PrepareStickers(const Stickers::Pack &pack)
|
||||
auto StickersListWidget::PrepareStickers(
|
||||
const QVector<DocumentData*> &pack)
|
||||
-> std::vector<Sticker> {
|
||||
return ranges::view::all(
|
||||
pack
|
||||
@ -1288,7 +1289,7 @@ void StickersListWidget::fillLocalSearchRows(const QString &query) {
|
||||
for (const auto &[setId, titleWords] : _searchIndex) {
|
||||
if (allSearchWordsInTitle(titleWords)) {
|
||||
if (const auto it = sets.find(setId); it != sets.end()) {
|
||||
addSearchRow(&*it);
|
||||
addSearchRow(it->second.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1299,7 +1300,7 @@ void StickersListWidget::fillCloudSearchRows(
|
||||
const auto &sets = session().data().stickerSets();
|
||||
for (const auto setId : cloudSets) {
|
||||
if (const auto it = sets.find(setId); it != sets.end()) {
|
||||
addSearchRow(&*it);
|
||||
addSearchRow(it->second.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1310,7 +1311,7 @@ void StickersListWidget::addSearchRow(not_null<const Stickers::Set*> set) {
|
||||
set->flags,
|
||||
set->title,
|
||||
set->shortName,
|
||||
set->thumbnail,
|
||||
ImagePtr(),// set->thumbnail, #TODO optimize stickers
|
||||
set->count,
|
||||
!SetInMyList(set->flags),
|
||||
PrepareStickers(set->stickers.empty()
|
||||
@ -2123,10 +2124,11 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
|
||||
auto &sets = session().data().stickerSetsRef();
|
||||
auto it = sets.find(Stickers::CustomSetId);
|
||||
if (it != sets.cend()) {
|
||||
for (int i = 0, l = it->stickers.size(); i < l; ++i) {
|
||||
if (it->stickers.at(i) == document) {
|
||||
it->stickers.removeAt(i);
|
||||
if (it->stickers.isEmpty()) {
|
||||
const auto set = it->second.get();
|
||||
for (int i = 0, l = set->stickers.size(); i < l; ++i) {
|
||||
if (set->stickers.at(i) == document) {
|
||||
set->stickers.removeAt(i);
|
||||
if (set->stickers.isEmpty()) {
|
||||
sets.erase(it);
|
||||
}
|
||||
Local::writeInstalledStickers();
|
||||
@ -2295,14 +2297,14 @@ void StickersListWidget::refreshFeaturedSets() {
|
||||
const auto till = end(wereOfficial);
|
||||
for (auto i = from; i != till; ++i) {
|
||||
auto &set = *i;
|
||||
auto it = sets.constFind(set.id);
|
||||
auto it = sets.find(set.id);
|
||||
if (it == sets.cend()
|
||||
|| ((it->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !(it->flags & MTPDstickerSet::Flag::f_archived)
|
||||
|| ((it->second->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !(it->second->flags & MTPDstickerSet::Flag::f_archived)
|
||||
&& !_installedLocallySets.contains(set.id))) {
|
||||
continue;
|
||||
}
|
||||
set.flags = it->flags;
|
||||
set.flags = it->second->flags;
|
||||
_officialSets.push_back(std::move(set));
|
||||
}
|
||||
}
|
||||
@ -2312,16 +2314,17 @@ void StickersListWidget::refreshSearchSets() {
|
||||
refreshSearchIndex();
|
||||
|
||||
const auto &sets = session().data().stickerSets();
|
||||
for (auto &set : _searchSets) {
|
||||
if (const auto it = sets.find(set.id); it != sets.end()) {
|
||||
set.flags = it->flags;
|
||||
if (!it->stickers.empty()) {
|
||||
set.lottiePlayer = nullptr;
|
||||
set.stickers = PrepareStickers(it->stickers);
|
||||
for (auto &entry : _searchSets) {
|
||||
if (const auto it = sets.find(entry.id); it != sets.end()) {
|
||||
const auto set = it->second.get();
|
||||
entry.flags = set->flags;
|
||||
if (!set->stickers.empty()) {
|
||||
entry.lottiePlayer = nullptr;
|
||||
entry.stickers = PrepareStickers(set->stickers);
|
||||
}
|
||||
if (!SetInMyList(set.flags)) {
|
||||
_installedLocallySets.remove(set.id);
|
||||
set.externalLayout = true;
|
||||
if (!SetInMyList(entry.flags)) {
|
||||
_installedLocallySets.remove(entry.id);
|
||||
entry.externalLayout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2373,32 +2376,34 @@ bool StickersListWidget::appendSet(
|
||||
bool externalLayout,
|
||||
AppendSkip skip) {
|
||||
auto &sets = session().data().stickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
if (it == sets.cend() || (!externalLayout && it->stickers.isEmpty())) {
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend()
|
||||
|| (!externalLayout && it->second->stickers.isEmpty())) {
|
||||
return false;
|
||||
}
|
||||
const auto set = it->second.get();
|
||||
if ((skip == AppendSkip::Archived)
|
||||
&& (it->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
&& (set->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
return false;
|
||||
}
|
||||
if ((skip == AppendSkip::Installed)
|
||||
&& (it->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !(it->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
&& (set->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !(set->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
if (!_installedLocallySets.contains(setId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
to.emplace_back(
|
||||
it->id,
|
||||
it->flags,
|
||||
it->title,
|
||||
it->shortName,
|
||||
it->thumbnail,
|
||||
it->count,
|
||||
set->id,
|
||||
set->flags,
|
||||
set->title,
|
||||
set->shortName,
|
||||
ImagePtr(), // set->thumbnail, #TODO optimize stickers
|
||||
set->count,
|
||||
externalLayout,
|
||||
PrepareStickers((it->stickers.empty() && externalLayout)
|
||||
? it->covers
|
||||
: it->stickers));
|
||||
PrepareStickers((set->stickers.empty() && externalLayout)
|
||||
? set->covers
|
||||
: set->stickers));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2417,13 +2422,13 @@ auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
|
||||
|
||||
const auto &sets = session().data().stickerSets();
|
||||
const auto &recent = Stickers::GetRecentPack();
|
||||
const auto customIt = sets.constFind(Stickers::CustomSetId);
|
||||
const auto cloudIt = sets.constFind(Stickers::CloudRecentSetId);
|
||||
const auto customIt = sets.find(Stickers::CustomSetId);
|
||||
const auto cloudIt = sets.find(Stickers::CloudRecentSetId);
|
||||
const auto customCount = (customIt != sets.cend())
|
||||
? customIt->stickers.size()
|
||||
? customIt->second->stickers.size()
|
||||
: 0;
|
||||
const auto cloudCount = (cloudIt != sets.cend())
|
||||
? cloudIt->stickers.size()
|
||||
? cloudIt->second->stickers.size()
|
||||
: 0;
|
||||
result.reserve(cloudCount + recent.size() + customCount);
|
||||
_custom.reserve(cloudCount + recent.size() + customCount);
|
||||
@ -2448,7 +2453,7 @@ auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
|
||||
};
|
||||
|
||||
if (cloudCount > 0) {
|
||||
for (const auto document : cloudIt->stickers) {
|
||||
for (const auto document : cloudIt->second->stickers) {
|
||||
add(document, false);
|
||||
}
|
||||
}
|
||||
@ -2456,7 +2461,7 @@ auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
|
||||
add(recentSticker.first, false);
|
||||
}
|
||||
if (customCount > 0) {
|
||||
for (const auto document : customIt->stickers) {
|
||||
for (const auto document : customIt->second->stickers) {
|
||||
add(document, true);
|
||||
}
|
||||
}
|
||||
@ -2502,11 +2507,12 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
|
||||
|
||||
void StickersListWidget::refreshFavedStickers() {
|
||||
clearSelection();
|
||||
auto &sets = session().data().stickerSets();
|
||||
auto it = sets.constFind(Stickers::FavedSetId);
|
||||
if (it == sets.cend() || it->stickers.isEmpty()) {
|
||||
const auto &sets = session().data().stickerSets();
|
||||
const auto it = sets.find(Stickers::FavedSetId);
|
||||
if (it == sets.cend() || it->second->stickers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const auto set = it->second.get();
|
||||
const auto externalLayout = false;
|
||||
const auto shortName = QString();
|
||||
const auto thumbnail = ImagePtr();
|
||||
@ -2517,12 +2523,12 @@ void StickersListWidget::refreshFavedStickers() {
|
||||
Lang::Hard::FavedSetTitle(),
|
||||
shortName,
|
||||
thumbnail,
|
||||
it->count,
|
||||
set->count,
|
||||
externalLayout,
|
||||
PrepareStickers(it->stickers));
|
||||
PrepareStickers(set->stickers));
|
||||
_favedStickersMap = base::flat_set<not_null<DocumentData*>> {
|
||||
it->stickers.begin(),
|
||||
it->stickers.end()
|
||||
set->stickers.begin(),
|
||||
set->stickers.end()
|
||||
};
|
||||
}
|
||||
|
||||
@ -2569,11 +2575,12 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
|
||||
return;
|
||||
}
|
||||
auto &set = _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID();
|
||||
auto &sets = session().data().stickerSets();
|
||||
auto it = sets.constFind(set.vid().v);
|
||||
const auto &sets = session().data().stickerSets();
|
||||
const auto it = sets.find(set.vid().v);
|
||||
if (it != sets.cend()) {
|
||||
auto isInstalled = (it->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !(it->flags & MTPDstickerSet::Flag::f_archived);
|
||||
const auto set = it->second.get();
|
||||
auto isInstalled = (set->flags & MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !(set->flags & MTPDstickerSet::Flag::f_archived);
|
||||
if (isInstalled && !canEdit) {
|
||||
removeHiddenForGroup();
|
||||
} else if (isShownHere(hidden)) {
|
||||
@ -2586,9 +2593,9 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
|
||||
tr::lng_group_stickers(tr::now),
|
||||
shortName,
|
||||
thumbnail,
|
||||
it->count,
|
||||
set->count,
|
||||
externalLayout,
|
||||
PrepareStickers(it->stickers));
|
||||
PrepareStickers(set->stickers));
|
||||
}
|
||||
return;
|
||||
} else if (!isShownHere(hidden)
|
||||
@ -2909,11 +2916,11 @@ void StickersListWidget::displaySet(uint64 setId) {
|
||||
}
|
||||
}
|
||||
auto &sets = session().data().stickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
_displayingSet = true;
|
||||
checkHideWithBox(Ui::show(
|
||||
Box<StickerSetBox>(controller(), Stickers::inputSetId(*it)),
|
||||
Box<StickerSetBox>(controller(), it->second->mtpInput()),
|
||||
Ui::LayerOption::KeepOther).data());
|
||||
}
|
||||
}
|
||||
@ -2929,12 +2936,13 @@ void StickersListWidget::checkHideWithBox(QPointer<Ui::BoxContent> box) {
|
||||
}
|
||||
|
||||
void StickersListWidget::installSet(uint64 setId) {
|
||||
auto &sets = session().data().stickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
const auto &sets = session().data().stickerSets();
|
||||
const auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
const auto input = Stickers::inputSetId(*it);
|
||||
if ((it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)
|
||||
|| it->stickers.empty()) {
|
||||
const auto set = it->second.get();
|
||||
const auto input = set->mtpInput();
|
||||
if ((set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)
|
||||
|| set->stickers.empty()) {
|
||||
_api.request(MTPmessages_GetStickerSet(
|
||||
input
|
||||
)).done([=](const MTPmessages_StickerSet &result) {
|
||||
@ -2990,38 +2998,40 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
|
||||
}
|
||||
|
||||
void StickersListWidget::removeSet(uint64 setId) {
|
||||
auto &sets = session().data().stickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
const auto &sets = session().data().stickerSets();
|
||||
const auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
_removingSetId = it->id;
|
||||
auto text = tr::lng_stickers_remove_pack(tr::now, lt_sticker_pack, it->title);
|
||||
const auto set = it->second.get();
|
||||
_removingSetId = set->id;
|
||||
auto text = tr::lng_stickers_remove_pack(tr::now, lt_sticker_pack, set->title);
|
||||
Ui::show(Box<ConfirmBox>(text, tr::lng_stickers_remove_pack_confirm(tr::now), crl::guard(this, [=] {
|
||||
Ui::hideLayer();
|
||||
auto &sets = session().data().stickerSetsRef();
|
||||
auto it = sets.find(_removingSetId);
|
||||
const auto &sets = session().data().stickerSetsRef();
|
||||
const auto it = sets.find(_removingSetId);
|
||||
if (it != sets.cend()) {
|
||||
if (it->id && it->access) {
|
||||
_api.request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)))).send();
|
||||
} else if (!it->shortName.isEmpty()) {
|
||||
_api.request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(it->shortName)))).send();
|
||||
const auto set = it->second.get();
|
||||
if (set->id && set->access) {
|
||||
_api.request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetID(MTP_long(set->id), MTP_long(set->access)))).send();
|
||||
} else if (!set->shortName.isEmpty()) {
|
||||
_api.request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(set->shortName)))).send();
|
||||
}
|
||||
auto writeRecent = false;
|
||||
auto &recent = Stickers::GetRecentPack();
|
||||
for (auto i = recent.begin(); i != recent.cend();) {
|
||||
if (it->stickers.indexOf(i->first) >= 0) {
|
||||
if (set->stickers.indexOf(i->first) >= 0) {
|
||||
i = recent.erase(i);
|
||||
writeRecent = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
it->flags &= ~MTPDstickerSet::Flag::f_installed_date;
|
||||
it->installDate = TimeId(0);
|
||||
set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
|
||||
set->installDate = TimeId(0);
|
||||
//
|
||||
// Set can be in search results.
|
||||
//
|
||||
//if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured)
|
||||
// && !(it->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
//if (!(set->flags & MTPDstickerSet_ClientFlag::f_featured)
|
||||
// && !(set->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
// sets.erase(it);
|
||||
//}
|
||||
int removeIndex = session().data().stickerSetsOrder().indexOf(_removingSetId);
|
||||
|
@ -196,7 +196,8 @@ private:
|
||||
std::vector<Sticker> stickers;
|
||||
};
|
||||
|
||||
static std::vector<Sticker> PrepareStickers(const Stickers::Pack &pack);
|
||||
static std::vector<Sticker> PrepareStickers(
|
||||
const QVector<DocumentData*> &pack);
|
||||
|
||||
void preloadMoreOfficial();
|
||||
QSize boundingBoxSize() const;
|
||||
|
134
Telegram/SourceFiles/chat_helpers/stickers_set.cpp
Normal file
134
Telegram/SourceFiles/chat_helpers/stickers_set.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "chat_helpers/stickers_set.h"
|
||||
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "ui/image/image_source.h"
|
||||
#include "app.h"
|
||||
|
||||
namespace Stickers {
|
||||
|
||||
void SetThumbnailView::set(
|
||||
not_null<Main::Session*> session,
|
||||
QByteArray content) {
|
||||
auto image = App::readImage(content, nullptr, false);
|
||||
if (image.isNull()) {
|
||||
_content = std::move(content);
|
||||
} else {
|
||||
_image = std::make_unique<Image>(
|
||||
std::make_unique<Images::ImageSource>(std::move(image), "PNG"));
|
||||
}
|
||||
session->downloaderTaskFinished().notify();
|
||||
}
|
||||
|
||||
Image *SetThumbnailView::image() const {
|
||||
return _image.get();
|
||||
}
|
||||
|
||||
QByteArray SetThumbnailView::content() const {
|
||||
return _content;
|
||||
}
|
||||
|
||||
Set::Set(
|
||||
not_null<Data::Session*> owner,
|
||||
uint64 id,
|
||||
uint64 access,
|
||||
const QString &title,
|
||||
const QString &shortName,
|
||||
int count,
|
||||
int32 hash,
|
||||
MTPDstickerSet::Flags flags,
|
||||
TimeId installDate)
|
||||
: id(id)
|
||||
, access(access)
|
||||
, title(title)
|
||||
, shortName(shortName)
|
||||
, count(count)
|
||||
, hash(hash)
|
||||
, flags(flags)
|
||||
, installDate(installDate)
|
||||
, _owner(owner) {
|
||||
}
|
||||
|
||||
MTPInputStickerSet Set::mtpInput() const {
|
||||
return (id && access)
|
||||
? MTP_inputStickerSetID(MTP_long(id), MTP_long(access))
|
||||
: MTP_inputStickerSetShortName(MTP_string(shortName));
|
||||
}
|
||||
|
||||
void Set::setThumbnail(const ImageWithLocation &data) {
|
||||
Data::UpdateCloudFile(
|
||||
_thumbnail,
|
||||
data,
|
||||
_owner->cache(),
|
||||
Data::kImageCacheTag,
|
||||
[=](Data::FileOrigin origin) { loadThumbnail(origin); });
|
||||
if (!data.bytes.isEmpty()) {
|
||||
if (_thumbnail.loader) {
|
||||
_thumbnail.loader->cancel();
|
||||
}
|
||||
if (const auto view = activeThumbnailView()) {
|
||||
view->set(&_owner->session(), data.bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Set::hasThumbnail() const {
|
||||
return _thumbnail.location.valid();
|
||||
}
|
||||
|
||||
bool Set::thumbnailLoading() const {
|
||||
return (_thumbnail.loader != nullptr);
|
||||
}
|
||||
|
||||
bool Set::thumbnailFailed() const {
|
||||
return (_thumbnail.flags & Data::CloudFile::Flag::Failed);
|
||||
}
|
||||
|
||||
void Set::loadThumbnail(Data::FileOrigin origin) {
|
||||
auto &file = _thumbnail;
|
||||
const auto fromCloud = LoadFromCloudOrLocal;
|
||||
const auto cacheTag = Data::kImageCacheTag;
|
||||
const auto autoLoading = false;
|
||||
Data::LoadCloudFile(file, origin, fromCloud, autoLoading, cacheTag, [=] {
|
||||
if (const auto active = activeThumbnailView()) {
|
||||
return !active->image() && active->content().isEmpty();
|
||||
}
|
||||
return true;
|
||||
}, [=](QByteArray result) {
|
||||
if (const auto active = activeThumbnailView()) {
|
||||
active->set(&_owner->session(), std::move(result));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const ImageLocation &Set::thumbnailLocation() const {
|
||||
return _thumbnail.location;
|
||||
}
|
||||
|
||||
int Set::thumbnailByteSize() const {
|
||||
return _thumbnail.byteSize;
|
||||
}
|
||||
|
||||
std::shared_ptr<SetThumbnailView> Set::createThumbnailView() {
|
||||
if (auto active = activeThumbnailView()) {
|
||||
return active;
|
||||
}
|
||||
auto view = std::make_shared<SetThumbnailView>();
|
||||
_thumbnailView = view;
|
||||
return view;
|
||||
}
|
||||
|
||||
std::shared_ptr<SetThumbnailView> Set::activeThumbnailView() {
|
||||
return _thumbnailView.lock();
|
||||
}
|
||||
|
||||
} // namespace Stickers
|
92
Telegram/SourceFiles/chat_helpers/stickers_set.h
Normal file
92
Telegram/SourceFiles/chat_helpers/stickers_set.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "data/data_cloud_file.h"
|
||||
|
||||
class DocumentData;
|
||||
|
||||
namespace Data {
|
||||
class Session;
|
||||
} // namespace Data
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Stickers {
|
||||
|
||||
using Order = QList<uint64>;
|
||||
using SavedGifs = QVector<DocumentData*>;
|
||||
using Pack = QVector<DocumentData*>;
|
||||
using ByEmojiMap = QMap<EmojiPtr, Pack>;
|
||||
|
||||
class Set;
|
||||
using Sets = base::flat_map<uint64, std::unique_ptr<Set>>;
|
||||
|
||||
class SetThumbnailView final {
|
||||
public:
|
||||
void set(not_null<Main::Session*> session, QByteArray content);
|
||||
|
||||
[[nodiscard]] Image *image() const;
|
||||
[[nodiscard]] QByteArray content() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Image> _image;
|
||||
QByteArray _content;
|
||||
|
||||
};
|
||||
|
||||
class Set final {
|
||||
public:
|
||||
Set(
|
||||
not_null<Data::Session*> owner,
|
||||
uint64 id,
|
||||
uint64 access,
|
||||
const QString &title,
|
||||
const QString &shortName,
|
||||
int count,
|
||||
int32 hash,
|
||||
MTPDstickerSet::Flags flags,
|
||||
TimeId installDate);
|
||||
|
||||
[[nodiscard]] MTPInputStickerSet mtpInput() const;
|
||||
|
||||
void setThumbnail(const ImageWithLocation &data);
|
||||
|
||||
[[nodiscard]] bool hasThumbnail() const;
|
||||
[[nodiscard]] bool thumbnailLoading() const;
|
||||
[[nodiscard]] bool thumbnailFailed() const;
|
||||
void loadThumbnail(Data::FileOrigin origin);
|
||||
[[nodiscard]] const ImageLocation &thumbnailLocation() const;
|
||||
[[nodiscard]] int thumbnailByteSize() const;
|
||||
|
||||
[[nodiscard]] std::shared_ptr<SetThumbnailView> createThumbnailView();
|
||||
[[nodiscard]] std::shared_ptr<SetThumbnailView> activeThumbnailView();
|
||||
|
||||
uint64 id = 0;
|
||||
uint64 access = 0;
|
||||
QString title, shortName;
|
||||
int count = 0;
|
||||
int32 hash = 0;
|
||||
MTPDstickerSet::Flags flags;
|
||||
TimeId installDate = 0;
|
||||
Pack stickers;
|
||||
std::vector<TimeId> dates;
|
||||
Pack covers;
|
||||
ByEmojiMap emoji;
|
||||
|
||||
private:
|
||||
const not_null<Data::Session*> _owner;
|
||||
|
||||
Data::CloudFile _thumbnail;
|
||||
std::weak_ptr<SetThumbnailView> _thumbnailView;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Stickers
|
@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_session.h"
|
||||
#include "storage/cache/storage_cache_database.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/image/image_source.h"
|
||||
#include "main/main_session.h"
|
||||
|
||||
#include <compare>
|
||||
@ -74,7 +74,6 @@ void CloudImage::load(FileOrigin origin) {
|
||||
active->set(_session, std::move(result));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const ImageLocation &CloudImage::location() const {
|
||||
|
@ -18,6 +18,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "core/file_utilities.h"
|
||||
#include "core/media_active_cache.h"
|
||||
#include "core/mime_type.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "chat_helpers/stickers_set.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "media/streaming/media_streaming_loader_mtproto.h"
|
||||
@ -1182,16 +1184,16 @@ bool DocumentData::isStickerSetInstalled() const {
|
||||
|
||||
const auto &sets = _owner->stickerSets();
|
||||
return sticker()->set.match([&](const MTPDinputStickerSetID &data) {
|
||||
const auto i = sets.constFind(data.vid().v);
|
||||
const auto i = sets.find(data.vid().v);
|
||||
return (i != sets.cend())
|
||||
&& !(i->flags & MTPDstickerSet::Flag::f_archived)
|
||||
&& (i->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
&& !(i->second->flags & MTPDstickerSet::Flag::f_archived)
|
||||
&& (i->second->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
}, [&](const MTPDinputStickerSetShortName &data) {
|
||||
const auto name = qs(data.vshort_name()).toLower();
|
||||
for (const auto &set : sets) {
|
||||
if (set.shortName.toLower() == name) {
|
||||
return !(set.flags & MTPDstickerSet::Flag::f_archived)
|
||||
&& (set.flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
for (const auto &[id, set] : sets) {
|
||||
if (set->shortName.toLower() == name) {
|
||||
return !(set->flags & MTPDstickerSet::Flag::f_archived)
|
||||
&& (set->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/history.h"
|
||||
#include "window/themes/window_theme_preview.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/image/image_source.h"
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
|
||||
|
@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/history_item.h"
|
||||
#include "history/history.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/image/image_source.h"
|
||||
|
||||
namespace Data {
|
||||
|
||||
|
@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#pragma once
|
||||
|
||||
#include "storage/storage_databases.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "chat_helpers/stickers_set.h"
|
||||
#include "dialogs/dialogs_key.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "dialogs/dialogs_main_list.h"
|
||||
|
@ -362,17 +362,6 @@ struct Data {
|
||||
|
||||
HiddenPinnedMessagesMap HiddenPinnedMessages;
|
||||
|
||||
Stickers::Sets StickerSets;
|
||||
Stickers::Order StickerSetsOrder;
|
||||
crl::time LastStickersUpdate = 0;
|
||||
crl::time LastRecentStickersUpdate = 0;
|
||||
crl::time LastFavedStickersUpdate = 0;
|
||||
Stickers::Order FeaturedStickerSetsOrder;
|
||||
int FeaturedStickerSetsUnreadCount = 0;
|
||||
base::Observable<void> FeaturedStickerSetsUnreadCountChanged;
|
||||
crl::time LastFeaturedStickersUpdate = 0;
|
||||
Stickers::Order ArchivedStickerSetsOrder;
|
||||
|
||||
bool AskDownloadPath = false;
|
||||
QString DownloadPath;
|
||||
QByteArray DownloadPathBookmark;
|
||||
@ -491,17 +480,6 @@ DefineRefVar(Global, base::Observable<void>, PhoneCallsEnabledChanged);
|
||||
|
||||
DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages);
|
||||
|
||||
DefineVar(Global, Stickers::Sets, StickerSets);
|
||||
DefineVar(Global, Stickers::Order, StickerSetsOrder);
|
||||
DefineVar(Global, crl::time, LastStickersUpdate);
|
||||
DefineVar(Global, crl::time, LastRecentStickersUpdate);
|
||||
DefineVar(Global, crl::time, LastFavedStickersUpdate);
|
||||
DefineVar(Global, Stickers::Order, FeaturedStickerSetsOrder);
|
||||
DefineVar(Global, int, FeaturedStickerSetsUnreadCount);
|
||||
DefineRefVar(Global, base::Observable<void>, FeaturedStickerSetsUnreadCountChanged);
|
||||
DefineVar(Global, crl::time, LastFeaturedStickersUpdate);
|
||||
DefineVar(Global, Stickers::Order, ArchivedStickerSetsOrder);
|
||||
|
||||
DefineVar(Global, bool, AskDownloadPath);
|
||||
DefineVar(Global, QString, DownloadPath);
|
||||
DefineVar(Global, QByteArray, DownloadPathBookmark);
|
||||
|
@ -26,7 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/view/media/history_view_media_common.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "core/application.h" // Application::showDocument.
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/image/image_source.h"
|
||||
#include "ui/grouped_layout.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_streaming.h"
|
||||
|
@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/history_location_manager.h"
|
||||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "chat_helpers/stickers.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_user.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "mainwidget.h"
|
||||
#include "observer_peer.h"
|
||||
#include "main/main_app_config.h"
|
||||
|
@ -3360,7 +3360,8 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
|
||||
auto it = sets.find(Stickers::CloudRecentSetId);
|
||||
if (it == sets.cend()) {
|
||||
if (it == sets.cend()) {
|
||||
it = sets.insert(Stickers::CloudRecentSetId, Stickers::Set(
|
||||
it = sets.emplace(Stickers::CloudRecentSetId, std::make_unique<Stickers::Set>(
|
||||
&session().data(),
|
||||
Stickers::CloudRecentSetId,
|
||||
uint64(0),
|
||||
tr::lng_recent_stickers(tr::now),
|
||||
@ -3368,28 +3369,28 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
|
||||
0, // count
|
||||
0, // hash
|
||||
MTPDstickerSet_ClientFlag::f_special | 0,
|
||||
TimeId(0),
|
||||
ImagePtr()));
|
||||
TimeId(0))).first;
|
||||
} else {
|
||||
it->title = tr::lng_recent_stickers(tr::now);
|
||||
it->second->title = tr::lng_recent_stickers(tr::now);
|
||||
}
|
||||
}
|
||||
const auto set = it->second.get();
|
||||
auto removedFromEmoji = std::vector<not_null<EmojiPtr>>();
|
||||
auto index = it->stickers.indexOf(sticker);
|
||||
auto index = set->stickers.indexOf(sticker);
|
||||
if (index > 0) {
|
||||
if (it->dates.empty()) {
|
||||
if (set->dates.empty()) {
|
||||
session().api().requestRecentStickersForce();
|
||||
} else {
|
||||
Assert(it->dates.size() == it->stickers.size());
|
||||
it->dates.erase(it->dates.begin() + index);
|
||||
Assert(set->dates.size() == set->stickers.size());
|
||||
set->dates.erase(set->dates.begin() + index);
|
||||
}
|
||||
it->stickers.removeAt(index);
|
||||
for (auto i = it->emoji.begin(); i != it->emoji.end();) {
|
||||
set->stickers.removeAt(index);
|
||||
for (auto i = set->emoji.begin(); i != set->emoji.end();) {
|
||||
if (const auto index = i->indexOf(sticker); index >= 0) {
|
||||
removedFromEmoji.emplace_back(i.key());
|
||||
i->removeAt(index);
|
||||
if (i->isEmpty()) {
|
||||
i = it->emoji.erase(i);
|
||||
i = set->emoji.erase(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -3397,17 +3398,17 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
|
||||
}
|
||||
}
|
||||
if (index) {
|
||||
if (it->dates.size() == it->stickers.size()) {
|
||||
it->dates.insert(it->dates.begin(), base::unixtime::now());
|
||||
if (set->dates.size() == set->stickers.size()) {
|
||||
set->dates.insert(set->dates.begin(), base::unixtime::now());
|
||||
}
|
||||
it->stickers.push_front(sticker);
|
||||
set->stickers.push_front(sticker);
|
||||
if (const auto emojiList = Stickers::GetEmojiListFromSet(sticker)) {
|
||||
for (const auto emoji : *emojiList) {
|
||||
it->emoji[emoji].push_front(sticker);
|
||||
set->emoji[emoji].push_front(sticker);
|
||||
}
|
||||
} else if (!removedFromEmoji.empty()) {
|
||||
for (const auto emoji : removedFromEmoji) {
|
||||
it->emoji[emoji].push_front(sticker);
|
||||
set->emoji[emoji].push_front(sticker);
|
||||
}
|
||||
} else {
|
||||
session().api().requestRecentStickersForce();
|
||||
@ -3426,7 +3427,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!recent.isEmpty() && it->stickers.size() + recent.size() > Global::StickersRecentLimit()) {
|
||||
while (!recent.isEmpty() && set->stickers.size() + recent.size() > Global::StickersRecentLimit()) {
|
||||
writeOldRecent = true;
|
||||
recent.pop_back();
|
||||
}
|
||||
@ -3437,13 +3438,14 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
|
||||
|
||||
// Remove that sticker from custom stickers, now it is in cloud recent stickers.
|
||||
bool writeInstalledStickers = false;
|
||||
auto custom = sets.find(Stickers::CustomSetId);
|
||||
if (custom != sets.cend()) {
|
||||
auto customIt = sets.find(Stickers::CustomSetId);
|
||||
if (customIt != sets.cend()) {
|
||||
const auto custom = customIt->second.get();
|
||||
int removeIndex = custom->stickers.indexOf(sticker);
|
||||
if (removeIndex >= 0) {
|
||||
custom->stickers.removeAt(removeIndex);
|
||||
if (custom->stickers.isEmpty()) {
|
||||
sets.erase(custom);
|
||||
sets.erase(customIt);
|
||||
}
|
||||
writeInstalledStickers = true;
|
||||
}
|
||||
@ -4520,12 +4522,13 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||
auto &sets = session().data().stickerSets();
|
||||
Stickers::Order result;
|
||||
for (const auto &item : order) {
|
||||
if (sets.constFind(item.v) == sets.cend()) {
|
||||
if (sets.find(item.v) == sets.cend()) {
|
||||
break;
|
||||
}
|
||||
result.push_back(item.v);
|
||||
}
|
||||
if (result.size() != session().data().stickerSetsOrder().size() || result.size() != order.size()) {
|
||||
if (result.size() != session().data().stickerSetsOrder().size()
|
||||
|| result.size() != order.size()) {
|
||||
session().data().setLastStickersUpdate(0);
|
||||
session().api().updateStickers();
|
||||
} else {
|
||||
|
@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "storage/localstorage.h"
|
||||
#include "data/data_session.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mtproto/facade.h"
|
||||
#include "layout.h"
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/unixtime.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "mtproto/facade.h"
|
||||
#include "lottie/lottie_animation.h"
|
||||
#include "history/history_item.h"
|
||||
#include "boxes/send_files_box.h"
|
||||
|
@ -3438,9 +3438,7 @@ void _writeStickerSet(QDataStream &stream, const Stickers::Set &set) {
|
||||
<< qint32(set.hash)
|
||||
<< qint32(set.flags)
|
||||
<< qint32(set.installDate);
|
||||
Serialize::writeStorageImageLocation(
|
||||
stream,
|
||||
set.thumbnail ? set.thumbnail->location() : StorageImageLocation());
|
||||
Serialize::writeImageLocation(stream, set.thumbnailLocation());
|
||||
};
|
||||
if (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded) {
|
||||
writeInfo(-set.count);
|
||||
@ -3483,7 +3481,7 @@ void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::
|
||||
if (!_working()) return;
|
||||
|
||||
const auto &sets = Auth().data().stickerSets();
|
||||
if (sets.isEmpty()) {
|
||||
if (sets.empty()) {
|
||||
if (stickersKey) {
|
||||
ClearKey(stickersKey);
|
||||
stickersKey = 0;
|
||||
@ -3497,8 +3495,9 @@ void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::
|
||||
quint32 size = sizeof(quint32) + sizeof(qint32) + sizeof(qint32);
|
||||
|
||||
int32 setsCount = 0;
|
||||
for (const auto &set : sets) {
|
||||
auto result = checkSet(set);
|
||||
for (const auto &[id, set] : sets) {
|
||||
const auto raw = set.get();
|
||||
auto result = checkSet(*raw);
|
||||
if (result == StickerSetCheckResult::Abort) {
|
||||
return;
|
||||
} else if (result == StickerSetCheckResult::Skip) {
|
||||
@ -3507,28 +3506,26 @@ void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::
|
||||
|
||||
// id + access + title + shortName + stickersCount + hash + flags + installDate
|
||||
size += sizeof(quint64) * 2
|
||||
+ Serialize::stringSize(set.title)
|
||||
+ Serialize::stringSize(set.shortName)
|
||||
+ Serialize::stringSize(raw->title)
|
||||
+ Serialize::stringSize(raw->shortName)
|
||||
+ sizeof(qint32) * 4
|
||||
+ Serialize::storageImageLocationSize(set.thumbnail
|
||||
? set.thumbnail->location()
|
||||
: StorageImageLocation());
|
||||
if (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded) {
|
||||
+ Serialize::imageLocationSize(raw->thumbnailLocation());
|
||||
if (raw->flags & MTPDstickerSet_ClientFlag::f_not_loaded) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto sticker : set.stickers) {
|
||||
for (const auto sticker : raw->stickers) {
|
||||
size += Serialize::Document::sizeInStream(sticker);
|
||||
}
|
||||
|
||||
size += sizeof(qint32); // datesCount
|
||||
if (!set.dates.empty()) {
|
||||
Assert(set.stickers.size() == set.dates.size());
|
||||
size += set.dates.size() * sizeof(qint32);
|
||||
if (!raw->dates.empty()) {
|
||||
Assert(raw->stickers.size() == raw->dates.size());
|
||||
size += raw->dates.size() * sizeof(qint32);
|
||||
}
|
||||
|
||||
size += sizeof(qint32); // emojiCount
|
||||
for (auto j = set.emoji.cbegin(), e = set.emoji.cend(); j != e; ++j) {
|
||||
for (auto j = raw->emoji.cbegin(), e = raw->emoji.cend(); j != e; ++j) {
|
||||
size += Serialize::stringSize(j.key()->id()) + sizeof(qint32) + (j->size() * sizeof(quint64));
|
||||
}
|
||||
|
||||
@ -3555,14 +3552,14 @@ void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::
|
||||
<< quint32(kStickersVersionTag)
|
||||
<< qint32(kStickersSerializeVersion)
|
||||
<< qint32(setsCount);
|
||||
for (const auto &set : sets) {
|
||||
auto result = checkSet(set);
|
||||
for (const auto &[id, set] : sets) {
|
||||
auto result = checkSet(*set);
|
||||
if (result == StickerSetCheckResult::Abort) {
|
||||
return;
|
||||
} else if (result == StickerSetCheckResult::Skip) {
|
||||
continue;
|
||||
}
|
||||
_writeStickerSet(data.stream, set);
|
||||
_writeStickerSet(data.stream, *set);
|
||||
}
|
||||
data.stream << order;
|
||||
|
||||
@ -3612,7 +3609,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
|
||||
qint32 setHash = 0;
|
||||
MTPDstickerSet::Flags setFlags = 0;
|
||||
qint32 setFlagsValue = 0;
|
||||
StorageImageLocation setThumbnail;
|
||||
ImageLocation setThumbnail;
|
||||
|
||||
stickers.stream
|
||||
>> setId
|
||||
@ -3623,13 +3620,12 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
|
||||
>> setHash
|
||||
>> setFlagsValue
|
||||
>> setInstallDate;
|
||||
const auto thumbnail = Serialize::readStorageImageLocation(
|
||||
const auto thumbnail = Serialize::readImageLocation(
|
||||
stickers.version,
|
||||
stickers.stream);
|
||||
if (!thumbnail || !_checkStreamStatus(stickers.stream)) {
|
||||
return failed();
|
||||
} else if (thumbnail->valid()
|
||||
&& thumbnail->type() == LocationType::Legacy) {
|
||||
} else if (thumbnail->valid() && thumbnail->isLegacy()) {
|
||||
setThumbnail = thumbnail->convertToModern(
|
||||
LocationType::StickerSetThumb,
|
||||
setId,
|
||||
@ -3659,7 +3655,8 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
|
||||
if (it == sets.cend()) {
|
||||
// We will set this flags from order lists when reading those stickers.
|
||||
setFlags &= ~(MTPDstickerSet::Flag::f_installed_date | MTPDstickerSet_ClientFlag::f_featured);
|
||||
it = sets.insert(setId, Stickers::Set(
|
||||
it = sets.emplace(setId, std::make_unique<Stickers::Set>(
|
||||
&Auth().data(),
|
||||
setId,
|
||||
setAccess,
|
||||
setTitle,
|
||||
@ -3667,23 +3664,24 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
|
||||
0,
|
||||
setHash,
|
||||
MTPDstickerSet::Flags(setFlags),
|
||||
setInstallDate,
|
||||
Images::CreateStickerSetThumbnail(setThumbnail)));
|
||||
setInstallDate)).first;
|
||||
it->second->setThumbnail(
|
||||
ImageWithLocation{ .location = setThumbnail });
|
||||
}
|
||||
auto &set = it.value();
|
||||
auto inputSet = MTP_inputStickerSetID(MTP_long(set.id), MTP_long(set.access));
|
||||
const auto fillStickers = set.stickers.isEmpty();
|
||||
const auto set = it->second.get();
|
||||
auto inputSet = MTP_inputStickerSetID(MTP_long(set->id), MTP_long(set->access));
|
||||
const auto fillStickers = set->stickers.isEmpty();
|
||||
|
||||
if (scnt < 0) { // disabled not loaded set
|
||||
if (!set.count || fillStickers) {
|
||||
set.count = -scnt;
|
||||
if (!set->count || fillStickers) {
|
||||
set->count = -scnt;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fillStickers) {
|
||||
set.stickers.reserve(scnt);
|
||||
set.count = 0;
|
||||
set->stickers.reserve(scnt);
|
||||
set->count = 0;
|
||||
}
|
||||
|
||||
Serialize::Document::StickerSetInfo info(setId, setAccess, setShortName);
|
||||
@ -3699,13 +3697,13 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
|
||||
}
|
||||
read.emplace(document->id);
|
||||
if (fillStickers) {
|
||||
set.stickers.push_back(document);
|
||||
if (!(set.flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
set->stickers.push_back(document);
|
||||
if (!(set->flags & MTPDstickerSet_ClientFlag::f_special)) {
|
||||
if (document->sticker()->set.type() != mtpc_inputStickerSetID) {
|
||||
document->sticker()->set = inputSet;
|
||||
}
|
||||
}
|
||||
++set.count;
|
||||
++set->count;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3715,17 +3713,17 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
|
||||
if (datesCount != scnt) {
|
||||
return failed();
|
||||
}
|
||||
const auto fillDates = (set.id == Stickers::CloudRecentSetId)
|
||||
&& (set.stickers.size() == datesCount);
|
||||
const auto fillDates = (set->id == Stickers::CloudRecentSetId)
|
||||
&& (set->stickers.size() == datesCount);
|
||||
if (fillDates) {
|
||||
set.dates.clear();
|
||||
set.dates.reserve(datesCount);
|
||||
set->dates.clear();
|
||||
set->dates.reserve(datesCount);
|
||||
}
|
||||
for (auto i = 0; i != datesCount; ++i) {
|
||||
qint32 date = 0;
|
||||
stickers.stream >> date;
|
||||
if (fillDates) {
|
||||
set.dates.push_back(TimeId(date));
|
||||
set->dates.push_back(TimeId(date));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3752,7 +3750,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
|
||||
if (fillStickers) {
|
||||
if (auto emoji = Ui::Emoji::Find(emojiString)) {
|
||||
emoji = emoji->original();
|
||||
set.emoji.insert(emoji, pack);
|
||||
set->emoji.insert(emoji, pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3785,10 +3783,11 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
|
||||
for (const auto setId : std::as_const(*outOrder)) {
|
||||
auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
it->flags |= readingFlags;
|
||||
const auto set = it->second.get();
|
||||
set->flags |= readingFlags;
|
||||
if ((readingFlags == MTPDstickerSet::Flag::f_installed_date)
|
||||
&& !it->installDate) {
|
||||
it->installDate = kDefaultStickerInstallDate;
|
||||
&& !set->installDate) {
|
||||
set->installDate = kDefaultStickerInstallDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3888,7 +3887,8 @@ void importOldRecentStickers() {
|
||||
auto &recent = cRefRecentStickers();
|
||||
recent.clear();
|
||||
|
||||
auto &def = sets.insert(Stickers::DefaultSetId, Stickers::Set(
|
||||
const auto def = sets.emplace(Stickers::DefaultSetId, std::make_unique<Stickers::Set>(
|
||||
&Auth().data(),
|
||||
Stickers::DefaultSetId,
|
||||
uint64(0),
|
||||
tr::lng_stickers_default_set(tr::now),
|
||||
@ -3898,9 +3898,9 @@ void importOldRecentStickers() {
|
||||
(MTPDstickerSet::Flag::f_official
|
||||
| MTPDstickerSet::Flag::f_installed_date
|
||||
| MTPDstickerSet_ClientFlag::f_special),
|
||||
kDefaultStickerInstallDate,
|
||||
ImagePtr())).value();
|
||||
auto &custom = sets.insert(Stickers::CustomSetId, Stickers::Set(
|
||||
kDefaultStickerInstallDate)).first->second.get();
|
||||
const auto custom = sets.emplace(Stickers::CustomSetId, std::make_unique<Stickers::Set>(
|
||||
&Auth().data(),
|
||||
Stickers::CustomSetId,
|
||||
uint64(0),
|
||||
qsl("Custom stickers"),
|
||||
@ -3909,8 +3909,7 @@ void importOldRecentStickers() {
|
||||
0, // hash
|
||||
(MTPDstickerSet::Flag::f_installed_date
|
||||
| MTPDstickerSet_ClientFlag::f_special),
|
||||
kDefaultStickerInstallDate,
|
||||
ImagePtr())).value();
|
||||
kDefaultStickerInstallDate)).first->second.get();
|
||||
|
||||
QMap<uint64, bool> read;
|
||||
while (!stickers.stream.atEnd()) {
|
||||
@ -3953,22 +3952,24 @@ void importOldRecentStickers() {
|
||||
}
|
||||
|
||||
if (value > 0) {
|
||||
def.stickers.push_back(doc);
|
||||
++def.count;
|
||||
def->stickers.push_back(doc);
|
||||
++def->count;
|
||||
} else {
|
||||
custom.stickers.push_back(doc);
|
||||
++custom.count;
|
||||
custom->stickers.push_back(doc);
|
||||
++custom->count;
|
||||
}
|
||||
if (recent.size() < Global::StickersRecentLimit() && qAbs(value) > 1) {
|
||||
recent.push_back(qMakePair(doc, qAbs(value)));
|
||||
}
|
||||
}
|
||||
if (def.stickers.isEmpty()) {
|
||||
if (def->stickers.isEmpty()) {
|
||||
sets.remove(Stickers::DefaultSetId);
|
||||
} else {
|
||||
order.push_front(Stickers::DefaultSetId);
|
||||
}
|
||||
if (custom.stickers.isEmpty()) sets.remove(Stickers::CustomSetId);
|
||||
if (custom->stickers.isEmpty()) {
|
||||
sets.remove(Stickers::CustomSetId);
|
||||
}
|
||||
|
||||
writeInstalledStickers();
|
||||
writeUserSettings();
|
||||
@ -3996,11 +3997,13 @@ void readFeaturedStickers() {
|
||||
&Auth().data().featuredStickerSetsOrderRef(),
|
||||
MTPDstickerSet::Flags() | MTPDstickerSet_ClientFlag::f_featured);
|
||||
|
||||
auto &sets = Auth().data().stickerSets();
|
||||
const auto &sets = Auth().data().stickerSets();
|
||||
const auto &order = Auth().data().featuredStickerSetsOrder();
|
||||
int unreadCount = 0;
|
||||
for_const (auto setId, Auth().data().featuredStickerSetsOrder()) {
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
for (const auto setId : order) {
|
||||
auto it = sets.find(setId);
|
||||
if (it != sets.cend()
|
||||
&& (it->second->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
++unreadCount;
|
||||
}
|
||||
}
|
||||
@ -4033,9 +4036,9 @@ int32 countDocumentVectorHash(const QVector<DocumentData*> vector) {
|
||||
|
||||
int32 countSpecialStickerSetHash(uint64 setId) {
|
||||
auto &sets = Auth().data().stickerSets();
|
||||
auto it = sets.constFind(setId);
|
||||
auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
return countDocumentVectorHash(it->stickers);
|
||||
return countDocumentVectorHash(it->second->stickers);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -4043,16 +4046,17 @@ int32 countSpecialStickerSetHash(uint64 setId) {
|
||||
int32 countStickersHash(bool checkOutdatedInfo) {
|
||||
auto result = Api::HashInit();
|
||||
bool foundOutdated = false;
|
||||
auto &sets = Auth().data().stickerSets();
|
||||
auto &order = Auth().data().stickerSetsOrder();
|
||||
const auto &sets = Auth().data().stickerSets();
|
||||
const auto &order = Auth().data().stickerSetsOrder();
|
||||
for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) {
|
||||
auto j = sets.constFind(*i);
|
||||
if (j != sets.cend()) {
|
||||
if (j->id == Stickers::DefaultSetId) {
|
||||
auto it = sets.find(*i);
|
||||
if (it != sets.cend()) {
|
||||
const auto set = it->second.get();
|
||||
if (set->id == Stickers::DefaultSetId) {
|
||||
foundOutdated = true;
|
||||
} else if (!(j->flags & MTPDstickerSet_ClientFlag::f_special)
|
||||
&& !(j->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
Api::HashUpdate(result, j->hash);
|
||||
} else if (!(set->flags & MTPDstickerSet_ClientFlag::f_special)
|
||||
&& !(set->flags & MTPDstickerSet::Flag::f_archived)) {
|
||||
Api::HashUpdate(result, set->hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4076,8 +4080,9 @@ int32 countFeaturedStickersHash() {
|
||||
for (const auto setId : featured) {
|
||||
Api::HashUpdate(result, setId);
|
||||
|
||||
auto it = sets.constFind(setId);
|
||||
if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
const auto it = sets.find(setId);
|
||||
if (it != sets.cend()
|
||||
&& (it->second->flags & MTPDstickerSet_ClientFlag::f_unread)) {
|
||||
Api::HashUpdate(result, 1);
|
||||
}
|
||||
}
|
||||
|
@ -175,74 +175,6 @@ ImagePtr Create(const StorageImageLocation &location, int size) {
|
||||
return Create<StorageSource>(location, size, QByteArray());
|
||||
}
|
||||
|
||||
struct CreateSetThumbnail {
|
||||
using Source = Stickers::ThumbnailSource;
|
||||
ImagePtr operator()(
|
||||
const StorageImageLocation &location,
|
||||
int size) {
|
||||
return Create<Source>(location, size, QByteArray());
|
||||
}
|
||||
ImagePtr operator()(
|
||||
const StorageImageLocation &location,
|
||||
const QByteArray &bytes) {
|
||||
return Create<Source>(location, bytes.size(), bytes);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CreateLocation, typename Method>
|
||||
ImagePtr CreateFromPhotoSize(
|
||||
CreateLocation &&createLocation,
|
||||
const MTPPhotoSize &size,
|
||||
Method method = Method()) {
|
||||
return size.match([&](const MTPDphotoSize &data) {
|
||||
const auto &location = data.vlocation().c_fileLocationToBeDeprecated();
|
||||
return method(
|
||||
StorageImageLocation(
|
||||
createLocation(data.vtype(), location),
|
||||
data.vw().v,
|
||||
data.vh().v),
|
||||
data.vsize().v);
|
||||
}, [&](const MTPDphotoCachedSize &data) {
|
||||
const auto bytes = qba(data.vbytes());
|
||||
const auto &location = data.vlocation().c_fileLocationToBeDeprecated();
|
||||
return method(
|
||||
StorageImageLocation(
|
||||
createLocation(data.vtype(), location),
|
||||
data.vw().v,
|
||||
data.vh().v),
|
||||
bytes);
|
||||
}, [&](const MTPDphotoStrippedSize &data) {
|
||||
auto image = FromInlineBytes(qba(data.vbytes()));
|
||||
return !image.isNull()
|
||||
? Images::Create(std::move(image), "JPG")
|
||||
: ImagePtr();
|
||||
}, [&](const MTPDphotoSizeEmpty &) {
|
||||
return ImagePtr();
|
||||
});
|
||||
}
|
||||
|
||||
ImagePtr Create(const MTPDstickerSet &set, const MTPPhotoSize &size) {
|
||||
const auto thumbDcId = set.vthumb_dc_id();
|
||||
const auto create = [&](
|
||||
const MTPstring &thumbSize,
|
||||
const MTPDfileLocationToBeDeprecated &location) {
|
||||
return StorageFileLocation(
|
||||
thumbDcId->v,
|
||||
Auth().userId(),
|
||||
MTP_inputStickerSetThumb(
|
||||
MTP_inputStickerSetID(set.vid(), set.vaccess_hash()),
|
||||
location.vvolume_id(),
|
||||
location.vlocal_id()));
|
||||
};
|
||||
return thumbDcId
|
||||
? CreateFromPhotoSize(create, size, CreateSetThumbnail())
|
||||
: ImagePtr();
|
||||
}
|
||||
|
||||
ImagePtr CreateStickerSetThumbnail(const StorageImageLocation &location) {
|
||||
return CreateSetThumbnail()(location, 0);
|
||||
}
|
||||
|
||||
QSize GetSizeForDocument(const QVector<MTPDocumentAttribute> &attributes) {
|
||||
for (const auto &attribute : attributes) {
|
||||
if (attribute.type() == mtpc_documentAttributeImageSize) {
|
||||
|
@ -378,6 +378,10 @@ bool StorageFileLocation::valid() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StorageFileLocation::isLegacy() const {
|
||||
return (_type == Type::Legacy);
|
||||
}
|
||||
|
||||
bool StorageFileLocation::isDocumentThumbnail() const {
|
||||
return (_type == Type::Document) && (_sizeLetter != 0);
|
||||
}
|
||||
@ -810,6 +814,12 @@ bool DownloadLocation::valid() const {
|
||||
});
|
||||
}
|
||||
|
||||
bool DownloadLocation::isLegacy() const {
|
||||
return data.is<StorageFileLocation>()
|
||||
? data.get_unchecked<StorageFileLocation>().isLegacy()
|
||||
: false;
|
||||
}
|
||||
|
||||
QByteArray DownloadLocation::fileReference() const {
|
||||
if (!data.is<StorageFileLocation>()) {
|
||||
return QByteArray();
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
|
||||
[[nodiscard]] Type type() const;
|
||||
[[nodiscard]] bool valid() const;
|
||||
[[nodiscard]] bool isLegacy() const;
|
||||
[[nodiscard]] Storage::Cache::Key cacheKey() const;
|
||||
[[nodiscard]] Storage::Cache::Key bigFileBaseCacheKey() const;
|
||||
|
||||
@ -184,6 +185,9 @@ public:
|
||||
[[nodiscard]] bool valid() const {
|
||||
return _file.valid();
|
||||
}
|
||||
[[nodiscard]] bool isLegacy() const {
|
||||
return _file.isLegacy();
|
||||
}
|
||||
[[nodiscard]] QByteArray fileReference() const {
|
||||
return _file.fileReference();
|
||||
}
|
||||
@ -413,6 +417,7 @@ public:
|
||||
|
||||
[[nodiscard]] Storage::Cache::Key cacheKey() const;
|
||||
[[nodiscard]] bool valid() const;
|
||||
[[nodiscard]] bool isLegacy() const;
|
||||
[[nodiscard]] QByteArray fileReference() const;
|
||||
bool refreshFileReference(const QByteArray &data);
|
||||
bool refreshFileReference(const Data::UpdatedFileReferences &updates);
|
||||
@ -472,6 +477,9 @@ public:
|
||||
[[nodiscard]] bool valid() const {
|
||||
return _file.valid();
|
||||
}
|
||||
[[nodiscard]] bool isLegacy() const {
|
||||
return _file.isLegacy();
|
||||
}
|
||||
[[nodiscard]] QByteArray fileReference() const {
|
||||
return _file.fileReference();
|
||||
}
|
||||
|
@ -136,6 +136,68 @@ ImageWithLocation FromPhotoSize(
|
||||
});
|
||||
}
|
||||
|
||||
ImageWithLocation FromPhotoSize(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDstickerSet &set,
|
||||
const MTPPhotoSize &size) {
|
||||
if (!set.vthumb_dc_id()) {
|
||||
return ImageWithLocation();
|
||||
}
|
||||
return size.match([&](const MTPDphotoSize &data) {
|
||||
const auto &location = data.vlocation().c_fileLocationToBeDeprecated();
|
||||
return ImageWithLocation{
|
||||
.location = ImageLocation(
|
||||
DownloadLocation{ StorageFileLocation(
|
||||
set.vthumb_dc_id()->v,
|
||||
session->userId(),
|
||||
MTP_inputStickerSetThumb(
|
||||
MTP_inputStickerSetID(set.vid(), set.vaccess_hash()),
|
||||
location.vvolume_id(),
|
||||
location.vlocal_id())) },
|
||||
data.vw().v,
|
||||
data.vh().v),
|
||||
.bytesCount = data.vsize().v
|
||||
};
|
||||
}, [&](const MTPDphotoCachedSize &data) {
|
||||
const auto &location = data.vlocation().c_fileLocationToBeDeprecated();
|
||||
const auto bytes = qba(data.vbytes());
|
||||
return ImageWithLocation{
|
||||
.location = ImageLocation(
|
||||
DownloadLocation{ StorageFileLocation(
|
||||
set.vthumb_dc_id()->v,
|
||||
session->userId(),
|
||||
MTP_inputStickerSetThumb(
|
||||
MTP_inputStickerSetID(set.vid(), set.vaccess_hash()),
|
||||
location.vvolume_id(),
|
||||
location.vlocal_id())) },
|
||||
data.vw().v,
|
||||
data.vh().v),
|
||||
.bytesCount = bytes.size(),
|
||||
.bytes = bytes
|
||||
};
|
||||
}, [&](const MTPDphotoStrippedSize &data) {
|
||||
return ImageWithLocation();
|
||||
//const auto bytes = ExpandInlineBytes(qba(data.vbytes()));
|
||||
//return ImageWithLocation{
|
||||
// .location = ImageLocation(
|
||||
// DownloadLocation{ StorageFileLocation(
|
||||
// document.vdc_id().v,
|
||||
// session->userId(),
|
||||
// MTP_inputDocumentFileLocation(
|
||||
// document.vid(),
|
||||
// document.vaccess_hash(),
|
||||
// document.vfile_reference(),
|
||||
// data.vtype())) },
|
||||
// width, // ???
|
||||
// height), // ???
|
||||
// .bytesCount = bytes.size(),
|
||||
// .bytes = bytes
|
||||
//};
|
||||
}, [&](const MTPDphotoSizeEmpty &) {
|
||||
return ImageWithLocation();
|
||||
});
|
||||
}
|
||||
|
||||
ImageWithLocation FromImageInMemory(
|
||||
const QImage &image,
|
||||
const char *format) {
|
||||
|
@ -23,6 +23,10 @@ namespace Images {
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDdocument &document,
|
||||
const MTPPhotoSize &size);
|
||||
[[nodiscard]] ImageWithLocation FromPhotoSize(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDstickerSet &set,
|
||||
const MTPPhotoSize &size);
|
||||
[[nodiscard]] ImageWithLocation FromVideoSize(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDdocument &document,
|
||||
|
@ -445,7 +445,7 @@ void EditorBlock::enumerateRows(Callback callback) const {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for_const (auto &row, _data) {
|
||||
for (const auto &row : _data) {
|
||||
if (!callback(row)) {
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user