2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-09-05 00:55:12 +00:00

Version bumped to 0.9.61 stable.

Merge branch 'archived_stickers' into cancel_reset.

Conflicts:
	Telegram/Resources/winrc/Telegram.rc
	Telegram/Resources/winrc/Updater.rc
	Telegram/SourceFiles/app.cpp
	Telegram/SourceFiles/core/version.h
	Telegram/SourceFiles/localstorage.cpp
	Telegram/Telegram.vcxproj.filters
	Telegram/Telegram.xcodeproj/project.pbxproj
	Telegram/build/version
This commit is contained in:
John Preston
2016-07-25 22:54:40 +03:00
61 changed files with 3998 additions and 1344 deletions

View File

@@ -479,11 +479,12 @@ namespace {
lskBackground = 0x08, // no data
lskUserSettings = 0x09, // no data
lskRecentHashtagsAndBots = 0x0a, // no data
lskStickers = 0x0b, // no data
lskStickersOld = 0x0b, // no data
lskSavedPeers = 0x0c, // no data
lskReportSpamStatuses = 0x0d, // no data
lskSavedGifsOld = 0x0e, // no data
lskSavedGifs = 0x0f, // no data
lskStickersKeys = 0x10, // no data
};
enum {
@@ -542,6 +543,7 @@ namespace {
dbiDialogsMode = 0x40,
dbiModerateMode = 0x41,
dbiVideoVolume = 0x42,
dbiStickersRecentLimit = 0x43,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,
@@ -571,7 +573,9 @@ namespace {
uint64 _storageWebFilesSize = 0;
FileKey _locationsKey = 0, _reportSpamStatusesKey = 0;
FileKey _recentStickersKeyOld = 0, _stickersKey = 0, _savedGifsKey = 0;
FileKey _recentStickersKeyOld = 0;
FileKey _installedStickersKey = 0, _featuredStickersKey = 0, _recentStickersKey = 0, _archivedStickersKey = 0;
FileKey _savedGifsKey = 0;
FileKey _backgroundKey = 0;
bool _backgroundWasRead = false;
@@ -835,6 +839,14 @@ namespace {
Global::SetSavedGifsLimit(limit);
} break;
case dbiStickersRecentLimit: {
qint32 limit;
stream >> limit;
if (!_checkStreamStatus(stream)) return false;
Global::SetStickersRecentLimit(limit);
} break;
case dbiMegagroupSizeMax: {
qint32 maxSize;
stream >> maxSize;
@@ -1725,7 +1737,9 @@ namespace {
StorageMap imagesMap, stickerImagesMap, audiosMap;
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
quint64 locationsKey = 0, reportSpamStatusesKey = 0;
quint64 recentStickersKeyOld = 0, stickersKey = 0, savedGifsKey = 0;
quint64 recentStickersKeyOld = 0;
quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, archivedStickersKey = 0;
quint64 savedGifsKey = 0;
quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0;
while (!map.stream.atEnd()) {
quint32 keyType;
@@ -1806,8 +1820,11 @@ namespace {
case lskRecentHashtagsAndBots: {
map.stream >> recentHashtagsAndBotsKey;
} break;
case lskStickers: {
map.stream >> stickersKey;
case lskStickersOld: {
map.stream >> installedStickersKey;
} break;
case lskStickersKeys: {
map.stream >> installedStickersKey >> featuredStickersKey >> recentStickersKey >> archivedStickersKey;
} break;
case lskSavedGifsOld: {
quint64 key;
@@ -1842,7 +1859,10 @@ namespace {
_locationsKey = locationsKey;
_reportSpamStatusesKey = reportSpamStatusesKey;
_recentStickersKeyOld = recentStickersKeyOld;
_stickersKey = stickersKey;
_installedStickersKey = installedStickersKey;
_featuredStickersKey = featuredStickersKey;
_recentStickersKey = recentStickersKey;
_archivedStickersKey = archivedStickersKey;
_savedGifsKey = savedGifsKey;
_savedPeersKey = savedPeersKey;
_backgroundKey = backgroundKey;
@@ -1915,7 +1935,9 @@ namespace {
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_reportSpamStatusesKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_recentStickersKeyOld) mapSize += sizeof(quint32) + sizeof(quint64);
if (_stickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
mapSize += sizeof(quint32) + 4 * sizeof(quint64);
}
if (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
@@ -1961,8 +1983,9 @@ namespace {
if (_recentStickersKeyOld) {
mapData.stream << quint32(lskRecentStickersOld) << quint64(_recentStickersKeyOld);
}
if (_stickersKey) {
mapData.stream << quint32(lskStickers) << quint64(_stickersKey);
if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
mapData.stream << quint32(lskStickersKeys);
mapData.stream << quint64(_installedStickersKey) << quint64(_featuredStickersKey) << quint64(_recentStickersKey) << quint64(_archivedStickersKey);
}
if (_savedGifsKey) {
mapData.stream << quint32(lskSavedGifs) << quint64(_savedGifsKey);
@@ -2185,12 +2208,13 @@ namespace Local {
size += Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password);
}
size += sizeof(quint32) + sizeof(qint32) * 6;
size += sizeof(quint32) + sizeof(qint32) * 7;
EncryptedDescriptor data(size);
data.stream << quint32(dbiChatSizeMax) << qint32(Global::ChatSizeMax());
data.stream << quint32(dbiMegagroupSizeMax) << qint32(Global::MegagroupSizeMax());
data.stream << quint32(dbiSavedGifsLimit) << qint32(Global::SavedGifsLimit());
data.stream << quint32(dbiStickersRecentLimit) << qint32(Global::StickersRecentLimit());
data.stream << quint32(dbiAutoStart) << qint32(cAutoStart());
data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized());
data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu());
@@ -2247,7 +2271,9 @@ namespace Local {
_webFilesMap.clear();
_storageWebFilesSize = 0;
_locationsKey = _reportSpamStatusesKey = 0;
_recentStickersKeyOld = _stickersKey = _savedGifsKey = 0;
_recentStickersKeyOld = 0;
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0;
_savedGifsKey = 0;
_backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0;
_oldMapVersion = _oldSettingsVersion = 0;
_mapChanged = true;
@@ -3017,26 +3043,23 @@ namespace Local {
}
}
void _writeStickerSet(QDataStream &stream, uint64 setId) {
auto it = Global::StickerSets().constFind(setId);
if (it == Global::StickerSets().cend()) return;
bool notLoaded = (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded);
void _writeStickerSet(QDataStream &stream, const Stickers::Set &set) {
bool notLoaded = (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded);
if (notLoaded) {
stream << quint64(it->id) << quint64(it->access) << it->title << it->shortName << qint32(-it->count) << qint32(it->hash) << qint32(it->flags);
stream << quint64(set.id) << quint64(set.access) << set.title << set.shortName << qint32(-set.count) << qint32(set.hash) << qint32(set.flags);
return;
} else {
if (it->stickers.isEmpty()) return;
if (set.stickers.isEmpty()) return;
}
stream << quint64(it->id) << quint64(it->access) << it->title << it->shortName << qint32(it->stickers.size()) << qint32(it->hash) << qint32(it->flags);
for (StickerPack::const_iterator j = it->stickers.cbegin(), e = it->stickers.cend(); j != e; ++j) {
stream << quint64(set.id) << quint64(set.access) << set.title << set.shortName << qint32(set.stickers.size()) << qint32(set.hash) << qint32(set.flags);
for (StickerPack::const_iterator j = set.stickers.cbegin(), e = set.stickers.cend(); j != e; ++j) {
Serialize::Document::writeToStream(stream, *j);
}
if (AppVersion > 9018) {
stream << qint32(it->emoji.size());
for (StickersByEmojiMap::const_iterator j = it->emoji.cbegin(), e = it->emoji.cend(); j != e; ++j) {
stream << qint32(set.emoji.size());
for (StickersByEmojiMap::const_iterator j = set.emoji.cbegin(), e = set.emoji.cend(); j != e; ++j) {
stream << emojiString(j.key()) << qint32(j->size());
for (int32 k = 0, l = j->size(); k < l; ++k) {
stream << quint64(j->at(k)->id);
@@ -3045,61 +3068,274 @@ namespace Local {
}
}
void writeStickers() {
// In generic method _writeStickerSets() we look through all the sets and call a
// callback on each set to see, if we write it, skip it or abort the whole write.
enum class StickerSetCheckResult {
Write,
Skip,
Abort,
};
// CheckSet is a functor on Stickers::Set, which returns a StickerSetCheckResult.
template <typename CheckSet>
void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::Order &order) {
if (!_working()) return;
const Stickers::Sets &sets(Global::StickerSets());
auto &sets = Global::StickerSets();
if (sets.isEmpty()) {
if (_stickersKey) {
clearKey(_stickersKey);
_stickersKey = 0;
if (stickersKey) {
clearKey(stickersKey);
stickersKey = 0;
_mapChanged = true;
}
_writeMap();
} else {
int32 setsCount = 0;
QByteArray hashToWrite;
quint32 size = sizeof(quint32) + Serialize::bytearraySize(hashToWrite);
for (auto i = sets.cbegin(); i != sets.cend(); ++i) {
bool notLoaded = (i->flags & MTPDstickerSet_ClientFlag::f_not_loaded);
if (notLoaded) {
if (!(i->flags & MTPDstickerSet::Flag::f_disabled) || (i->flags & MTPDstickerSet::Flag::f_official)) { // waiting to receive
return;
}
} else {
if (i->stickers.isEmpty()) continue;
}
// id + access + title + shortName + stickersCount + hash + flags
size += sizeof(quint64) * 2 + Serialize::stringSize(i->title) + Serialize::stringSize(i->shortName) + sizeof(quint32) + sizeof(qint32) * 2;
for (StickerPack::const_iterator j = i->stickers.cbegin(), e = i->stickers.cend(); j != e; ++j) {
size += Serialize::Document::sizeInStream(*j);
}
if (AppVersion > 9018) {
size += sizeof(qint32); // emojiCount
for (StickersByEmojiMap::const_iterator j = i->emoji.cbegin(), e = i->emoji.cend(); j != e; ++j) {
size += Serialize::stringSize(emojiString(j.key())) + sizeof(qint32) + (j->size() * sizeof(quint64));
}
}
++setsCount;
}
if (!_stickersKey) {
_stickersKey = genKey();
_mapChanged = true;
_writeMap(WriteMapFast);
}
EncryptedDescriptor data(size);
data.stream << quint32(setsCount) << hashToWrite;
_writeStickerSet(data.stream, Stickers::CustomSetId);
for (auto i = Global::StickerSetsOrder().cbegin(), e = Global::StickerSetsOrder().cend(); i != e; ++i) {
_writeStickerSet(data.stream, *i);
}
FileWriteDescriptor file(_stickersKey);
file.writeEncrypted(data);
return;
}
int32 setsCount = 0;
QByteArray hashToWrite;
quint32 size = sizeof(quint32) + Serialize::bytearraySize(hashToWrite);
for_const (auto &set, sets) {
auto result = checkSet(set);
if (result == StickerSetCheckResult::Abort) {
return;
} else if (result == StickerSetCheckResult::Skip) {
continue;
}
// id + access + title + shortName + stickersCount + hash + flags
size += sizeof(quint64) * 2 + Serialize::stringSize(set.title) + Serialize::stringSize(set.shortName) + sizeof(quint32) + sizeof(qint32) * 2;
for_const (auto &sticker, set.stickers) {
size += Serialize::Document::sizeInStream(sticker);
}
size += sizeof(qint32); // emojiCount
for (auto j = set.emoji.cbegin(), e = set.emoji.cend(); j != e; ++j) {
size += Serialize::stringSize(emojiString(j.key())) + sizeof(qint32) + (j->size() * sizeof(quint64));
}
++setsCount;
}
if (!setsCount && order.isEmpty()) {
if (stickersKey) {
clearKey(stickersKey);
stickersKey = 0;
_mapChanged = true;
}
_writeMap();
return;
}
size += sizeof(qint32) + (order.size() * sizeof(quint64));
if (!stickersKey) {
stickersKey = genKey();
_mapChanged = true;
_writeMap(WriteMapFast);
}
EncryptedDescriptor data(size);
data.stream << quint32(setsCount) << hashToWrite;
for_const (auto &set, sets) {
auto result = checkSet(set);
if (result == StickerSetCheckResult::Abort) {
return;
} else if (result == StickerSetCheckResult::Skip) {
continue;
}
_writeStickerSet(data.stream, set);
}
data.stream << order;
FileWriteDescriptor file(stickersKey);
file.writeEncrypted(data);
}
void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, MTPDstickerSet::Flags readingFlags = 0) {
FileReadDescriptor stickers;
if (!readEncryptedFile(stickers, stickersKey)) {
clearKey(stickersKey);
stickersKey = 0;
_writeMap();
return;
}
bool readingInstalled = (readingFlags == qFlags(MTPDstickerSet::Flag::f_installed));
auto &sets = Global::RefStickerSets();
if (outOrder) outOrder->clear();
quint32 cnt;
QByteArray hash;
stickers.stream >> cnt >> hash; // ignore hash, it is counted
if (readingInstalled && stickers.version < 8019) { // bad data in old caches
cnt += 2; // try to read at least something
}
for (uint32 i = 0; i < cnt; ++i) {
quint64 setId = 0, setAccess = 0;
QString setTitle, setShortName;
qint32 scnt = 0;
stickers.stream >> setId >> setAccess >> setTitle >> setShortName >> scnt;
qint32 setHash = 0, setFlags = 0;
if (stickers.version > 8033) {
stickers.stream >> setHash >> setFlags;
if (setFlags & qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old)) {
setFlags &= ~qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old);
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_not_loaded);
}
}
if (readingInstalled && stickers.version < 9061) {
setFlags |= qFlags(MTPDstickerSet::Flag::f_installed);
}
if (setId == Stickers::DefaultSetId) {
setTitle = lang(lng_stickers_default_set);
setFlags |= qFlags(MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special);
if (readingInstalled && outOrder && stickers.version < 9061) {
outOrder->push_front(setId);
}
} else if (setId == Stickers::CustomSetId) {
setTitle = lang(lng_custom_stickers);
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_special);
} else if (setId == Stickers::CloudRecentSetId) {
setTitle = lang(lng_emoji_category0); // Frequently used
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_special);
} else if (setId) {
if (readingInstalled && outOrder && stickers.version < 9061) {
outOrder->push_back(setId);
}
} else {
continue;
}
auto it = sets.find(setId);
if (it == sets.cend()) {
// We will set this flags from order lists when reading those stickers.
setFlags &= ~(MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_featured);
it = sets.insert(setId, Stickers::Set(setId, setAccess, setTitle, setShortName, 0, setHash, MTPDstickerSet::Flags(setFlags)));
}
auto &set = it.value();
if (scnt < 0) { // disabled not loaded set
if (!set.count || set.stickers.isEmpty()) {
set.count = -scnt;
}
continue;
}
bool fillStickers = set.stickers.isEmpty();
if (fillStickers) {
set.stickers.reserve(scnt);
set.count = 0;
}
Serialize::Document::StickerSetInfo info(setId, setAccess, setShortName);
OrderedSet<DocumentId> read;
for (int32 j = 0; j < scnt; ++j) {
auto document = Serialize::Document::readStickerFromStream(stickers.version, stickers.stream, info);
if (!document || !document->sticker()) continue;
if (read.contains(document->id)) continue;
read.insert(document->id);
if (fillStickers) {
set.stickers.push_back(document);
++set.count;
}
}
if (stickers.version > 9018) {
qint32 emojiCount;
stickers.stream >> emojiCount;
for (int32 j = 0; j < emojiCount; ++j) {
QString emojiString;
qint32 stickersCount;
stickers.stream >> emojiString >> stickersCount;
StickerPack pack;
pack.reserve(stickersCount);
for (int32 k = 0; k < stickersCount; ++k) {
quint64 id;
stickers.stream >> id;
DocumentData *doc = App::document(id);
if (!doc || !doc->sticker()) continue;
pack.push_back(doc);
}
if (fillStickers) {
if (auto e = emojiGetNoColor(emojiFromText(emojiString))) {
set.emoji.insert(e, pack);
}
}
}
}
}
// Read orders of installed and featured stickers.
if (outOrder && stickers.version >= 9061) {
stickers.stream >> *outOrder;
}
// Set flags that we dropped above from the order.
if (readingFlags && outOrder) {
for_const (auto setId, *outOrder) {
auto it = sets.find(setId);
if (it != sets.cend()) {
it->flags |= readingFlags;
}
}
}
}
void writeInstalledStickers() {
_writeStickerSets(_installedStickersKey, [](const Stickers::Set &set) {
if (set.id == Stickers::CloudRecentSetId) { // separate file for recent
return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
if (set.stickers.isEmpty()) { // all other special are "installed"
return StickerSetCheckResult::Skip;
}
} else if (!(set.flags & MTPDstickerSet::Flag::f_installed) || (set.flags & MTPDstickerSet::Flag::f_archived)) {
return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded) { // waiting to receive
return StickerSetCheckResult::Abort;
} else if (set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip;
}
return StickerSetCheckResult::Write;
}, Global::StickerSetsOrder());
}
void writeFeaturedStickers() {
_writeStickerSets(_featuredStickersKey, [](const Stickers::Set &set) {
if (set.id == Stickers::CloudRecentSetId) { // separate file for recent
return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
return StickerSetCheckResult::Skip;
} else if (!(set.flags & MTPDstickerSet_ClientFlag::f_featured)) {
return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_not_loaded) { // waiting to receive
return StickerSetCheckResult::Abort;
} else if (set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip;
}
return StickerSetCheckResult::Write;
}, Global::FeaturedStickerSetsOrder());
}
void writeRecentStickers() {
_writeStickerSets(_recentStickersKey, [](const Stickers::Set &set) {
if (set.id != Stickers::CloudRecentSetId || set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip;
}
return StickerSetCheckResult::Write;
}, Stickers::Order());
}
void writeArchivedStickers() {
_writeStickerSets(_archivedStickersKey, [](const Stickers::Set &set) {
if (!(set.flags & MTPDstickerSet::Flag::f_archived) || set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip;
}
return StickerSetCheckResult::Write;
}, Global::ArchivedStickerSetsOrder());
}
void importOldRecentStickers() {
@@ -3113,17 +3349,17 @@ namespace Local {
return;
}
Stickers::Sets &sets(Global::RefStickerSets());
auto &sets = Global::RefStickerSets();
sets.clear();
Stickers::Order &order(Global::RefStickerSetsOrder());
auto &order = Global::RefStickerSetsOrder();
order.clear();
RecentStickerPack &recent(cRefRecentStickers());
auto &recent = cRefRecentStickers();
recent.clear();
Stickers::Set &def(sets.insert(Stickers::DefaultSetId, Stickers::Set(Stickers::DefaultSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::Flag::f_official)).value());
Stickers::Set &custom(sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, 0)).value());
auto &def = sets.insert(Stickers::DefaultSetId, Stickers::Set(Stickers::DefaultSetId, 0, lang(lng_stickers_default_set), QString(), 0, 0, MTPDstickerSet::Flag::f_official | MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_special)).value();
auto &custom = sets.insert(Stickers::CustomSetId, Stickers::Set(Stickers::CustomSetId, 0, lang(lng_custom_stickers), QString(), 0, 0, MTPDstickerSet::Flag::f_installed | MTPDstickerSet_ClientFlag::f_special)).value();
QMap<uint64, bool> read;
while (!stickers.stream.atEnd()) {
@@ -3149,7 +3385,7 @@ namespace Local {
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
}
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation());
DocumentData *doc = App::documentSet(id, 0, access, 0, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation());
if (!doc->sticker()) continue;
if (value > 0) {
@@ -3159,7 +3395,9 @@ namespace Local {
custom.stickers.push_back(doc);
++custom.count;
}
if (recent.size() < StickerPanPerRow * StickerPanRowsPerPage && qAbs(value) > 1) recent.push_back(qMakePair(doc, qAbs(value)));
if (recent.size() < Global::StickersRecentLimit() && qAbs(value) > 1) {
recent.push_back(qMakePair(doc, qAbs(value)));
}
}
if (def.stickers.isEmpty()) {
sets.remove(Stickers::DefaultSetId);
@@ -3168,7 +3406,7 @@ namespace Local {
}
if (custom.stickers.isEmpty()) sets.remove(Stickers::CustomSetId);
writeStickers();
writeInstalledStickers();
writeUserSettings();
clearKey(_recentStickersKeyOld);
@@ -3176,130 +3414,95 @@ namespace Local {
_writeMap();
}
void readStickers() {
if (!_stickersKey) {
void readInstalledStickers() {
if (!_installedStickersKey) {
return importOldRecentStickers();
}
FileReadDescriptor stickers;
if (!readEncryptedFile(stickers, _stickersKey)) {
clearKey(_stickersKey);
_stickersKey = 0;
_writeMap();
return;
Global::RefStickerSets().clear();
_readStickerSets(_installedStickersKey, &Global::RefStickerSetsOrder(), qFlags(MTPDstickerSet::Flag::f_installed));
}
void readFeaturedStickers() {
_readStickerSets(_featuredStickersKey, &Global::RefFeaturedStickerSetsOrder(), qFlags(MTPDstickerSet_ClientFlag::f_featured));
auto &sets = Global::StickerSets();
int unreadCount = 0;
for_const (auto setId, Global::FeaturedStickerSetsOrder()) {
auto it = sets.constFind(setId);
if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
++unreadCount;
}
}
Global::SetFeaturedStickerSetsUnreadCount(unreadCount);
}
Stickers::Sets &sets(Global::RefStickerSets());
sets.clear();
void readRecentStickers() {
_readStickerSets(_recentStickersKey);
}
Stickers::Order &order(Global::RefStickerSetsOrder());
order.clear();
quint32 cnt;
QByteArray hash;
stickers.stream >> cnt >> hash; // ignore hash, it is counted
if (stickers.version < 8019) { // bad data in old caches
cnt += 2; // try to read at least something
}
for (uint32 i = 0; i < cnt; ++i) {
quint64 setId = 0, setAccess = 0;
QString setTitle, setShortName;
qint32 scnt = 0;
stickers.stream >> setId >> setAccess >> setTitle >> setShortName >> scnt;
qint32 setHash = 0, setFlags = 0;
if (stickers.version > 8033) {
stickers.stream >> setHash >> setFlags;
if (setFlags & qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old)) {
setFlags &= ~qFlags(MTPDstickerSet_ClientFlag::f_not_loaded__old);
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_not_loaded);
}
}
if (setId == Stickers::DefaultSetId) {
setTitle = lang(lng_stickers_default_set);
setFlags |= qFlags(MTPDstickerSet::Flag::f_official);
order.push_front(setId);
} else if (setId == Stickers::CustomSetId) {
setTitle = lang(lng_custom_stickers);
} else if (setId) {
order.push_back(setId);
} else {
continue;
}
Stickers::Set &set(sets.insert(setId, Stickers::Set(setId, setAccess, setTitle, setShortName, 0, setHash, MTPDstickerSet::Flags(setFlags))).value());
if (scnt < 0) { // disabled not loaded set
set.count = -scnt;
continue;
}
set.stickers.reserve(scnt);
Serialize::Document::StickerSetInfo info(setId, setAccess, setShortName);
OrderedSet<DocumentId> read;
for (int32 j = 0; j < scnt; ++j) {
auto document = Serialize::Document::readStickerFromStream(stickers.stream, info);
if (!document || !document->sticker()) continue;
if (read.contains(document->id)) continue;
read.insert(document->id);
set.stickers.push_back(document);
++set.count;
}
if (stickers.version > 9018) {
qint32 emojiCount;
stickers.stream >> emojiCount;
for (int32 j = 0; j < emojiCount; ++j) {
QString emojiString;
qint32 stickersCount;
stickers.stream >> emojiString >> stickersCount;
StickerPack pack;
pack.reserve(stickersCount);
for (int32 k = 0; k < stickersCount; ++k) {
quint64 id;
stickers.stream >> id;
DocumentData *doc = App::document(id);
if (!doc || !doc->sticker()) continue;
pack.push_back(doc);
}
if (EmojiPtr e = emojiGetNoColor(emojiFromText(emojiString))) {
set.emoji.insert(e, pack);
}
}
}
void readArchivedStickers() {
static bool archivedStickersRead = false;
if (!archivedStickersRead) {
_readStickerSets(_archivedStickersKey, &Global::RefArchivedStickerSetsOrder());
archivedStickersRead = true;
}
}
int32 countStickersHash(bool checkOfficial) {
int32 countStickersHash(bool checkOutdatedInfo) {
uint32 acc = 0;
bool foundOfficial = false, foundBad = false;;
const Stickers::Sets &sets(Global::StickerSets());
const Stickers::Order &order(Global::StickerSetsOrder());
bool foundOutdated = false;
auto &sets = Global::StickerSets();
auto &order = Global::StickerSetsOrder();
for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) {
auto j = sets.constFind(*i);
if (j != sets.cend()) {
if (j->id == 0) {
foundBad = true;
} else if (j->flags & MTPDstickerSet::Flag::f_official) {
foundOfficial = true;
}
if (!(j->flags & MTPDstickerSet::Flag::f_disabled)) {
if (j->id == Stickers::DefaultSetId) {
foundOutdated = true;
} else if (!(j->flags & MTPDstickerSet_ClientFlag::f_special)
&& !(j->flags & MTPDstickerSet::Flag::f_archived)) {
acc = (acc * 20261) + j->hash;
}
}
}
return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0;
return (!checkOutdatedInfo || !foundOutdated) ? int32(acc & 0x7FFFFFFF) : 0;
}
int32 countRecentStickersHash() {
uint32 acc = 0;
auto &sets = Global::StickerSets();
auto it = sets.constFind(Stickers::CloudRecentSetId);
if (it != sets.cend()) {
for_const (auto doc, it->stickers) {
auto docId = doc->id;
acc = (acc * 20261) + uint32(docId >> 32);
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
}
}
return int32(acc & 0x7FFFFFFF);
}
int32 countFeaturedStickersHash() {
uint32 acc = 0;
auto &sets = Global::StickerSets();
auto &featured = Global::FeaturedStickerSetsOrder();
for_const (auto setId, featured) {
acc = (acc * 20261) + uint32(setId >> 32);
acc = (acc * 20261) + uint32(setId & 0xFFFFFFFF);
auto it = sets.constFind(setId);
if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
acc = (acc * 20261) + 1U;
}
}
return int32(acc & 0x7FFFFFFF);
}
int32 countSavedGifsHash() {
uint32 acc = 0;
const SavedGifs &saved(cSavedGifs());
for (SavedGifs::const_iterator i = saved.cbegin(), e = saved.cend(); i != e; ++i) {
uint64 docId = (*i)->id;
auto &saved = cSavedGifs();
for_const (auto doc, saved) {
auto docId = doc->id;
acc = (acc * 20261) + uint32(docId >> 32);
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
}
@@ -3357,7 +3560,7 @@ namespace Local {
saved.reserve(cnt);
OrderedSet<DocumentId> read;
for (uint32 i = 0; i < cnt; ++i) {
DocumentData *document = Serialize::Document::readFromStream(gifs.stream);
DocumentData *document = Serialize::Document::readFromStream(gifs.version, gifs.stream);
if (!document || !document->isAnimation()) continue;
if (read.contains(document->id)) continue;
@@ -3862,8 +4065,8 @@ namespace Local {
_recentStickersKeyOld = 0;
_mapChanged = true;
}
if (_stickersKey) {
_stickersKey = 0;
if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0;
_mapChanged = true;
}
if (_recentHashtagsAndBotsKey) {