mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 14:38:15 +00:00
sticker packs done
This commit is contained in:
@@ -21,6 +21,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||
#include "lang.h"
|
||||
|
||||
namespace {
|
||||
enum StickerSetType {
|
||||
StickerSetTypeEmpty = 0,
|
||||
StickerSetTypeID = 1,
|
||||
StickerSetTypeShortName = 2,
|
||||
};
|
||||
|
||||
typedef quint64 FileKey;
|
||||
|
||||
@@ -140,6 +145,10 @@ namespace {
|
||||
return sizeof(quint32) + str.size() * sizeof(ushort);
|
||||
}
|
||||
|
||||
uint32 _bytearraySize(const QByteArray &arr) {
|
||||
return sizeof(quint32) + arr.size();
|
||||
}
|
||||
|
||||
QByteArray _settingsSalt, _passKeySalt, _passKeyEncrypted;
|
||||
|
||||
mtpAuthKey _oldKey, _settingsKey, _passKey, _localKey;
|
||||
@@ -484,17 +493,18 @@ namespace {
|
||||
FileKey _dataNameKey = 0;
|
||||
|
||||
enum { // Local Storage Keys
|
||||
lskUserMap = 0,
|
||||
lskDraft, // data: PeerId peer
|
||||
lskDraftPosition, // data: PeerId peer
|
||||
lskImages, // data: StorageKey location
|
||||
lskLocations, // no data
|
||||
lskStickers, // data: StorageKey location
|
||||
lskAudios, // data: StorageKey location
|
||||
lskRecentStickers, // no data
|
||||
lskBackground, // no data
|
||||
lskUserSettings, // no data
|
||||
lskRecentHashtags, // no data
|
||||
lskUserMap = 0x00,
|
||||
lskDraft = 0x01, // data: PeerId peer
|
||||
lskDraftPosition = 0x02, // data: PeerId peer
|
||||
lskImages = 0x03, // data: StorageKey location
|
||||
lskLocations = 0x04, // no data
|
||||
lskStickerImages = 0x05, // data: StorageKey location
|
||||
lskAudios = 0x06, // data: StorageKey location
|
||||
lskRecentStickersOld = 0x07, // no data
|
||||
lskBackground = 0x08, // no data
|
||||
lskUserSettings = 0x09, // no data
|
||||
lskRecentHashtags = 0x0a, // no data
|
||||
lskStickers = 0x0b, // no data
|
||||
};
|
||||
|
||||
typedef QMap<PeerId, FileKey> DraftsMap;
|
||||
@@ -509,7 +519,7 @@ namespace {
|
||||
FileLocationPairs _fileLocationPairs;
|
||||
FileKey _locationsKey = 0;
|
||||
|
||||
FileKey _recentStickersKey = 0;
|
||||
FileKey _recentStickersKeyOld = 0, _stickersKey = 0;
|
||||
|
||||
FileKey _backgroundKey = 0;
|
||||
bool _backgroundWasRead = false;
|
||||
@@ -520,7 +530,7 @@ namespace {
|
||||
|
||||
typedef QPair<FileKey, qint32> FileDesc; // file, size
|
||||
typedef QMap<StorageKey, FileDesc> StorageMap;
|
||||
StorageMap _imagesMap, _stickersMap, _audiosMap;
|
||||
StorageMap _imagesMap, _stickerImagesMap, _audiosMap;
|
||||
int32 _storageImagesSize = 0, _storageStickersSize = 0, _storageAudiosSize = 0;
|
||||
|
||||
bool _mapChanged = false;
|
||||
@@ -585,7 +595,7 @@ namespace {
|
||||
locations.stream >> first >> second >> type >> loc.name >> loc.modified >> loc.size;
|
||||
|
||||
MediaKey key(first, second);
|
||||
loc.type = type;
|
||||
loc.type = StorageFileType(type);
|
||||
|
||||
if (loc.check()) {
|
||||
_fileLocations.insert(key, loc);
|
||||
@@ -953,6 +963,14 @@ namespace {
|
||||
cSetRecentEmojisPreload(v);
|
||||
} break;
|
||||
|
||||
case dbiRecentStickers: {
|
||||
RecentStickerPreload v;
|
||||
stream >> v;
|
||||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
cSetRecentStickersPreload(v);
|
||||
} break;
|
||||
|
||||
case dbiEmojiVariants: {
|
||||
EmojiColorVariants v;
|
||||
stream >> v;
|
||||
@@ -1192,8 +1210,9 @@ namespace {
|
||||
|
||||
uint32 size = 11 * (sizeof(quint32) + sizeof(qint32));
|
||||
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath());
|
||||
size += sizeof(quint32) + sizeof(qint32) + cGetRecentEmojis().size() * (sizeof(uint64) + sizeof(ushort));
|
||||
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
|
||||
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
|
||||
size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort));
|
||||
size += sizeof(quint32) + _stringSize(cDialogLastPath());
|
||||
|
||||
EncryptedDescriptor data(size);
|
||||
@@ -1211,14 +1230,27 @@ namespace {
|
||||
data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab());
|
||||
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
|
||||
|
||||
RecentEmojisPreload v;
|
||||
v.reserve(cGetRecentEmojis().size());
|
||||
for (RecentEmojiPack::const_iterator i = cGetRecentEmojis().cbegin(), e = cGetRecentEmojis().cend(); i != e; ++i) {
|
||||
v.push_back(qMakePair(emojiKey(i->first), i->second));
|
||||
{
|
||||
RecentEmojisPreload v(cRecentEmojisPreload());
|
||||
if (v.isEmpty()) {
|
||||
v.reserve(cGetRecentEmojis().size());
|
||||
for (RecentEmojiPack::const_iterator i = cGetRecentEmojis().cbegin(), e = cGetRecentEmojis().cend(); i != e; ++i) {
|
||||
v.push_back(qMakePair(emojiKey(i->first), i->second));
|
||||
}
|
||||
}
|
||||
data.stream << quint32(dbiRecentEmojis) << v;
|
||||
}
|
||||
data.stream << quint32(dbiRecentEmojis) << v;
|
||||
|
||||
data.stream << quint32(dbiEmojiVariants) << cEmojiVariants();
|
||||
{
|
||||
RecentStickerPreload v(cRecentStickersPreload());
|
||||
if (v.isEmpty()) {
|
||||
v.reserve(cGetRecentStickers().size());
|
||||
for (RecentStickerPack::const_iterator i = cGetRecentStickers().cbegin(), e = cGetRecentStickers().cend(); i != e; ++i) {
|
||||
v.push_back(qMakePair(i->first->id, i->second));
|
||||
}
|
||||
}
|
||||
data.stream << quint32(dbiRecentStickers) << v;
|
||||
}
|
||||
|
||||
FileWriteDescriptor file(_userSettingsKey);
|
||||
file.writeEncrypted(data);
|
||||
@@ -1340,9 +1372,9 @@ namespace {
|
||||
|
||||
DraftsMap draftsMap, draftsPositionsMap;
|
||||
DraftsNotReadMap draftsNotReadMap;
|
||||
StorageMap imagesMap, stickersMap, audiosMap;
|
||||
StorageMap imagesMap, stickerImagesMap, audiosMap;
|
||||
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
|
||||
quint64 locationsKey = 0, recentStickersKey = 0, backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0;
|
||||
quint64 locationsKey = 0, recentStickersKeyOld = 0, stickersKey = 0, backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0;
|
||||
while (!map.stream.atEnd()) {
|
||||
quint32 keyType;
|
||||
map.stream >> keyType;
|
||||
@@ -1380,7 +1412,7 @@ namespace {
|
||||
storageImagesSize += size;
|
||||
}
|
||||
} break;
|
||||
case lskStickers: {
|
||||
case lskStickerImages: {
|
||||
quint32 count = 0;
|
||||
map.stream >> count;
|
||||
for (quint32 i = 0; i < count; ++i) {
|
||||
@@ -1388,7 +1420,7 @@ namespace {
|
||||
quint64 first, second;
|
||||
qint32 size;
|
||||
map.stream >> key >> first >> second >> size;
|
||||
stickersMap.insert(StorageKey(first, second), FileDesc(key, size));
|
||||
stickerImagesMap.insert(StorageKey(first, second), FileDesc(key, size));
|
||||
storageStickersSize += size;
|
||||
}
|
||||
} break;
|
||||
@@ -1407,8 +1439,8 @@ namespace {
|
||||
case lskLocations: {
|
||||
map.stream >> locationsKey;
|
||||
} break;
|
||||
case lskRecentStickers: {
|
||||
map.stream >> recentStickersKey;
|
||||
case lskRecentStickersOld: {
|
||||
map.stream >> recentStickersKeyOld;
|
||||
} break;
|
||||
case lskBackground: {
|
||||
map.stream >> backgroundKey;
|
||||
@@ -1419,6 +1451,9 @@ namespace {
|
||||
case lskRecentHashtags: {
|
||||
map.stream >> recentHashtagsKey;
|
||||
} break;
|
||||
case lskStickers: {
|
||||
map.stream >> stickersKey;
|
||||
} break;
|
||||
default:
|
||||
LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType));
|
||||
return Local::ReadMapFailed;
|
||||
@@ -1434,13 +1469,14 @@ namespace {
|
||||
|
||||
_imagesMap = imagesMap;
|
||||
_storageImagesSize = storageImagesSize;
|
||||
_stickersMap = stickersMap;
|
||||
_stickerImagesMap = stickerImagesMap;
|
||||
_storageStickersSize = storageStickersSize;
|
||||
_audiosMap = audiosMap;
|
||||
_storageAudiosSize = storageAudiosSize;
|
||||
|
||||
_locationsKey = locationsKey;
|
||||
_recentStickersKey = recentStickersKey;
|
||||
_recentStickersKeyOld = recentStickersKeyOld;
|
||||
_stickersKey = stickersKey;
|
||||
_backgroundKey = backgroundKey;
|
||||
_userSettingsKey = userSettingsKey;
|
||||
_recentHashtagsKey = recentHashtagsKey;
|
||||
@@ -1500,10 +1536,11 @@ namespace {
|
||||
if (!_draftsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsMap.size() * sizeof(quint64) * 2;
|
||||
if (!_draftsPositionsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsPositionsMap.size() * sizeof(quint64) * 2;
|
||||
if (!_imagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _imagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
if (!_stickersMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _stickersMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
if (!_stickerImagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _stickerImagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
if (!_audiosMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _audiosMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_recentStickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_recentStickersKeyOld) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_stickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_recentHashtagsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
@@ -1526,9 +1563,9 @@ namespace {
|
||||
mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second);
|
||||
}
|
||||
}
|
||||
if (!_stickersMap.isEmpty()) {
|
||||
mapData.stream << quint32(lskStickers) << quint32(_stickersMap.size());
|
||||
for (StorageMap::const_iterator i = _stickersMap.cbegin(), e = _stickersMap.cend(); i != e; ++i) {
|
||||
if (!_stickerImagesMap.isEmpty()) {
|
||||
mapData.stream << quint32(lskStickerImages) << quint32(_stickerImagesMap.size());
|
||||
for (StorageMap::const_iterator i = _stickerImagesMap.cbegin(), e = _stickerImagesMap.cend(); i != e; ++i) {
|
||||
mapData.stream << quint64(i.value().first) << quint64(i.key().first) << quint64(i.key().second) << qint32(i.value().second);
|
||||
}
|
||||
}
|
||||
@@ -1541,8 +1578,11 @@ namespace {
|
||||
if (_locationsKey) {
|
||||
mapData.stream << quint32(lskLocations) << quint64(_locationsKey);
|
||||
}
|
||||
if (_recentStickersKey) {
|
||||
mapData.stream << quint32(lskRecentStickers) << quint64(_recentStickersKey);
|
||||
if (_recentStickersKeyOld) {
|
||||
mapData.stream << quint32(lskRecentStickersOld) << quint64(_recentStickersKeyOld);
|
||||
}
|
||||
if (_stickersKey) {
|
||||
mapData.stream << quint32(lskStickers) << quint64(_stickersKey);
|
||||
}
|
||||
if (_backgroundKey) {
|
||||
mapData.stream << quint32(lskBackground) << quint64(_backgroundKey);
|
||||
@@ -1786,9 +1826,9 @@ namespace Local {
|
||||
_draftsPositionsMap.clear();
|
||||
_imagesMap.clear();
|
||||
_draftsNotReadMap.clear();
|
||||
_stickersMap.clear();
|
||||
_stickerImagesMap.clear();
|
||||
_audiosMap.clear();
|
||||
_locationsKey = _recentStickersKey = _backgroundKey = _userSettingsKey = _recentHashtagsKey = 0;
|
||||
_locationsKey = _recentStickersKeyOld = _stickersKey = _backgroundKey = _userSettingsKey = _recentHashtagsKey = 0;
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapNow);
|
||||
|
||||
@@ -1996,13 +2036,13 @@ namespace Local {
|
||||
if (_imagesMap.constFind(location) != _imagesMap.cend()) return;
|
||||
|
||||
QByteArray fmt = image->savedFormat();
|
||||
mtpTypeId format = 0;
|
||||
StorageFileType format = StorageFileUnknown;
|
||||
if (fmt == "JPG") {
|
||||
format = mtpc_storage_fileJpeg;
|
||||
format = StorageFileJpeg;
|
||||
} else if (fmt == "PNG") {
|
||||
format = mtpc_storage_filePng;
|
||||
format = StorageFilePng;
|
||||
} else if (fmt == "GIF") {
|
||||
format = mtpc_storage_fileGif;
|
||||
format = StorageFileGif;
|
||||
}
|
||||
if (format) {
|
||||
image->forget();
|
||||
@@ -2052,7 +2092,7 @@ namespace Local {
|
||||
quint32 imageType;
|
||||
draft.stream >> locFirst >> locSecond >> imageType >> imageData;
|
||||
|
||||
return (locFirst == location.first && locSecond == location.second) ? StorageImageSaved(imageType, imageData) : StorageImageSaved();
|
||||
return (locFirst == location.first && locSecond == location.second) ? StorageImageSaved(StorageFileType(imageType), imageData) : StorageImageSaved();
|
||||
}
|
||||
|
||||
int32 hasImages() {
|
||||
@@ -2063,13 +2103,13 @@ namespace Local {
|
||||
return _storageImagesSize;
|
||||
}
|
||||
|
||||
void writeSticker(const StorageKey &location, const QByteArray &sticker, bool overwrite) {
|
||||
void writeStickerImage(const StorageKey &location, const QByteArray &sticker, bool overwrite) {
|
||||
if (!_working()) return;
|
||||
|
||||
qint32 size = _storageStickerSize(sticker.size());
|
||||
StorageMap::const_iterator i = _stickersMap.constFind(location);
|
||||
if (i == _stickersMap.cend()) {
|
||||
i = _stickersMap.insert(location, FileDesc(genKey(UserPath), size));
|
||||
StorageMap::const_iterator i = _stickerImagesMap.constFind(location);
|
||||
if (i == _stickerImagesMap.cend()) {
|
||||
i = _stickerImagesMap.insert(location, FileDesc(genKey(UserPath), size));
|
||||
_storageStickersSize += size;
|
||||
_mapChanged = true;
|
||||
_writeMap();
|
||||
@@ -2083,20 +2123,20 @@ namespace Local {
|
||||
if (i.value().second != size) {
|
||||
_storageStickersSize += size;
|
||||
_storageStickersSize -= i.value().second;
|
||||
_stickersMap[location].second = size;
|
||||
_stickerImagesMap[location].second = size;
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray readSticker(const StorageKey &location) {
|
||||
StorageMap::iterator j = _stickersMap.find(location);
|
||||
if (j == _stickersMap.cend()) {
|
||||
QByteArray readStickerImage(const StorageKey &location) {
|
||||
StorageMap::iterator j = _stickerImagesMap.find(location);
|
||||
if (j == _stickerImagesMap.cend()) {
|
||||
return QByteArray();
|
||||
}
|
||||
FileReadDescriptor draft;
|
||||
if (!readEncryptedFile(draft, j.value().first, UserPath)) {
|
||||
clearKey(j.value().first, UserPath);
|
||||
_storageStickersSize -= j.value().second;
|
||||
_stickersMap.erase(j);
|
||||
_stickerImagesMap.erase(j);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
@@ -2108,7 +2148,7 @@ namespace Local {
|
||||
}
|
||||
|
||||
int32 hasStickers() {
|
||||
return _stickersMap.size();
|
||||
return _stickerImagesMap.size();
|
||||
}
|
||||
|
||||
qint64 storageStickersSize() {
|
||||
@@ -2167,56 +2207,91 @@ namespace Local {
|
||||
return _storageAudiosSize;
|
||||
}
|
||||
|
||||
void writeRecentStickers() {
|
||||
void writeStickers() {
|
||||
if (!_working()) return;
|
||||
|
||||
const RecentStickerPack &recent(cRecentStickers());
|
||||
if (recent.isEmpty()) {
|
||||
if (_recentStickersKey) {
|
||||
clearKey(_recentStickersKey);
|
||||
_recentStickersKey = 0;
|
||||
|
||||
const StickerSets &sets(cStickerSets());
|
||||
if (sets.isEmpty()) {
|
||||
if (_stickersKey) {
|
||||
clearKey(_stickersKey);
|
||||
_stickersKey = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
_writeMap();
|
||||
} else {
|
||||
if (!_recentStickersKey) {
|
||||
_recentStickersKey = genKey();
|
||||
if (!_stickersKey) {
|
||||
_stickersKey = genKey();
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapFast);
|
||||
}
|
||||
quint32 size = 0;
|
||||
for (RecentStickerPack::const_iterator i = recent.cbegin(); i != recent.cend(); ++i) {
|
||||
DocumentData *doc = i->first;
|
||||
if (doc->status == FileFailed) continue;
|
||||
quint32 size = sizeof(quint32) + _bytearraySize(cStickersHash());
|
||||
for (StickerSets::const_iterator i = sets.cbegin(); i != sets.cend(); ++i) {
|
||||
if (i->stickers.isEmpty()) continue;
|
||||
|
||||
// id + value + access + date + namelen + name + mimelen + mime + dc + size + width + height + type + alt
|
||||
size += sizeof(quint64) + sizeof(qint16) + sizeof(quint64) + sizeof(qint32) + _stringSize(doc->name) + _stringSize(doc->mime) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + _stringSize(doc->sticker ? doc->sticker->alt : QString());
|
||||
// id + access + title + shortName + stickersCount
|
||||
size += sizeof(quint64) * 2 + _stringSize(i->title) + _stringSize(i->shortName) + sizeof(quint32);
|
||||
for (StickerPack::const_iterator j = i->stickers.cbegin(), e = i->stickers.cend(); j != e; ++j) {
|
||||
DocumentData *doc = *j;
|
||||
|
||||
// id + access + date + namelen + name + mimelen + mime + dc + size + width + height + type + alt + type-of-set
|
||||
size += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + _stringSize(doc->name) + _stringSize(doc->mime) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + _stringSize(doc->sticker->alt) + sizeof(qint32);
|
||||
|
||||
// thumb-width + thumb-height + thumb-dc + thumb-volume + thumb-local + thumb-secret
|
||||
size += sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint64) + sizeof(qint32) + sizeof(quint64);
|
||||
}
|
||||
}
|
||||
EncryptedDescriptor data(size);
|
||||
for (RecentStickerPack::const_iterator i = recent.cbegin(); i != recent.cend(); ++i) {
|
||||
DocumentData *doc = i->first;
|
||||
if (doc->status == FileFailed) continue;
|
||||
data.stream << quint32(sets.size()) << cStickersHash();
|
||||
for (StickerSets::const_iterator i = sets.cbegin(); i != sets.cend(); ++i) {
|
||||
if (i->stickers.isEmpty()) continue;
|
||||
|
||||
data.stream << quint64(doc->id) << qint16(i->second) << quint64(doc->access) << qint32(doc->date) << doc->name << doc->mime << qint32(doc->dc) << qint32(doc->size) << qint32(doc->dimensions.width()) << qint32(doc->dimensions.height()) << qint32(doc->type) << (doc->sticker ? doc->sticker->alt : QString());
|
||||
data.stream << quint64(i->id) << quint64(i->access) << i->title << i->shortName << quint32(i->stickers.size());
|
||||
for (StickerPack::const_iterator j = i->stickers.cbegin(), e = i->stickers.cend(); j != e; ++j) {
|
||||
DocumentData *doc = *j;
|
||||
data.stream << quint64(doc->id) << quint64(doc->access) << qint32(doc->date) << doc->name << doc->mime << qint32(doc->dc) << qint32(doc->size) << qint32(doc->dimensions.width()) << qint32(doc->dimensions.height()) << qint32(doc->type) << doc->sticker->alt;
|
||||
switch (doc->sticker->set.type()) {
|
||||
case mtpc_inputStickerSetID: {
|
||||
data.stream << qint32(StickerSetTypeID);
|
||||
} break;
|
||||
case mtpc_inputStickerSetShortName: {
|
||||
data.stream << qint32(StickerSetTypeShortName);
|
||||
} break;
|
||||
case mtpc_inputStickerSetEmpty:
|
||||
default: {
|
||||
data.stream << qint32(StickerSetTypeEmpty);
|
||||
} break;
|
||||
}
|
||||
const StorageImageLocation &loc(doc->sticker->loc);
|
||||
data.stream << qint32(loc.width) << qint32(loc.height) << qint32(loc.dc) << quint64(loc.volume) << qint32(loc.local) << quint64(loc.secret);
|
||||
}
|
||||
}
|
||||
FileWriteDescriptor file(_recentStickersKey);
|
||||
FileWriteDescriptor file(_stickersKey);
|
||||
file.writeEncrypted(data);
|
||||
}
|
||||
}
|
||||
|
||||
void readRecentStickers() {
|
||||
if (!_recentStickersKey) return;
|
||||
void importOldRecentStickers() {
|
||||
if (!_recentStickersKeyOld) return;
|
||||
|
||||
FileReadDescriptor stickers;
|
||||
if (!readEncryptedFile(stickers, _recentStickersKey)) {
|
||||
clearKey(_recentStickersKey);
|
||||
_recentStickersKey = 0;
|
||||
if (!readEncryptedFile(stickers, _recentStickersKeyOld)) {
|
||||
clearKey(_recentStickersKeyOld);
|
||||
_recentStickersKeyOld = 0;
|
||||
_writeMap();
|
||||
return;
|
||||
}
|
||||
|
||||
StickerSets &sets(cRefStickerSets());
|
||||
sets.clear();
|
||||
RecentStickerPack &recent(cRefRecentStickers());
|
||||
recent.clear();
|
||||
|
||||
cSetStickersHash(QByteArray());
|
||||
|
||||
StickerSet &def(sets.insert(DefaultStickerSetId, StickerSet(DefaultStickerSetId, 0, qsl("Great Minds"), QString())).value());
|
||||
StickerSet &custom(sets.insert(CustomStickerSetId, StickerSet(CustomStickerSetId, 0, lang(lng_custom_stickers), QString())).value());
|
||||
|
||||
QMap<uint64, bool> read;
|
||||
RecentStickerPack recent;
|
||||
while (!stickers.stream.atEnd()) {
|
||||
quint64 id, access;
|
||||
QString name, mime, alt;
|
||||
@@ -2226,7 +2301,7 @@ namespace Local {
|
||||
if (stickers.version >= 7021) {
|
||||
stickers.stream >> alt;
|
||||
}
|
||||
if (read.contains(id)) continue;
|
||||
if (!value || read.contains(id)) continue;
|
||||
read.insert(id, true);
|
||||
|
||||
QVector<MTPDocumentAttribute> attributes;
|
||||
@@ -2240,10 +2315,109 @@ namespace Local {
|
||||
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
|
||||
}
|
||||
|
||||
recent.push_back(qMakePair(App::document(id, 0, access, date, attributes, mime, ImagePtr(), dc, size), value));
|
||||
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, ImagePtr(), dc, size, StorageImageLocation());
|
||||
if (!doc->sticker) continue;
|
||||
|
||||
if (value > 0) {
|
||||
def.stickers.push_back(doc);
|
||||
} else {
|
||||
custom.stickers.push_back(doc);
|
||||
}
|
||||
if (recent.size() < StickerPanPerRow * StickerPanRowsPerPage && qAbs(value) > 1) recent.push_back(qMakePair(doc, qAbs(value)));
|
||||
}
|
||||
if (def.stickers.isEmpty()) sets.remove(DefaultStickerSetId);
|
||||
if (custom.stickers.isEmpty()) sets.remove(CustomStickerSetId);
|
||||
|
||||
writeStickers();
|
||||
writeUserSettings();
|
||||
|
||||
clearKey(_recentStickersKeyOld);
|
||||
_recentStickersKeyOld = 0;
|
||||
_writeMap();
|
||||
}
|
||||
|
||||
void readStickers() {
|
||||
if (!_stickersKey) {
|
||||
return importOldRecentStickers();
|
||||
}
|
||||
|
||||
cSetRecentStickers(recent);
|
||||
FileReadDescriptor stickers;
|
||||
if (!readEncryptedFile(stickers, _stickersKey)) {
|
||||
clearKey(_stickersKey);
|
||||
_stickersKey = 0;
|
||||
_writeMap();
|
||||
return;
|
||||
}
|
||||
|
||||
StickerSets &sets(cRefStickerSets());
|
||||
sets.clear();
|
||||
|
||||
quint32 cnt;
|
||||
QByteArray hash;
|
||||
stickers.stream >> cnt >> hash;
|
||||
for (int32 i = 0; i < cnt; ++i) {
|
||||
quint64 setId = 0, setAccess = 0;
|
||||
QString setTitle, setShortName;
|
||||
quint32 scnt = 0;
|
||||
stickers.stream >> setId >> setAccess >> setTitle >> setShortName >> scnt;
|
||||
|
||||
if (setId == DefaultStickerSetId) {
|
||||
setTitle = qsl("Great Minds");
|
||||
} else if (setId == CustomStickerSetId) {
|
||||
setTitle = lang(lng_custom_stickers);
|
||||
}
|
||||
StickerSet &set(sets.insert(setId, StickerSet(setId, setAccess, setTitle, setShortName)).value());
|
||||
set.stickers.reserve(scnt);
|
||||
|
||||
QMap<uint64, bool> read;
|
||||
for (int32 j = 0; j < scnt; ++j) {
|
||||
quint64 id, access;
|
||||
QString name, mime, alt;
|
||||
qint32 date, dc, size, width, height, type, typeOfSet;
|
||||
stickers.stream >> id >> access >> date >> name >> mime >> dc >> size >> width >> height >> type >> alt >> typeOfSet;
|
||||
|
||||
qint32 thumbWidth, thumbHeight, thumbDc, thumbLocal;
|
||||
quint64 thumbVolume, thumbSecret;
|
||||
stickers.stream >> thumbWidth >> thumbHeight >> thumbDc >> thumbVolume >> thumbLocal >> thumbSecret;
|
||||
|
||||
if (read.contains(id)) continue;
|
||||
read.insert(id, true);
|
||||
|
||||
if (setId == DefaultStickerSetId || setId == CustomStickerSetId) {
|
||||
typeOfSet = StickerSetTypeEmpty;
|
||||
}
|
||||
|
||||
QVector<MTPDocumentAttribute> attributes;
|
||||
if (!name.isEmpty()) attributes.push_back(MTP_documentAttributeFilename(MTP_string(name)));
|
||||
if (type == AnimatedDocument) {
|
||||
attributes.push_back(MTP_documentAttributeAnimated());
|
||||
} else if (type == StickerDocument) {
|
||||
switch (typeOfSet) {
|
||||
case StickerSetTypeID: {
|
||||
attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetID(MTP_long(setId), MTP_long(setAccess))));
|
||||
} break;
|
||||
case StickerSetTypeShortName: {
|
||||
attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetShortName(MTP_string(setShortName))));
|
||||
} break;
|
||||
case StickerSetTypeEmpty:
|
||||
default: {
|
||||
attributes.push_back(MTP_documentAttributeSticker(MTP_string(alt), MTP_inputStickerSetEmpty()));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
if (width > 0 && height > 0) {
|
||||
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
|
||||
}
|
||||
|
||||
StorageImageLocation thumb(thumbWidth, thumbHeight, thumbDc, thumbVolume, thumbLocal, thumbSecret);
|
||||
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, thumb.dc ? ImagePtr(thumb) : ImagePtr(), dc, size, thumb);
|
||||
if (!doc->sticker) continue;
|
||||
|
||||
set.stickers.push_back(doc);
|
||||
}
|
||||
}
|
||||
|
||||
cSetStickersHash(hash);
|
||||
}
|
||||
|
||||
void writeBackground(int32 id, const QImage &img) {
|
||||
@@ -2412,8 +2586,8 @@ namespace Local {
|
||||
_storageImagesSize = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (!_stickersMap.isEmpty()) {
|
||||
_stickersMap.clear();
|
||||
if (!_stickerImagesMap.isEmpty()) {
|
||||
_stickerImagesMap.clear();
|
||||
_storageStickersSize = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
@@ -2434,8 +2608,12 @@ namespace Local {
|
||||
_locationsKey = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (_recentStickersKey) {
|
||||
_recentStickersKey = 0;
|
||||
if (_recentStickersKeyOld) {
|
||||
_recentStickersKeyOld = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (_stickersKey) {
|
||||
_stickersKey = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (_recentHashtagsKey) {
|
||||
@@ -2462,9 +2640,9 @@ namespace Local {
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (data->stickers.isEmpty()) {
|
||||
data->stickers = _stickersMap;
|
||||
data->stickers = _stickerImagesMap;
|
||||
} else {
|
||||
for (StorageMap::const_iterator i = _stickersMap.cbegin(), e = _stickersMap.cend(); i != e; ++i) {
|
||||
for (StorageMap::const_iterator i = _stickerImagesMap.cbegin(), e = _stickerImagesMap.cend(); i != e; ++i) {
|
||||
StorageKey k = i.key();
|
||||
while (data->stickers.constFind(k) != data->stickers.cend()) {
|
||||
++k.second;
|
||||
@@ -2472,8 +2650,8 @@ namespace Local {
|
||||
data->stickers.insert(k, i.value());
|
||||
}
|
||||
}
|
||||
if (!_stickersMap.isEmpty()) {
|
||||
_stickersMap.clear();
|
||||
if (!_stickerImagesMap.isEmpty()) {
|
||||
_stickerImagesMap.clear();
|
||||
_storageStickersSize = 0;
|
||||
_mapChanged = true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user